Pytorch 中的 LSTM
前提
- troch.nn.LSTM 的用法的介绍有很多,本篇主要说几点作者在使用其时遇到的容易忽略的地方。
- 其次,我下面说的前两点是针对统一长度序列的使用。
1.返回值内容
首先,因为不同的课程的讲述的偏差,所以我之前对 LSTM 的返回值有了一些不理解。例如下图是李宏毅老师的 ppt,其中得到 h ( c ′ ) h(c^{'}) h(c′) 之后要经过一个遗忘门才是输出;而再下面的公式是丘锡鹏老师的的书中所使用的公式,可以看到,丘老师所讲的内容是跳过了刚刚中间的一步,直接得到的就是经过遗忘门的输出。
由于上面的一点不同,所以我一开始使用 o u t , ( h t , c t ) = t o r c h . n n . L S T M ( ) out,(h_t,c_t) = torch.nn.LSTM() out,(ht,ct)=torch.nn.LSTM() 时认为, h t h_t ht 代表的隐状态是没有通过遗忘门的内容, o u t out out 代表的输出是 h t h_t ht 通过遗忘门之后的内容。
但后来我发现,pytorch 中的 LSTM 的 o u t out out 和 h t h_t ht 都是通过了遗忘门的内容,其本身是相同的,唯一的区别就是 h t h_t ht 代表的是整个输入序列最后一个元素的隐状态,而 o u t out out 是序列中各个元素的隐状态的集合,测试如下:
a = torch.randn(1,3,5)
lstm = nn.LSTM(input_size=5,hidden_size=4,num_layers=1,batch_first=True)
out,(h,c) = lstm(a)
print(out[0])
print(h[0,0])
可以发现, o u t out out 的最后一个 vector 与 h h h 是完全相同的。所以 pytorch 中所用的就是丘老师所说的情况。
最后关于这一点我想说,可能严谨说来,提出 LSTM 的论文是按照李宏毅老师讲的那样,序列中的每个元素的隐状态和输出是不同的(差一次遗忘门控),但是实际上二者区别不大,所以不加区分也是可以的。
2.返回值的 shape
设置了 batch_first 为 True 以后,输入和得到的 out 会将 batch 排到第一维,但是 h 不会改变,即其还是以 num_layers 为第一维。(这一点也比较好理解,因为 python LSTM 其内部是将一句话中的每个词依次放入,每个词得到的 h 将同下一个 word 一起放入,如果因为 batch_first 改变了 h 的 shape,则将其放入下一个轮中时会出错)
3.处理变长序列之后得到的返回值
我们知道如果想用 pytorch 的 LSTM 处理变长序列,那么需要先对长度不一样的序列进行 pack,之后进行 LSTM 处理。此时得到的 out 则同样是一个 pack 后的序列,所以需要对其进行 unpack 操作。
Reference
- Hongyi Li. 2020. Recurrent Neural Network (RNN). from * University
- Xipeng Qiu. 2020 神经网络与深度学习
上一篇: pytorch中的LSTM