← 返回笔记列表
深度学习 第 49 / 49 篇

LSTM 股价预测笔记:原理与 PyTorch 实现

查看“深度学习”专题目录(49/49)
本文目录 5 个小节

为什么用 LSTM

普通 RNN 在长序列上有梯度消失问题。LSTM 通过门控机制和细胞状态 ctc_t 缓解这一问题。其核心方程为:

ft=σ(Wf[ht−1,xt]+bf)遗忘门it=σ(Wi[ht−1,xt]+bi)输入门c~t=tanh⁡(Wc[ht−1,xt]+bc)ct=ft⊙ct−1+it⊙c~tot=σ(Wo[ht−1,xt]+bo)输出门ht=ot⊙tanh⁡(ct)\begin{aligned} f_t &= \sigma(W_f [h_{t-1}, x_t] + b_f) & \text{遗忘门} \\ i_t &= \sigma(W_i [h_{t-1}, x_t] + b_i) & \text{输入门} \\ \tilde{c}_t &= \tanh(W_c [h_{t-1}, x_t] + b_c) \\ c_t &= f_t \odot c_{t-1} + i_t \odot \tilde{c}_t \\ o_t &= \sigma(W_o [h_{t-1}, x_t] + b_o) & \text{输出门} \\ h_t &= o_t \odot \tanh(c_t) \end{aligned}

其中 σ\sigma 是 sigmoid 函数,⊙\odot 是逐元素乘法。

数据构造的两个坑

  1. 归一化要在划分训练集之后做,用训练集的均值方差变换测试集,否则就是数据泄漏。
  2. 滑动窗口:用过去 LL 天预测下一天,(xt−L+1,…,xt)→xt+1(x_{t-L+1}, \dots, x_t) \to x_{t+1}。

最小实现

import torch
import torch.nn as nn

class StockLSTM(nn.Module):
    def __init__(self, input_size=1, hidden_size=64, num_layers=2):
        super().__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers,
                            batch_first=True, dropout=0.2)
        self.fc = nn.Linear(hidden_size, 1)

    def forward(self, x):
        # x: (batch, seq_len, features)
        out, _ = self.lstm(x)
        return self.fc(out[:, -1, :])  # 只取最后时刻的隐状态

model = StockLSTM()
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

实验中的观察

对价格本身建模往往不如对收益率建模稳定——价格是非平稳序列,模型容易学到”明天约等于今天”的懒惰解。

评估时除了 MSE,还应该看方向准确率(涨跌预测对的比例),这更贴近交易场景。

待深入

  • 加入成交量、技术指标等多特征输入
  • 与 GRU、Transformer(如 Informer、PatchTST)对比
  • 概率预测:输出分布而非点估计(分位数损失)
继续学习本专题