PyTorch LSTM预测谷歌股价时输出与目标趋势一致但缩放异常
LSTM股价预测缩放比例异常问题排查
问题描述
我用PyTorch搭建LSTM模型预测谷歌股价,训练后预测结果与目标值趋势一致,但缩放比例明显偏差。模型参数应为:输入维度1,隐藏层维度200,层数1,后续连接全连接层输出1。训练前用MinMaxScaler.fit_transform()做归一化,预测后用inverse_transform()还原,但问题依旧;尝试为训练/验证/测试集分别使用MinMaxScaler处理,结果趋势匹配但缩放问题仍存在。
数据处理代码
# get close prices from dataset df_close =pd.DataFrame( df['Close']) df_close_values = df_close.values # normalize data using MinMaxScaler mmscaler = MinMaxScaler(feature_range=(0,1)) df_close_scaled = mmscaler.fit_transform(df_close_values) # Sequence Lenght sequence_length = 25 # divide data into train, validation and test data len_data = df_close_values.shape[0] len_train_data = int(len_data * 0.8) len_val_data = int((len_data - len_train_data)/2) len_test_data = len_data - len_train_data - len_val_data train_data = df_close_scaled[0:len_train_data] val_data = df_close_scaled[len_train_data-sequence_length:len_train_data+len_val_data] test_data = df_close_scaled[len_train_data+len_val_data-sequence_length:] # Function to divide data into x and y def partition_dataset(sequence_length, train_df): x, y = [], [] data_len = train_df.shape[0] for i in range(sequence_length, data_len): x.append(train_df[i-sequence_length:i,:]) y.append(train_df[i,0]) # Convert the x and y to numpy arrays x = np.array(x, dtype=np.float32) y = np.array(y, dtype=np.float32) return x, y x_train, y_train = partition_dataset(sequence_length, train_data) x_val, y_val = partition_dataset(sequence_length, val_data) x_test, y_test = partition_dataset(sequence_length, test_data)
数据形状:x_train.shape , y_train.shape = (2554, 25, 1) (2554,)x_val.shape , y_val.shape = (322, 25, 1) (322,)x_test.shape , y_test.shape = (323, 25, 1) (323,)
LSTM模型代码
class LSTMPredictor(nn.Module): def __init__(self, input_size=50, hidden_size=1, num_layers=1, output_size=1, bidirectional=1, dropout=1.0, device='cuda'): super().__init__() # Atributes self.device = 'cuda' self.num_layers = num_layers self.hidden_size = hidden_size self.D = True if bidirectional==2 else False self.output_size = output_size self.dropout = dropout # define LSTM layer self.lstm = nn.LSTM(input_size = input_size, hidden_size = self.hidden_size, num_layers = self.num_layers, bidirectional = self.D, batch_first = True, dropout = dropout) # define fully connected (MLP) self.fully_connected = nn.Linear(self.hidden_size, self.output_size) self.dropout = nn.Dropout(p=0.2) def forward(self, x, hidden=None): # Propagate input through LSTM output, (h, _) = self.lstm(x) out = self.fully_connected(output[:,-1]) return out
截图说明
- 目标值(蓝色)与预测值(橙色)对比:预测值整体趋势与目标值匹配,但数值缩放比例偏差明显,橙色线波动幅度远小于蓝色线
- 预测值放大图:可见预测值波动趋势,但数值范围与真实值不符
- 更新后截图:趋势匹配依旧,但缩放问题未解决,预测值数值区间仍偏离真实值
问题原因排查
1. 模型初始化参数完全错误
你定义的LSTMPredictor类初始化参数与实际需求完全不匹配:
- 实际输入维度为1,但代码默认
input_size=50,且实例化时未覆盖该参数,导致LSTM输入维度与实际输入(batch, 25, 1)不匹配,模型未在正确维度上训练 - 实际需要隐藏层维度200,但代码默认
hidden_size=1,模型容量严重不足,仅能学习趋势,无法拟合数值幅度 dropout=1.0意味着所有神经元都会被丢弃,完全不合理,dropout取值应在0-1之间(例如0.2)
2. 归一化使用错误
- 初始用整个数据集做
fit_transform会导致数据泄露,正确做法是仅在训练集上fit scaler,再用同一个scaler对验证集、测试集做transform - 尝试分数据集单独使用MinMaxScaler,会导致各子集缩放基准不同,模型学习的是子集相对缩放,还原后自然与真实值缩放比例不一致
3. 数据划分边界的潜在问题
验证集和测试集划分时从len_train_data-sequence_length取数据,虽保证了序列长度,但如果还原时未对应原始数据集的正确区间,可能加剧数值偏差(次要问题,核心为模型参数和归一化)
修复方案
- 修正模型初始化参数
实例化模型时传入正确参数:
model = LSTMPredictor(input_size=1, hidden_size=200, num_layers=1, dropout=0.2, bidirectional=1)
同时简化bidirectional判断逻辑,不需要双向LSTM时直接设为False更清晰。
- 修正归一化流程
# 仅在训练集上拟合scaler mmscaler = MinMaxScaler(feature_range=(0,1)) train_data_scaled = mmscaler.fit_transform(df_close_values[0:len_train_data]) # 验证集、测试集用同一个scaler做转换 val_data_scaled = mmscaler.transform(df_close_values[len_train_data:len_train_data+len_val_data]) test_data_scaled = mmscaler.transform(df_close_values[len_train_data+len_val_data:]) # 重新划分序列(确保基于对应区间的缩放后数据) train_data = train_data_scaled val_data = np.concatenate([train_data_scaled[-sequence_length:], val_data_scaled], axis=0) test_data = np.concatenate([val_data_scaled[-sequence_length:], test_data_scaled], axis=0) x_train, y_train = partition_dataset(sequence_length, train_data) x_val, y_val = partition_dataset(sequence_length, val_data) x_test, y_test = partition_dataset(sequence_length, test_data)
- 检查逆转换的输入形状
模型输出为一维数组,inverse_transform要求输入为二维数组,还原时需先reshape:
y_pred_scaled = model(x_test).detach().cpu().numpy() y_pred = mmscaler.inverse_transform(y_pred_scaled.reshape(-1, 1))
内容的提问来源于stack exchange,提问作者sebastian orellana
相关产品推荐
相关产品推荐

