You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PyTorch实现LSTM股票涨跌预测模型时预测结果不随输入变化的问题求助

PyTorch实现LSTM股票涨跌预测模型时预测结果不随输入变化的问题求助

各位好,我现在在用PyTorch实现一个LSTM模型,目标是预测股票未来5分钟和10分钟的收盘价涨跌情况。我用了24年的5分钟粒度数据(覆盖7只股票),每一周的数据作为一个预测单元,输入包含19个特征。但目前遇到了一个核心问题:不管怎么调整参数,模型的预测结果几乎都停留在某个固定值附近,损失下降极其缓慢,完全学不到有效的预测模式。

数据预处理情况

我已经把输入和目标变量都转换为[batch_size, sequence_len, features]格式的PyTorch Tensor(我的具体维度是[32, 2016, 19]),并且做了0-1归一化处理。目标变量是二分类标签:如果未来价格上涨则标记为1,下跌则标记为0。

模型结构

我的LSTM模型定义如下:

import torch
import torch.nn as nn

class MultiInputOutputLSTM(nn.Module):
  def __init__(self, input_size, hidden_size, num_layers, output_size, dropout, lr, batch_size):
    super(MultiInputOutputLSTM, self).__init__()
    self.input_size = input_size
    self.hidden_size = hidden_size
    self.num_layers = num_layers
    self.dropout = dropout
    self.batch_size = batch_size
    self.loss_list = []
    self.accuracy = 0
    self.predictions_list = [0]
    
    self.lstm = nn.LSTM(input_size = self.input_size, hidden_size = self.hidden_size, num_layers = self.num_layers, dropout = self.dropout,  batch_first=True)
    self.fc = nn.Linear(hidden_size, output_size, bias=True)
    self.sigmoid = nn.Sigmoid()
    self.criterion = nn.BCEWithLogitsLoss()
    self.optimizer = torch.optim.RMSprop(self.parameters(), lr = lr, alpha=0.9, weight_decay=1e-4,  momentum=0.5)
    self.scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(self.optimizer, 'min')

  def forward(self, x):
    h0 = torch.zeros(self.num_layers, self.batch_size, self.hidden_size)
    c0 = torch.zeros(self.num_layers, self.batch_size, self.hidden_size)
    lstm_out, _ = self.lstm(x, (h0, c0))
    output = self.fc(lstm_out[:, -1, :])
    return output

  def train_step(self ,x, y):
        self.train()
        predictions_1 = torch.round(self.forward(x))
        predictions = self.forward(x)
        if (predictions_1.detach().cpu().numpy()[0] == y.detach().cpu().numpy()[0]).all():
          self.accuracy += 1
        self.predictions_list.append(predictions.detach().cpu().numpy()[0][0])
        penalty = torch.mean((predictions-0.5)**2)
        loss = self.criterion(predictions, y) + penalty
        self.scheduler.step(loss)
        self.optimizer.zero_grad()
        self.loss_list.append(loss.item())
        mean_loss = sum(self.loss_list)/len(self.loss_list)
        loss.backward()
        torch.nn.utils.clip_grad_norm_(self.parameters(), max_norm=6)
        self.optimizer.step()
        return loss.item(), mean_loss, self.accuracy, predictions.detach().cpu().numpy()[0], y.detach().cpu().numpy()[0]
  
  def test_step(self, inputs, targets):
    self.eval()
    with torch.no_grad():
      outputs = torch.round(self.forward(inputs))
      outputs = outputs.detach().cpu().numpy()[0]
      targets = targets.detach().cpu().numpy()[0]
      if (outputs == targets).all():
        accuracy = 1
      else:
        accuracy = 0
    return accuracy, outputs, targets

超参数设置

我当前使用的超参数如下:

input_size = 19
hidden_size = 3
num_layers = 5
output_size = 2
lr = 0.001
num_epochs = 5
batch_size = 32
dropout = 0.3

问题具体表现

  • 模型预测值几乎不变化:训练开始后,预测值只会在初始值附近做极小幅度的波动(比如±1e-3、1e-4),几乎没有随输入和训练轮数产生有效变化
  • 损失下降停滞:训练损失从初始的0.924缓慢降到0.889后就不再下降
  • 准确率极低:训练准确率仅在5.56%到11.67%之间波动,完全是随机猜测的水平

已尝试的调整方案

为了解决这个问题,我已经尝试了以下所有方案,但都没有改善:

  • 调整学习率:范围从1e-5到0.1都试过
  • 调整输出维度:尝试过不同的输出规模
  • 调整batch size:从1到256的不同大小都试过
  • 调整LSTM层数:1层到5层都试过
  • 调整输入特征数:从只保留1个特征到使用全部19个特征都试过
  • 调整dropout比例:0到0.5之间调整
  • 调整训练轮数:1轮到100轮都试过
  • 更换优化器:试过Adam、SGD、RMSProp,还调整了RMSProp的alpha、动量和权重衰减参数
  • 更换损失函数:试过BCELoss(配合Sigmoid激活)、L1Loss、MSELoss、CrossEntropyLoss,最后还在损失中加入了惩罚项(惩罚接近0.5的预测值),但效果微乎其微

训练样例展示

以下是训练过程中的部分输出,可以看到即使训练到第50轮,预测值也几乎没有变化:

Ticker - Df - Loss - Mean Loss - Predictions - Targets - Epoch
AAPL 1/120 0.808  0.808 [0.5642182  0.11684255] [1. 1.] 1/50 
AAPL 2/120 0.828  0.818 [0.5629723  0.12899561] [1. 1.] 1/50 
AAPL 3/120 0.834  0.823 [0.5472506  0.13749745] [1. 1.] 1/50 
AAPL 4/120 0.839  0.827 [0.52973044 0.13656825] [0. 0.] 1/50 
AAPL 5/120 0.821  0.826 [0.52082217 0.13681749] [0. 0.] 1/50 
AAPL 6/120 0.804  0.822 [0.5117941  0.14727135] [1. 1.] 1/50 
AAPL 7/120 0.779  0.816 [0.49826628 0.1547919 ] [0. 0.] 1/50 
AAPL 8/120 0.845  0.820 [0.49666688 0.1573844 ] [0. 0.] 1/50 
…
AAPL 1/120 0.762  0.751 [0.4200741  0.24348469] [1. 1.] 50/50 
AAPL 2/120 0.787  0.751 [0.43581426 0.23458275] [1. 1.] 50/50 
AAPL 3/120 0.797  0.751 [0.43012726 0.23912352] [1. 1.] 50/50 
AAPL 4/120 0.805  0.751 [0.43174705 0.23598525] [0. 0.] 50/50 
AAPL 5/120 0.794  0.751 [0.41290796 0.24462458] [0. 0.] 50/50 
AAPL 6/120 0.777  0.751 [0.42214283 0.2398287 ] [1. 1.] 50/50 
AAPL 7/120 0.747  0.751 [0.42418063 0.24077193] [0. 0.] 50/50 
AAPL 8/120 0.822  0.751 [0.44875318 0.23495609] [0. 0.] 50/50

恳请各位大佬帮忙分析一下问题出在哪里,或者有没有其他可以尝试的调整方向?

备注:内容来源于stack exchange,提问作者user22615570

火山引擎 最新活动