From 6e5172962a32b5c65d6bbe00cb5aac58e1056ab9 Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Sat, 9 Nov 2024 00:19:12 +0800 Subject: [PATCH] Fix bugs --- src/data_preparation.py | 31 +++++++++++++++++++++++-------- src/model_trainer.py | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/data_preparation.py b/src/data_preparation.py index 2d60f6d..ea9e47a 100644 --- a/src/data_preparation.py +++ b/src/data_preparation.py @@ -121,7 +121,6 @@ class DataPreparation: if scalers and 'feature_scaler' in scalers: X_scaled = scalers['feature_scaler'].transform(X) else: - # 如果没有提供标准化器,直接返回处理后的数组 X_scaled = X logging.info(f"Preprocessed data shape: {X_scaled.shape}") @@ -133,11 +132,10 @@ class DataPreparation: 'y': None # 验证数据可能没有标签 } - # 否则,从原始数据中提取特征 + # 从原始数据中提取特征和目标值 if not feature_names: feature_names = self.feature_analyzer.get_equipment_specific_features(equipment_type) - # 提取特征和目标值 features = [] targets = [] @@ -149,12 +147,17 @@ class DataPreparation: try: feature_values.append(float(value) if value is not None else 0.0) except (ValueError, TypeError): - feature_values.append(0.0) # 使用0替代NaN + feature_values.append(0.0) features.append(feature_values) - # 提取目标值(成本) + # 提取目标值(成本)并验证范围 try: - targets.append(float(item['actual_cost'])) + cost = float(item['actual_cost']) + logging.info(f"Raw cost value: {cost}") + if cost > 0: # 只使用正数成本值 + targets.append(cost) + else: + logging.warning(f"Skipping non-positive cost value: {cost}") except (ValueError, TypeError): logging.error(f"Invalid cost value: {item.get('actual_cost')}") continue @@ -163,23 +166,35 @@ class DataPreparation: X = np.array(features, dtype=float) y = np.array(targets, dtype=float) + # 记录数据范围 + logging.info(f"Features range: min={X.min()}, max={X.max()}") + logging.info(f"Targets range: min={y.min()}, max={y.max()}") + # 处理无效值 X = np.nan_to_num(X, nan=0.0, posinf=0.0, neginf=0.0) # 使用训练数据的标准化器 if scalers and 'feature_scaler' in scalers: X_scaled = scalers['feature_scaler'].transform(X) + if 'target_scaler' in scalers: + y_scaled = scalers['target_scaler'].transform(y.reshape(-1, 1)).ravel() + else: + y_scaled = y else: - # 如果没有提供标准化器,直接返回处理后的数组 X_scaled = X + y_scaled = y logging.info(f"Preprocessed data shape: {X_scaled.shape}") logging.info(f"Validation features shape: {X_scaled.shape}") logging.info(f"Validation features type: {X_scaled.dtype}") + # 记录标准化后的数据范围 + logging.info(f"Scaled validation X range: min={X_scaled.min()}, max={X_scaled.max()}") + logging.info(f"Scaled validation y range: min={y_scaled.min()}, max={y_scaled.max()}") + return { 'X': X_scaled, - 'y': y # 返回原始成本值 + 'y': y_scaled # 返回标准化后的成本值 } except Exception as e: diff --git a/src/model_trainer.py b/src/model_trainer.py index b6601d8..94a5d70 100644 --- a/src/model_trainer.py +++ b/src/model_trainer.py @@ -111,19 +111,43 @@ class ModelTrainer: # 训练集评估 train_pred = model.predict(X_train) + + # 如果使用了标准化,需要转换回原始范围 + if hasattr(self, 'target_scaler'): + train_pred = self.target_scaler.inverse_transform(train_pred.reshape(-1, 1)).ravel() + y_train_orig = self.target_scaler.inverse_transform(y_train.reshape(-1, 1)).ravel() + else: + y_train_orig = y_train + + # 记录预测范围 + logging.info(f"Train predictions range: min={train_pred.min()}, max={train_pred.max()}") + logging.info(f"Train actual range: min={y_train_orig.min()}, max={y_train_orig.max()}") + train_metrics = { - 'r2': r2_score(y_train, train_pred), - 'mae': mean_absolute_error(y_train, train_pred), - 'rmse': np.sqrt(mean_squared_error(y_train, train_pred)) + 'r2': r2_score(y_train_orig, train_pred), + 'mae': mean_absolute_error(y_train_orig, train_pred), + 'rmse': np.sqrt(mean_squared_error(y_train_orig, train_pred)) } # 验证集评估 if X_val is not None and y_val is not None: val_pred = model.predict(X_val) + + # 如果使用了标准化,需要转换回原始范围 + if hasattr(self, 'target_scaler'): + val_pred = self.target_scaler.inverse_transform(val_pred.reshape(-1, 1)).ravel() + y_val_orig = self.target_scaler.inverse_transform(y_val.reshape(-1, 1)).ravel() + else: + y_val_orig = y_val + + # 记录预测范围 + logging.info(f"Validation predictions range: min={val_pred.min()}, max={val_pred.max()}") + logging.info(f"Validation actual range: min={y_val_orig.min()}, max={y_val_orig.max()}") + val_metrics = { - 'r2': r2_score(y_val, val_pred), - 'mae': mean_absolute_error(y_val, val_pred), - 'rmse': np.sqrt(mean_squared_error(y_val, val_pred)) + 'r2': r2_score(y_val_orig, val_pred), + 'mae': mean_absolute_error(y_val_orig, val_pred), + 'rmse': np.sqrt(mean_squared_error(y_val_orig, val_pred)) } else: # 使用交叉验证 @@ -285,7 +309,7 @@ class ModelTrainer: try: logging.info(f"Loading model for {equipment_type}") - # 从数据库获��最新的激活模型 + # 从数据库获最新的激活模型 with get_db_connection() as conn: cursor = conn.cursor(dictionary=True) cursor.execute("""