LSTM多变量预测模型输入维度不兼容错误排查求助
问题
编写了一个LSTM多属性预测模型,目标是在同一模型中预测rain、humidity、pressure三个指标,但训练时出现以下错误:
ValueError: Exception encountered when calling layer 'sequential' (type Sequential)
具体提示:Input 0 of layer "lstm_2" is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: (32, 10)
已知输入张量形状为(32, 30, 3),明确是LSTM输入维度冲突问题(应为3维而非2维),但不清楚错误来源,请求排查。完整代码如下:
import logging logging.getLogger("tensorflow").setLevel(logging.ERROR) import numpy as np import matplotlib.pyplot as mplt import pandas as pd import tensorflow as tf df = pd.read_csv('D:/ĐỒ ÁN TRÍ TUỆ NHÂN TẠO/HCM_weather.csv') #print(df.head(10)) dataset = df[['rain' , 'humidi', 'pressure' ,'date']] dataset.set_index('date', inplace=True) dataset = dataset.reset_index(drop=True) training_set = dataset.iloc[:, [0,1,2]].values #print(training_set[:10]) from sklearn.preprocessing import MinMaxScaler sc = MinMaxScaler(feature_range=(0, 1)) training_set_scaled = sc.fit_transform(training_set) #print(training_set_scaled[:10]) x_train = [] y_train = [] n_future = 4 # Dự báo độ ẩm 4 ngày tới n_past = 30 # 30 ngày trước for i in range(n_past, len(training_set_scaled) - n_future +1): x_train.append(training_set_scaled[i - n_past:i, :]) y_train.append(training_set_scaled[i:i + n_future, :]) x_train, y_train = np.array(x_train), np.array(y_train) from keras.models import Sequential from keras.layers import LSTM, Dense, Dropout, Bidirectional regressor = Sequential() regressor.add(Bidirectional(LSTM(units=64, return_sequences=True, input_shape=(n_past, dataset.shape[1])))) regressor.add(Dropout(0.25)) regressor.add(LSTM(units=10, return_sequences=False)) regressor.add(Dropout(0.25)) regressor.add(LSTM(units=10, return_sequences=False)) regressor.add(Dropout(0.25)) regressor.add(LSTM(units=10)) regressor.add(Dropout(0.25)) regressor.add(Dense(units=n_future * 3, activation='relu')) regressor.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_absolute_error']) # Train the model regressor.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.1, verbose=1) testdataset = pd.read_csv('D:/ĐỒ ÁN TRÍ TUỆ NHÂN TẠO/HCM_weather.csv') testdataset = testdataset.iloc[:30, [5,6,7]].values real_humidity = pd.read_csv('D:/ĐỒ ÁN TRÍ TUỆ NHÂN TẠO/HCM_weather.csv') real_humidity = real_humidity.iloc[30:, [5,6,7]].values # Assuming 'testdataset' contains the data for the test set testing = sc.transform(testdataset) testing = np.array(testing) testing = np.reshape(testing, (1, n_past, 3)) predicted_values = [] # List to store the predictions for i in range(30): # Predict the next 'n_future' time steps prediction = regressor.predict(testing) # Store the prediction predicted_values.append(prediction[0]) # Convert the prediction to a 3D array to update 'testing' prediction_3d = prediction.reshape(1, -1, 3) # Remove the oldest time step from 'testing' and add the prediction testing = np.concatenate((testing[:, n_future:, :], prediction_3d), axis=1) testing = testing.reshape(1, n_past, 3) # Reshape to 3D predicted_values = np.array(predicted_values) predicted_values = sc.inverse_transform(predicted_values) predicted_values = np.reshape(predicted_values, (predicted_values.shape[0], predicted_values.shape[1] // 3 , 3)) print(predicted_values) print() print(predicted_values.size) print() print(predicted_values.shape) #real_humidity = real_humidity[:120] #predicted_values = predicted_values.reshape(120,1) #mplt.plot(predicted_values , label = 'predicted') #mplt.plot(real_humidity , label = 'real value') #mplt.legend() #mplt.show()
问题分析与解决方案
错误原因
LSTM层要求输入必须是3维张量,形状为(batch_size, time_steps, features)。你的错误出现在模型堆叠的LSTM层上:
- 第二个LSTM层设置了
return_sequences=False,输出是2维张量(batch_size, units)(即(32,10)) - 第三个LSTM层需要3维输入,但接收到的是第二个LSTM输出的2维张量,因此维度不匹配。
修正方案
如果要堆叠LSTM层,除了最后一层LSTM外,前面的所有LSTM层都需要设置return_sequences=True,这样才能输出3维张量供下一层LSTM使用。
另外需要补充两点:
- 输出层的形状要和
y_train的形状匹配:当前y_train的形状是(samples, n_future, 3),Dense层输出是n_future*3的一维向量,因此需要将y_train展平后再训练。 - 测试部分的列索引要和训练集对应,避免因列不匹配导致的数据错误。
修正后的模型核心代码
# 展平y_train,匹配Dense层输出形状 y_train = y_train.reshape(y_train.shape[0], n_future*3) regressor = Sequential() # 第一层双向LSTM,返回3维序列 regressor.add(Bidirectional(LSTM(units=64, return_sequences=True, input_shape=(n_past, 3)))) regressor.add(Dropout(0.25)) # 第二层LSTM,返回3维序列 regressor.add(LSTM(units=10, return_sequences=True)) regressor.add(Dropout(0.25)) # 第三层LSTM,返回3维序列 regressor.add(LSTM(units=10, return_sequences=True)) regressor.add(Dropout(0.25)) # 第四层LSTM,返回2维结果(供Dense层使用) regressor.add(LSTM(units=10, return_sequences=False)) regressor.add(Dropout(0.25)) # Dense层输出n_future*3个节点,对应展平后的y_train regressor.add(Dense(units=n_future * 3, activation='relu')) regressor.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_absolute_error'])
完整修正代码
import logging logging.getLogger("tensorflow").setLevel(logging.ERROR) import numpy as np import matplotlib.pyplot as mplt import pandas as pd import tensorflow as tf df = pd.read_csv('D:/ĐỒ ÁN TRÍ TUỆ NHÂN TẠO/HCM_weather.csv') dataset = df[['rain' , 'humidi', 'pressure' ,'date']] dataset.set_index('date', inplace=True) dataset = dataset.reset_index(drop=True) training_set = dataset.iloc[:, [0,1,2]].values from sklearn.preprocessing import MinMaxScaler sc = MinMaxScaler(feature_range=(0, 1)) training_set_scaled = sc.fit_transform(training_set) x_train = [] y_train = [] n_future = 4 # 预测未来4天 n_past = 30 # 使用过去30天的数据 for i in range(n_past, len(training_set_scaled) - n_future +1): x_train.append(training_set_scaled[i - n_past:i, :]) y_train.append(training_set_scaled[i:i + n_future, :]) x_train, y_train = np.array(x_train), np.array(y_train) # 展平y_train,匹配Dense层输出 y_train = y_train.reshape(y_train.shape[0], n_future*3) from keras.models import Sequential from keras.layers import LSTM, Dense, Dropout, Bidirectional regressor = Sequential() regressor.add(Bidirectional(LSTM(units=64, return_sequences=True, input_shape=(n_past, 3)))) regressor.add(Dropout(0.25)) regressor.add(LSTM(units=10, return_sequences=True)) regressor.add(Dropout(0.25)) regressor.add(LSTM(units=10, return_sequences=True)) regressor.add(Dropout(0.25)) regressor.add(LSTM(units=10, return_sequences=False)) regressor.add(Dropout(0.25)) regressor.add(Dense(units=n_future * 3, activation='relu')) regressor.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_absolute_error']) # 训练模型 regressor.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.1, verbose=1) testdataset = pd.read_csv('D:/ĐỒ ÁN TRÍ TUỆ NHÂN TẠO/HCM_weather.csv') # 匹配训练集列索引,确保是rain、humidi、pressure三列 testdataset = testdataset.iloc[:30, [0,1,2]].values real_humidity = pd.read_csv('D:/ĐỒ ÁN TRÍ TUỆ NHÂN TẠO/HCM_weather.csv') # 截取对应长度的真实数据 real_humidity = real_humidity.iloc[30:30+30*n_future, [0,1,2]].values # 预处理测试数据 testing = sc.transform(testdataset) testing = np.array(testing) testing = np.reshape(testing, (1, n_past, 3)) predicted_values = [] for i in range(30): prediction = regressor.predict(testing, verbose=0) predicted_values.append(prediction[0]) # 将预测结果转为3维,用于更新测试窗口 prediction_3d = prediction.reshape(1, n_future, 3) # 滑动窗口:移除最旧的n_future个时间步,加入新预测的结果 testing = np.concatenate((testing[:, n_future:, :], prediction_3d), axis=1) testing = testing.reshape(1, n_past, 3) # 逆标准化并调整形状为(总预测天数, 3) predicted_values = np.array(predicted_values) predicted_values = sc.inverse_transform(predicted_values) predicted_values = predicted_values.reshape(predicted_values.shape[0]*n_future, 3) print(predicted_values) print(f"预测结果形状: {predicted_values.shape}") print(f"真实数据形状: {real_humidity.shape}") # 可视化湿度预测结果 mplt.figure(figsize=(12,6)) mplt.plot(predicted_values[:,1], label='预测湿度') mplt.plot(real_humidity[:,1], label='真实湿度') mplt.legend() mplt.show()
内容的提问来源于stack exchange,提问作者Thebowl65t
相关产品推荐
相关产品推荐

