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

PyTorch LSTM谷歌股价预测出现周期性尖峰的原因排查

解决LSTM股价预测中周期性下降尖峰问题

可能的原因及对应解决方法

1. 数据处理环节问题

  • 测试集数据超出训练集缩放范围:MinMaxScaler基于训练集极值拟合,若测试集Open特征超出训练集的最小/最大值,模型会因从未见过此类数据输出异常尖峰。
    • 解决:
      • 检查测试集Open值分布,确认是否存在训练集未覆盖的极值;
      • 替换为RobustScaler,提升对异常值的鲁棒性;
      • 改用时间序列滚动划分(而非直接8:2切分),确保测试集数据分布与训练集更匹配。
  • 序列构建与缩放顺序错误:先构建序列再做特征缩放,会导致每个序列的缩放范围不一致,引发预测异常。正确流程是先对整个特征列做缩放,再构建时序序列。
    • 解决:严格遵循以下流程:
      scaler = MinMaxScaler(feature_range=(0,1))
      # 仅用训练集拟合scaler
      train_scaled = scaler.fit_transform(train_data[['Open']])
      # 用训练集拟合的scaler转换测试集
      test_scaled = scaler.transform(test_data[['Open']])
      # 基于缩放后的特征构建时序序列
      

2. 模型训练与状态管理问题

  • 训练轮次严重不足:仅训练3轮的LSTM几乎无法学习到股价的时序模式,属于欠拟合状态,会导致输出无意义的尖峰。
    • 解决:将训练轮次提升至50-100轮,同时加入早停机制:当验证集损失连续多轮不再下降时停止训练,避免过拟合。
  • LSTM隐藏状态处理错误:训练时未正确截断隐藏状态的梯度,或测试时未重置隐藏状态,会导致状态累积,引发周期性异常输出。
    • 解决:
      • 训练时,每个epoch初始化隐藏状态,且每个batch后对隐藏状态做detach()截断梯度:
        for epoch in range(epochs):
            h0 = torch.zeros(num_layers, batch_size, hidden_size).to(device)
            c0 = torch.zeros(num_layers, batch_size, hidden_size).to(device)
            for i in range(0, train_X.shape[0], batch_size):
                batch_X = train_X[i:i+batch_size].to(device)
                batch_y = train_y[i:i+batch_size].to(device)
                outputs, (h0, c0) = model(batch_X, (h0.detach(), c0.detach()))
                # 后续损失计算、反向传播步骤
        
      • 测试时,每个测试序列都重新初始化隐藏状态:
        model.eval()
        with torch.no_grad():
            predictions = []
            for seq in test_X:
                h0 = torch.zeros(num_layers, 1, hidden_size).to(device)
                c0 = torch.zeros(num_layers, 1, hidden_size).to(device)
                output, _ = model(seq.unsqueeze(0), (h0, c0))
                predictions.append(output.item())
        
  • 模型结构未做正则化:股价数据噪声较多,无正则化的LSTM容易过拟合,导致测试集输出异常。
    • 解决:在LSTM层加入dropout正则化,或调整隐藏层大小:
      # 加入dropout
      self.lstm = nn.LSTM(1, hidden_size, num_layers, dropout=0.2)
      # 或缩小hidden_size至32,降低模型容量
      

3. 损失函数选择问题

  • MSELoss对异常值过于敏感:股价的异常波动会被MSELoss放大,迫使模型为拟合这些异常点输出尖峰。
    • 解决:改用HuberLoss,它结合了MSE和MAE的优点,对异常值鲁棒性更强:
      criterion = nn.HuberLoss()
      

4. 可视化反缩放错误

  • 预测值反缩放时形状不匹配:MinMaxScaler的inverse_transform要求输入为二维数组,若预测值是一维数组,直接转换会导致数据变形,出现尖峰。
    • 解决:转换前将预测值调整为二维形状:
      predictions = scaler.inverse_transform(np.array(predictions).reshape(-1, 1))
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 16:12:29