如何基于多输入LSTM模型实现股票价格多日预测?
多变量LSTM股票多日预测修改方案
问题背景
我基于多变量时间序列实现了输入维度为(50,5)的LSTM股票预测模型,但目前只能输出单日单列的预测结果,想要实现30天的多日预测。尝试循环预测时,发现模型要求输入是50×5的维度,没法把单日1×1的预测结果补充到输入里,求修改指导。
现有代码与输出情况
训练数据维度
(480, 50, 5) # x_train:480个样本,每个样本50时间步×5特征 (480,) # y_train:每个样本对应1个单日收盘价标签 (132, 50, 5) # x_test (132,) # y_test
现有模型与单日预测代码
model = Sequential() n_neurons = x_train.shape[1] * x_train.shape[2] print(n_neurons, x_train.shape[1], x_train.shape[2]) model.add(LSTM(n_neurons, return_sequences=True, input_shape=(x_train.shape[1], x_train.shape[2]))) model.add(LSTM(n_neurons, return_sequences=False)) model.add(Dense(5)) model.add(Dense(1)) model.compile(optimizer='adam', loss='mse') epochs = 100 batch_size = 16 early_stop = EarlyStopping(monitor='loss', patience=5, verbose=1) history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test) ) # 单日预测逻辑 pred_price_scaled = model.predict(np.array(to_predict_scaled)) pred_price_unscaled = scaler.inverse_transform(pred_price_scaled.reshape(-1, 1)) price_today = np.round(data.loc[data.index[-1], "Close Price"]) predicted_price = np.round(pred_price_unscaled.ravel()[0], 2) change_percent = np.round(100 - (price_today * 100)/predicted_price, 2) print(f'The predicted close price is {predicted_price} ({"+" if change_percent > 0 else "-"}{change_percent}%) today={price_today}')
输出:The predicted close price is 1322.5 (-0.72%) today=1332.0
尝试的多日预测代码(存在问题)
while(i<30): yhat = model.predict(np.array(X_test_new)) X_test_new.extend(yhat[0].tolist()) lst_output.extend(yhat.tolist()) i=i+1
核心问题分析
模型输入要求是50时间步×5特征,但每次预测仅输出1个收盘价(1×1),无法直接补全5个特征的输入维度。要实现多日预测,必须解决两个核心问题:
- 每次预测后维持输入序列的50时间步长度
- 补全预测日除收盘价外的其他4个特征值
具体修改方案
方案:保留5特征的滚动预测(推荐)
假设你的5个特征是[Open, High, Low, Close, Volume]这类常规股票特征,以下是可直接运行的修改代码:
# 初始化预测结果列表 lst_output = [] # 复制初始输入(确保是形状为(1,50,5)的归一化数据) current_input = to_predict_scaled.copy() for _ in range(30): # 预测单日归一化后的收盘价 yhat_scaled = model.predict(current_input, verbose=0) lst_output.append(yhat_scaled[0][0]) # --- 构建新的输入序列 --- # 取输入序列最后1天的前4个特征(Open/High/Low/Volume)作为新一天的对应特征 last_day_features = current_input[0, -1, :4] # 拼接成新的1天数据:[Open, High, Low, 预测Close, Volume] new_day = np.concatenate([last_day_features, yhat_scaled[0]]) # 调整形状为(1,1,5),匹配输入维度要求 new_day = new_day.reshape(1,1,5) # 更新输入:去掉最旧的1天,加入新生成的1天,保持50时间步长度 current_input = np.concatenate([current_input[:, 1:, :], new_day], axis=1) # --- 反归一化处理 --- # 构造包含5列的数组(适配原始归一化器),仅Close列是预测值 pred_scaled_array = np.array(lst_output).reshape(-1,1) full_pred_scaled = np.hstack([np.zeros((30,4)), pred_scaled_array]) # 反归一化后提取Close列的预测结果 pred_unscaled = scaler.inverse_transform(full_pred_scaled)[:,4] # 输出30天预测结果 print("30天预测收盘价:", pred_unscaled.round(2))
关键说明
- 特征补全逻辑:代码中用前一日的Open/High/Low/Volume作为新一天的对应特征,是最简单的实现方式。如果追求更高精度,可以为每个特征单独训练预测模型,或用移动平均、插值等方法生成其他特征的预测值。
- 输入维度维持:每次预测后通过"丢弃最旧时间步+新增预测时间步"的方式,始终保持输入序列为50时间步长度。
- 反归一化适配:原始归一化器是针对5个特征训练的,因此需要构造包含5列的数组完成反归一化,最后提取Close列的结果即可。
内容的提问来源于stack exchange,提问作者Mogli141
相关产品推荐
相关产品推荐

