SKlearn MLP Regressor预测值持续为零问题求助
时间序列回归预测问题:MLP输出全零修复与替代模型推荐
一、MLP预测值全零的修复方案
1. 核心问题定位
代码存在三个关键问题导致预测值为零:
- 时间特征处理错误:直接将
datetime对象的numpy数组作为输入特征,MLP无法有效处理该类型输入,必须转换为数值型时间差。 - 目标变量未做尺度归一化:仅标准化输入特征而忽略目标变量,MLP对尺度敏感,容易收敛到全局均值或零值。
- MLP默认参数未适配回归任务:默认迭代次数不足、网络结构简单,模型未充分收敛。
2. 修改后的完整代码
import json import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.neural_network import MLPRegressor from sklearn.preprocessing import RobustScaler from sklearn.impute import SimpleImputer # 加载训练数据 with open('data.json', 'r') as file: data = json.load(file) df = pd.DataFrame(data) # 正确转换时间特征:计算与训练集最早时间的秒数差 df['periodFrom'] = pd.to_datetime(df['periodFrom']) min_time = df['periodFrom'].min() df['periodFrom_numeric'] = (df['periodFrom'] - min_time).dt.total_seconds() # 缺失值处理 imputer = SimpleImputer(strategy='mean') df['value'] = imputer.fit_transform(df[['value']]) # 拆分特征与目标 X_train = df['periodFrom_numeric'].values.reshape(-1, 1) y_train = df['value'].values # 加载新数据 with open('new_data_json.json', 'r') as file: new_data = json.load(file) new_df = pd.DataFrame(new_data) # 新数据时间特征转换:使用训练集的最早时间作为基准 new_df['periodFrom'] = pd.to_datetime(new_df['periodFrom']) new_df['periodFrom_numeric'] = (new_df['periodFrom'] - min_time).dt.total_seconds() new_df['value'] = imputer.transform(new_df[['value']]) X_new = new_df['periodFrom_numeric'].values.reshape(-1, 1) # 标准化输入特征与目标变量 scaler_X = RobustScaler() X_train_scaled = scaler_X.fit_transform(X_train) X_new_scaled = scaler_X.transform(X_new) scaler_y = RobustScaler() y_train_scaled = scaler_y.fit_transform(y_train.reshape(-1, 1)).ravel() # 构建适配回归任务的MLP模型 model = MLPRegressor( hidden_layer_sizes=(64, 32), activation='relu', solver='adam', max_iter=1000, random_state=42, early_stopping=True, validation_fraction=0.1 ) model.fit(X_train_scaled, y_train_scaled) # 预测并逆变换回原始尺度 predictions_scaled = model.predict(X_new_scaled).reshape(-1, 1) predictions = scaler_y.inverse_transform(predictions_scaled) # 可视化 plt.figure(figsize=(10, 6)) plt.scatter(df['periodFrom'], df['value'], label='训练集实际值', marker='o') plt.scatter(new_df['periodFrom'], predictions, label='MLP预测值', marker='o', color="green") plt.scatter(new_df['periodFrom'], new_df['value'], label='测试集实际值', marker="o", color="red") plt.xlabel('时间周期') plt.ylabel('流量值') plt.title('实际值与预测值对比') plt.legend() plt.grid(True) plt.xticks(rotation=45) plt.tight_layout() plt.show()
二、替代模型推荐
ARIMA残差过大说明数据可能存在非线性趋势或强季节性,以下模型更适配你的能源流量时间序列:
1. 梯度提升树(XGBoost/LightGBM)
树模型对非线性模式、异常值鲁棒性强,无需数据平稳性假设,可直接处理时间特征:
import lightgbm as lgb # 训练模型 model_lgb = lgb.LGBMRegressor(n_estimators=500, learning_rate=0.05, random_state=42) model_lgb.fit(X_train, y_train) # 预测 predictions_lgb = model_lgb.predict(X_new)
2. Prophet(Facebook开源工具)
专门针对时间序列设计,自动捕捉趋势、年/周/日季节性,配置简单:
from prophet import Prophet # 转换为Prophet要求的格式 prophet_train = df.rename(columns={'periodFrom': 'ds', 'value': 'y'})[['ds', 'y']] prophet_test = new_df.rename(columns={'periodFrom': 'ds'})[['ds']] # 训练与预测 model_prophet = Prophet(yearly_seasonality=True, weekly_seasonality=True, daily_seasonality=True) model_prophet.fit(prophet_train) forecast = model_prophet.predict(prophet_test) predictions_prophet = forecast['yhat'].values
3. LSTM(循环神经网络)
适合捕捉时间序列的长期依赖关系,对周期性流量数据效果优异:
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense # 转换为序列输入格式(示例:用前3个时间步预测当前值) def create_sequences(data, seq_length=3): X, y = [], [] for i in range(len(data)-seq_length): X.append(data[i:i+seq_length]) y.append(data[i+seq_length]) return np.array(X), np.array(y) # 准备序列数据 seq_X_train, seq_y_train = create_sequences(df['value'].values) seq_X_train = seq_X_train.reshape(seq_X_train.shape[0], seq_X_train.shape[1], 1) # 构建LSTM模型 model_lstm = Sequential() model_lstm.add(LSTM(50, activation='relu', input_shape=(3, 1))) model_lstm.add(Dense(1)) model_lstm.compile(optimizer='adam', loss='mse') model_lstm.fit(seq_X_train, seq_y_train, epochs=50, batch_size=32)
内容的提问来源于stack exchange,提问作者Boyan
相关产品推荐
相关产品推荐

