You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多变量时间序列预测:测试集归一化报错求助

问题分析与解决方案

错误原因

你遇到的ValueError核心是训练集和测试集的特征数量不匹配:

  • 合并后的训练集包含28个监测站特征(来自train.csv)+10个气象特征(来自weather.csv),共38个数值特征(排除date列),因此scaler.fit()是基于38个特征计算的归一化参数。
  • 但合并后的测试集只有10个气象特征(因为test.csv本身只有date列,没有任何监测站数据),用同一个scaler转换时,特征数从38变为10,自然触发不匹配报错。

解决方案

要解决这个问题,需要调整数据预处理和预测逻辑——测试阶段没有历史监测站数据,需要用训练集的末尾序列初始化预测,再滚动生成后续的监测站数据。以下是修正后的完整代码:

import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

# 加载数据集
train_df = pd.read_csv("train.csv")
weather_df = pd.read_csv("weather.csv")
test_df = pd.read_csv("test.csv")

# 合并数据集
merged_df = pd.merge(train_df, weather_df, on="date", how="inner")
merged_test_df = pd.merge(test_df, weather_df, on="date", how="inner")

# 整理训练数据(按日期排序)
train_data = merged_df.sort_values("date")
test_dates = merged_test_df["date"].values
test_weather = merged_test_df.drop("date", axis=1).values

# 归一化所有特征(28个监测站 + 10个气象 = 38个特征)
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_train = scaler.fit_transform(train_data.drop("date", axis=1))

# 定义窗口大小
window_size = 30

# 构建训练序列:输入是30天的完整数据,目标是下一天的监测站数据
train_X, train_y = [], []
for i in range(window_size, len(scaled_train)):
    train_X.append(scaled_train[i-window_size:i])  # 形状: (30, 38)
    train_y.append(scaled_train[i, :28])  # 目标是前28列(监测站数据)
train_X = np.array(train_X)
train_y = np.array(train_y)

# 搭建LSTM模型
model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(LSTM(50))
model.add(Dense(28))  # 输出28个监测站特征
model.compile(loss='mean_squared_error', optimizer='adam')

# 训练模型
model.fit(train_X, train_y, epochs=100, batch_size=32, verbose=1)

# --- 测试集预测逻辑 ---
# 用训练集的最后30天数据初始化预测序列
current_sequence = scaled_train[-window_size:]
predictions = []

for _ in range(len(test_weather)):
    # 调整序列形状适配模型输入
    input_seq = current_sequence.reshape(1, window_size, 38)
    # 预测当天的监测站数据
    pred_station = model.predict(input_seq, verbose=0)
    # 对当天的气象数据做归一化(构造dummy数组匹配scaler的38特征要求)
    dummy_station = np.zeros((1,28))
    scaled_weather = scaler.transform(np.hstack([dummy_station, test_weather[_].reshape(1,10)]))[:, 28:]
    # 拼接预测的监测站数据和归一化后的气象数据,形成下一个序列步
    next_step = np.hstack([pred_station, scaled_weather])
    # 保存预测结果
    predictions.append(pred_station[0])
    # 更新序列:移除最早的一步,加入新生成的步
    current_sequence = np.vstack([current_sequence[1:], next_step])

# 反归一化预测结果,得到真实数值
dummy_weather = np.zeros((len(predictions), 10))
pred_full = np.hstack([predictions, dummy_weather])
pred_actual = scaler.inverse_transform(pred_full)[:, :28]

# 保存预测结果到CSV
pred_df = pd.DataFrame(pred_actual, columns=train_df.columns[1:])
pred_df.insert(0, "date", test_dates)
pred_df.to_csv("predictions.csv", index=False)

关键调整点

  1. 明确目标变量:训练时只预测28个监测站特征,模型输出层改为Dense(28),聚焦核心预测目标。
  2. 滚动预测逻辑:测试阶段用训练集的最后30天数据初始化序列,每预测出一天的监测站数据后,和当天的气象数据拼接,作为下一次预测的输入序列,解决无历史监测数据的问题。
  3. 归一化适配:对测试集的气象数据单独做归一化时,通过构造包含dummy监测站数据的数组,匹配scaler的38个特征输入要求,确保归一化逻辑一致。

内容的提问来源于stack exchange,提问作者Moe_blg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 03:25:08