使用Pytorch构建LSTM网络实现对时间序列的预测
使用Python构建LSTM网络实现对时间序列的预测
1. LSTM网络神经元结构

LSTM网络 神经元结构示意图
在任一时刻
观察神经元内部结构,黄色方框从左至右可分别看作:
-
遗忘门 (forget gate):
,表示对信息的记忆程度; -
输入门 (input gate):
,表示对信息的输入强度; -
状态门 (cell gate):
,表示对输入信息的处理; -
输出门 (output gate):
,表示对信息的输出强度;
其中,
在此基础上可更新神经元
-
,即细胞状态 经过遗忘后的旧细胞状态 神经元处理后的新信息; -
,即隐藏状态 输出强度 tanh处理后的细胞状态;
其中
2. 多层LSTM网络
除去神经元内部结构的特殊性,LSTM 神经网络也分为输入层、隐(藏)层与输出层,输入层、输出层分别对应神经网络模型的输入向量


多层LSTM网络结构示意图
- 单层 LSTM 网络:
隐层神经元的输入信号 即为 ; - 多层 LSTM 网络:
第 1 层隐层神经元的输入信号 ,
第 层 神经元的输入信号 ,其中 服从取 0 概率为dropout
的伯努利分布,dropout
自行指定。
对于输入向量
训练目标:
训练参数:
训练方法:反向传播(本文训练方法),模拟退火法等
[========]
3. 构建 LSTM 网络
声明数据:
- 已知数据
,其中 ; - 预测目标向量
;
也就是说, 输入数据维度为 ,时间点个数为 ,预测步长为
声明 LSTM 网络:
- 输入数据维度
, 隐层神经元个数 (隐层状态 特征数) , 隐层数为
import torch import nn from torch myLSTM = nn.LSTM(input_size, hidden_size, num_layers)
LSTM 网络其他参数:
- bias : If False , then the layer does not use bias weights
and [1]. Default: True - batch_first : If True , then the input and output tensors are provided as
instead of .[2] Note that this does not apply to hidden or cell states. Default: False. dropout
: If non-zero , introduces a Dropout layer on the outputs of each LSTM layer except the last layer, with dropout probability equal to dropout. Default: 0- bidirectional : If True , becomes a bidirectional LSTM (denote
). Default: False (denote ). - proj_size : If > 0 , will use LSTM with projections (投影) of corresponding size (denote
). Default: 0 (denote ). 换句话说,proj_size 表现了细胞状态与隐藏状态的维数是否一致.
声明 LSTM 网络的输入与输出:
- 网络输入与输出均为张量 (tensor)
- 网络输入:input,(
);网络输出: output, ( ) - 指导手册上提出了 unbatched inputs 和 outputs 的情况,但在实际操作中,会提示 inputs 必须是 3 维的 (这里可能是笔者的操作有问题,欢迎大家来交流!)
output, (hn, cn) = myLSTM(input, (h0, c0))
input | |||
unbatched | |||
batch_first=True | |||
batch_first=False | |||
description | 初始时刻的隐藏状态 Default: |
初始时刻的细胞状态 Default: |
output | |||
unbatched | |||
batch_first=True | |||
batch_first=False | |||
description | 各个时刻 最后一层节点的隐藏状态 |
最终时刻 全部节点的隐藏状态 |
最终时刻 全部节点的细胞状态 |
注:对于双向 LSTM 网络, |
构建 LSTM 网络结构:
输入数据维度
隐层神经元个数 (隐层状态特征数)
隐层数为
传播方向为 单向
注:所有 weights 和 bias 的初始值服从均匀分布,其中 ;
整个过程可以选择在 GPU 上进行来提高运算速度,此时需要将模型所有的输入向量都转到 GPU 上,具体使用.to(device)
语句
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") class myLSTM(nn.Module): def __init__(self, input_size, output_size, hidden_size, num_layers): super(myLSTM, self).__init__() self.LSTM = nn.LSTM(input_size, hidden_size, num_layers) # LSTM self.reg = nn.Linear(hidden_size, output_size) # regression, 也就是隐藏层到输出层的线性全连接层 def forward(self, x): # 在这里,可以指定 (h0, c0),要记得.to(device) # 如果不指定则默认为 0 向量 x = x.to(device) output = self.LSTM(x)[0] # output, (hm, cm) = self.LSTM(x) # output = self.LSTM(x, (h0, c0))[0] # seq_len是输入数据的时间点个数 seq_len, batch_size, hidden_size = output.shape # for default batch_first=False # seq_len, hidden_size = output.shape # for unbatched input output = output[-1,:,:] #只取最终时刻最后一层节点的隐藏状态做回归,也可以通过hm取 output = self.reg(output) return output
4. 训练 LSTM 网络及预测
# 声明已知数据,可预先进行预处理 train_x # D*(m-L+1),因为之后时刻的 X^t 对应的 y^t 不完全已知,不同的预测任务可能会有所不同 train_y = train_x[s, :] train_x = train_x.to(device) train_y = train_y.to(device) # 加载模型 net = myLSTM(input_size=D, output_size=L, hidden_size=n, num_layers=l).to(device) # 定义模型 loss = nn.MSELoss().to(device) #定义损失函数 optimizer = torch.optim.Adam(net.parameters(), lr=1e-2) #定义优化器 # 开始训练 for i in range(100): # 迭代次数 output = net(train_x) # 向前传播 Loss = loss(out, train_y) # 计算损失 optimizer.zero_grad() # 梯度清零 Loss.backward() # 反向传播 optimizer.step() # 梯度更新 if i % 10 == 0: print('Epoch: {:4}, Loss: {:.5f}'.format(i, Loss.item())) # 验证 LSTM 网络 test_x # D*m,为全部时刻的数据 pred_y = net(test_x)[0] pred_y = pred_y[-1,:].item() # 简单预测最终时刻 X^m 对应的目标变量 y^m
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律