“他山之石,可以攻玉”,站在巨人的肩膀才能看得更高,走得更远。在科研的道路上,更需借助东风才能更快前行。为此,我们特别搜集整理了一些实用的代码链接,数据集,软件,编程技巧等,开辟“他山之石”专栏,助你乘风破浪,一路奋勇向前,敬请关注。
作者: 知乎—master苏地址:https://www.zhihu.com/people/zhenyu22
最近在学习LSTM应用在时间序列的预测上,但是遇到一个很大的问题就是LSTM在传统BP网络上加上时间步后,其结构就很难理解了,同时其输入输出数据格式也很难理解,网络上有很多介绍LSTM结构的文章,但是都不直观,对初学者是非常不友好的。我也是苦苦冥思很久,看了很多资料和网友分享的LSTM结构图形才明白其中的玄机。01
传统的BP网络和CNN网络
BP网络和CNN网络没有时间维,和传统的机器学习算法理解起来相差无几,CNN在处理彩色图像的3通道时,也可以理解为叠加多层,图形的三维矩阵当做空间的切片即可理解,写代码的时候照着图形一层层叠加即可。如下图是一个普通的BP网络和CNN网络。![fbb895468e36beef4b61fbe1de87ac1d.png](https://i-blog.csdnimg.cn/blog_migrate/6546ea364a671a67ad01240377186dc8.jpeg)
# 示例代码,没有实际意义
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu')) # 添加卷积层
model.add(MaxPooling2D(pool_size=(2, 2))) # 添加池化层
model.add(Dropout(0.25)) # 添加dropout层
model.add(Conv2D(32, (3, 3), activation='relu')) # 添加卷积层
model.add(MaxPooling2D(pool_size=(2, 2))) # 添加池化层
model.add(Dropout(0.25)) # 添加dropout层
.... # 添加其他卷积操作
model.add(Flatten()) # 拉平三维数组为2维数组
model.add(Dense(256, activation='relu')) 添加普通的全连接层
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
.... # 训练网络
02
LSTM网络
当我们在网络上搜索看LSTM结构的时候,看最多的是下面这张图:
![d0a2e0f624b869805af54d5e3776ed0f.png](https://i-blog.csdnimg.cn/blog_migrate/9287a05e132e5e32d81d6ff88a23804e.jpeg)
03
LSTM的输入结构
为了更好理解LSTM结构,还必须理解LSTM的数据输入情况。仿照3通道图像的样子,在加上时间轴后的多样本的多特征的不同时刻的数据立方体如下图所示:
![aefb107da86050a38f6ebe0b9548e86c.png](https://i-blog.csdnimg.cn/blog_migrate/8fb4dc4667665ab951680ba3cf04ff0c.jpeg)
![e49ba3c43edb560a501c7a54f73ca3e5.png](https://i-blog.csdnimg.cn/blog_migrate/a5f50ab5d9cb46b36e67ce6a772487ce.jpeg)
![3c23d3cadd471e804d5afc5d04b82afc.png](https://i-blog.csdnimg.cn/blog_migrate/fabb224433a09561d1fbf1f99b02ff63.jpeg)
04
pytorch中的LSTM
4.1 pytorch中定义的LSTM模型
pytorch中定义的LSTM模型的参数如下
class torch.nn.LSTM(*args, **kwargs)
参数有:
input_size:x的特征维度
hidden_size:隐藏层的特征维度
num_layers:lstm隐层的层数,默认为1
bias:False则bihbih=0和bhhbhh=0. 默认为True
batch_first:True则输入输出的数据格式为 (batch, seq, feature)
dropout:除最后一层,每一层的输出都进行dropout,默认为: 0
bidirectional:True则为双向lstm默认为False
结合前面的图形,我们一个个看。
(1)input_size:x的特征维度,就是数据立方体中的F,在NLP中就是一个词被embedding后的向量长度,如下图所示:
4.2 喂给LSTM的数据格式
pytorch中LSTM的输入数据格式默认如下:
input(seq_len, batch, input_size)
参数有:
seq_len:序列长度,在NLP中就是句子长度,一般都会用pad_sequence补齐长度
batch:每次喂给网络的数据条数,在NLP中就是一次喂给网络多少个句子
input_size:特征维度,和前面定义网络结构的input_size一致。
前面也说到,如果LSTM的参数 batch_first=True,则要求输入的格式是:
input(batch, seq_len, input_size)
刚好调换前面两个参数的位置。其实这是比较好理解的数据形式,下面以NLP中的embedding向量说明如何构造LSTM的输入。
之前我们的embedding矩阵如下图:
![96b2daa7abcd3e596017933d6ac251a7.png](https://i-blog.csdnimg.cn/blog_migrate/4c6eadcf9218ec168a06caaf6897a802.jpeg)
![5fe09bedb1e6fa26db4201fa31d7282e.png](https://i-blog.csdnimg.cn/blog_migrate/e3a931949f35a8a6bdcd82b8283870d6.jpeg)
![cd45acc5c0cbe4396458af1afbfcede3.png](https://i-blog.csdnimg.cn/blog_migrate/77acf94717e921daaccaa0eed7ccff38.jpeg)
h0(num_layers * num_directions, batch, hidden_size)
c0(num_layers * num_directions, batch, hidden_size)
参数:
num_layers:隐藏层数
num_directions:如果是单向循环网络,则num_directions=1,双向则num_directions=2
batch:输入数据的batch
hidden_size:隐藏层神经元个数
注意,如果我们定义的input格式是:
input(batch, seq_len, input_size)
则H和C的格式也是要变的:
h0(batc,num_layers * num_directions, h, hidden_size)
c0(batc,num_layers * num_directions, h, hidden_size)
4.3 LSTM的output格式
LSTM的输出是一个tuple,如下:
output,(ht, ct) = net(input)
output: 最后一个状态的隐藏层的神经元输出
ht:最后一个状态的隐含层的状态值
ct:最后一个状态的隐含层的遗忘门值
output的默认维度是:
output(seq_len, batch, hidden_size * num_directions)
ht(num_layers * num_directions, batch, hidden_size)
ct(num_layers * num_directions, batch, hidden_size)
和input的情况类似,如果我们前面定义的input格式是:
input(batch, seq_len, input_size)
则ht和ct的格式也是要变的:
ht(batc,num_layers * num_directions, h, hidden_size)
ct(batc,num_layers * num_directions, h, hidden_size)
说了这么多,我们回过头来看看ht和ct在哪里,请看下图:
05
LSTM和其他网络组合
还记得吗,output的维度等于隐藏层神经元的个数,即hidden_size,在一些时间序列的预测中,会在output后,接上一个全连接层,全连接层的输入维度等于LSTM的hidden_size,之后的网络处理就和BP网络相同了,如下图:![4421943be9c59867f8e9168e8a435c44.png](https://i-blog.csdnimg.cn/blog_migrate/c6e29a62005755914983292bea6117fd.jpeg)
import torch
from torch import nn
class RegLSTM(nn.Module):
def __init__(self):
super(RegLSTM, self).__init__()
# 定义LSTM
self.rnn = nn.LSTM(input_size, hidden_size, hidden_num_layers)
# 定义回归层网络,输入的特征维度等于LSTM的输出,输出维度为1
self.reg = nn.Sequential(
nn.Linear(hidden_size, 1)
)
def forward(self, x):
x, (ht,ct) = self.rnn(x)
seq_len, batch_size, hidden_size= x.shape
x = y.view(-1, hidden_size)
x = self.reg(x)
x = x.view(seq_len, batch_size, -1)
return x
当然,有些模型则是将输出当做另一个LSTM的输入,或者使用隐藏层ht,ct的信息进行建模,不一而足。
好了,以上就是我对LSTM的一些学习心得,看完记得关注点赞。
参考:
https://zhuanlan.zhihu.com/p/94757947
https://zhuanlan.zhihu.com/p/59862381
https://zhuanlan.zhihu.com/p/36455374
https://www.zhihu.com/question/41949741/answer/318771336
https://blog.csdn.net/android_ruben/article/details/80206792
本文目的在于学术交流,并不代表本公众号赞同其观点或对其内容真实性负责,版权归原作者所有,如有侵权请告知删除。
![96b2f3d8e027771de2520c7fe205aaa3.gif](https://i-blog.csdnimg.cn/blog_migrate/973d80fa91744bb97d20ade316de13a9.gif)
直播预告
![96b2f3d8e027771de2520c7fe205aaa3.gif](https://i-blog.csdnimg.cn/blog_migrate/973d80fa91744bb97d20ade316de13a9.gif)
![7483be98706695eac01bf5e226c0a008.png](https://i-blog.csdnimg.cn/blog_migrate/6ea9e5651b1ad9b7219a2903b2d39701.png)
“他山之石”历史文章
PointNet论文复现及代码详解
SCI写作常用句型之研究结果&发现
白话生成对抗网络GAN及代码实现
pytorch的余弦退火学习率
Pytorch转ONNX-实战篇(tracing机制)
联邦学习:FedAvg 的 Pytorch 实现
PyTorch实现ShuffleNet-v2亲身实践
训练时显存优化技术——OP合并与gradient checkpoint
浅谈数据标准化与Pytorch中NLLLoss和CrossEntropyLoss损失函数的区别
在C++平台上部署PyTorch模型流程+踩坑实录
libtorch使用经验
深度学习模型转换与部署那些事(含ONNX格式详细分析)
如何支撑上亿类别的人脸训练?显存均衡的模型并行(PyTorch实现)
PyTorch trick 集锦
![d28285bad392010c6b22a045532bf127.png](https://i-blog.csdnimg.cn/blog_migrate/fa4eb9497b0948d70af321e595327fb2.png)
![6bc782e001ccfc061e148fd835420aa6.gif](https://i-blog.csdnimg.cn/blog_migrate/29fa05caa34be9e0e00b8a36de279d69.gif)
分享、点赞、在看,给个三连击呗!