MinMaxScaler逆变换后test_X原始数据异常问题求助
问题分析与解决方案
核心错误原因
- 训练数据未用缩放后的数据:你第一步对整个数据集做了
fit_transform得到scaled,但后续划分训练/测试集时直接用了原始的values,导致模型练的是未缩放的原始数据,和scaler的拟合逻辑完全脱节。 - 逆变换列顺序不匹配:原始数据集列顺序是
[0,1,2,3,4],第2列是目标列。但你拼接预测值/真实值和test_X时用了np.concatenate((yhat, test_X), axis=1),得到的列顺序是[y,0,1,3,4],和scaler拟合时的列顺序对不上,逆变换时scaler会按原始列的缩放规则处理,直接导致数据错位、结果错误。 - 没备份原始test_X:逆变换前你修改了
test_X的形状,还没存副本,后续操作很容易搞混数据。
修正后的完整代码步骤
1. 读取数据并正确缩放
dataset = read_csv('zz.csv', header=0, index_col=0) values = dataset.values scaler = MinMaxScaler(feature_range=(0, 1)) # 对整个数据集做拟合+缩放,得到缩放后的数组 scaled = scaler.fit_transform(values)
2. 划分训练/测试集(用缩放后的数据)
train = scaled[:168, :] test = scaled[168:, :] # 从缩放后的数据里提取特征列和目标列 train_X, train_y = train[:, [0,1,3,4]], train[:, 2] test_X, test_y = test[:, [0,1,3,4]], test[:, 2] # 调整形状适配LSTM输入 train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1])) test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1])) # 备份缩放后的test_X,避免后续修改影响逆变换 test_X_original = test_X.reshape((test_X.shape[0], test_X.shape[2]))
3. 构建并训练LSTM模型(这部分不用改)
# design network model = Sequential() model.add(LSTM(4, return_sequences=True, activation="relu", input_shape=(train_X.shape[1], train_X.shape[2]))) model.add(LSTM(16, return_sequences=False, activation="relu")) model.add(Dense(1)) nadam = tf.keras.optimizers.Nadam(learning_rate=0.0005, beta_1=0.9, beta_2=0.999, epsilon=1e-07) model.compile(loss='mae', optimizer=nadam, metrics=[tf.keras.metrics.MeanSquaredError()]) stop_early = tf.keras.callbacks.EarlyStopping(monitor='val_mean_squared_error', patience=5) history = model.fit(train_X, train_y, epochs=2000, verbose=1, validation_split=0.2, shuffle=False, callbacks=[stop_early])
4. 预测并正确逆变换
# 预测 yhat = model.predict(test_X) yhat = yhat.reshape(yhat.shape[0], 1) # ------------------- 逆变换预测值 ------------------- # 构造和原始数据集列顺序一致的数组:[0,1,yhat,3,4] inv_yhat_array = np.zeros((len(yhat), 5)) inv_yhat_array[:, 0] = test_X_original[:, 0] inv_yhat_array[:, 1] = test_X_original[:, 1] inv_yhat_array[:, 2] = yhat[:, 0] inv_yhat_array[:, 3] = test_X_original[:, 2] inv_yhat_array[:, 4] = test_X_original[:, 3] # 逆变换后提取目标列 inv_yhat = scaler.inverse_transform(inv_yhat_array)[:, 2] # ------------------- 逆变换真实值 ------------------- # 构造和原始数据集列顺序一致的数组:[0,1,test_y,3,4] inv_y_array = np.zeros((len(test_y), 5)) inv_y_array[:, 0] = test_X_original[:, 0] inv_y_array[:, 1] = test_X_original[:, 1] inv_y_array[:, 2] = test_y[:] inv_y_array[:, 3] = test_X_original[:, 2] inv_y_array[:, 4] = test_X_original[:, 3] # 逆变换后提取目标列 inv_y = scaler.inverse_transform(inv_y_array)[:, 2]
额外优化建议
为了避免数据泄露,建议仅用训练集拟合scaler,再缩放训练集和测试集,修改第一步和第二步如下:
# 先划分原始数据的训练/测试集 train_values = values[:168, :] test_values = values[168:, :] # 仅用训练集拟合scaler,再分别缩放训练集和测试集 scaler = MinMaxScaler(feature_range=(0, 1)) train_scaled = scaler.fit_transform(train_values) test_scaled = scaler.transform(test_values) # 后续提取特征和目标列直接用train_scaled和test_scaled即可
内容的提问来源于stack exchange,提问作者Betabore
相关产品推荐
相关产品推荐

