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




