基于LSTM的时间序列滚动预测疑问及无历史场景改造咨询
问题解答
关于forecasted_values.append(predicted_value[0])的疑问
这是因为PyTorch模型的输出会保留batch维度:
- 在滚动预测时,你输入的是单个长度为30的历史序列,对应的batch_size是1。模型最后一层(通常是线性层)的输出形状为
(batch_size, output_size),这里output_size=1(预测单步股价),所以predicted_value是一个二维张量/数组,比如[[152.3]]。 predicted_value[0]的作用是取出batch维度下的第一个(也是唯一一个)元素,得到一维的[152.3]。如果你需要拿到具体的数值,通常还会加上.item()(针对张量)或者[0](针对数组),但直接append这个一维结果也是常见写法,后续可统一处理。
简单说:模型输出带了batch维度,取第一个元素就是剥离这个维度,拿到当前单步的预测结果。
无历史数据时的动态序列窗口预测改造
核心思路是初始化一个合理的初始窗口,然后用预测值滚动更新窗口,具体步骤和代码改造如下:
1. 生成初始窗口
初始窗口的数值要尽量贴合目标股票的股价特征,比如用该股票的发行价、行业平均股价,或者基于历史数据的统计特征(均值、标准差)生成:
import numpy as np def generate_initial_window(seq_len, mean_price, std_price): # 用正态分布生成符合历史波动特征的初始值 initial_vals = np.random.normal(loc=mean_price, scale=std_price, size=seq_len) # 确保股价非负(股价不能为负) initial_vals = np.abs(initial_vals) # 转成模型需要的形状:(seq_len, input_size),这里input_size=1 return initial_vals.reshape(-1, 1)
2. 滚动预测逻辑改造
替换原有的基于历史数据的滚动逻辑,改为用初始窗口启动,不断用预测值更新窗口:
import torch from sklearn.preprocessing import MinMaxScaler # 假设训练时用了归一化 # 假设你已经有训练好的LSTM模型model,以及训练数据的scaler、统计特征 seq_length = 30 num_forecast_steps = 60 # 要预测的步数 # 用历史数据的均值和标准差生成初始窗口(如果没有历史数据,可手动设置合理值) mean_price = 145.0 # 示例值,可替换为发行价/行业均值 std_price = 8.0 # 示例值,可根据行业波动设置 # 生成初始窗口并做归一化(和训练流程一致) current_window = generate_initial_window(seq_length, mean_price, std_price) current_window = scaler.transform(current_window) forecasted_values = [] for _ in range(num_forecast_steps): # 转成PyTorch张量,适配模型输入形状(比如(batch_size, seq_len, input_size)) input_tensor = torch.tensor(current_window, dtype=torch.float32).unsqueeze(0) with torch.no_grad(): predicted = model(input_tensor) # 反归一化,得到真实股价范围的预测值 predicted = scaler.inverse_transform(predicted.numpy()) # 保存预测的标量值 forecasted_values.append(predicted[0][0]) # 更新窗口:移除最旧的一个值,添加新的预测值 current_window = np.vstack([current_window[1:], predicted])
注意事项
- 初始窗口的合理性直接影响后续预测的可靠性,尽量不要用完全随机的无意义数值。
- 必须保证初始窗口的预处理(归一化/标准化)和训练数据的流程完全一致,否则模型输出会失真。
- 如果你的模型输入形状是
(seq_len, batch_size, input_size)(非batch_first),需要调整input_tensor的形状为torch.tensor(current_window, dtype=torch.float32).unsqueeze(1)。
内容的提问来源于stack exchange,提问作者Enrique Vilchez Campillejo
相关产品推荐
相关产品推荐

