// Fork me on GitHub

torch.nn.lstm参数

 

这里num_layers是同一个time_step的结构堆叠,Lstm堆叠层数与time step无关。Time step表示的是时间序列长度,它是由数据的inputsize决定,你输的数据时序有多长,那么神经网络会自动确定,时间序列长度只需要与你输入的数据时序长度保持一致即可。

lstm=nn.LSTM(input_size,                     hidden_size,                      num_layers)
x                         seq_len,                          batch,                              input_size
h0            num_layers× \times×num_directions,   batch,                             hidden_size
c0            num_layers× \times×num_directions,   batch,                             hidden_size

output                 seq_len,                         batch,                num_directions× \times×hidden_size
hn            num_layers× \times×num_directions,   batch,                             hidden_size
cn            num_layers× \times×num_directions,    batch,                            hidden_size

举个例子:
对句子进行LSTM操作

假设有100个句子(sequence),每个句子里有7个词,batch_size=64,embedding_size=300

此时,各个参数为:
input_size=embedding_size=300
batch=batch_size=64
seq_len=7

另外设置hidden_size=100, num_layers=1

import torch
import torch.nn as nn
lstm = nn.LSTM(300, 100, 1)
x = torch.randn(7, 64, 300)
h0 = torch.randn(1, 64, 100)      

c0 = torch.randn(1, 64, 100)

output, (hn, cn)=lstm(x, (h0, c0))

>>
output.shape torch.Size([7, 64, 100])
hn.shape torch.Size([1, 64, 100])
cn.shape torch.Size([1, 64, 100])
--------------------- 
作者:huxuedan01 
来源:CSDN 
原文:https://blog.csdn.net/m0_37586991/article/details/88561746 
版权声明:本文为博主原创文章,转载请附上博文链接!

二、双向LSTM模型

1、双向LSTM的结构

双向LSTM(Bidirectional Long-Short Term Memorry,Bi-LSTM)不仅能利用到过去的信息,还能捕捉到后续的信息,比如在词性标注问题中,一个词的词性由上下文的词所决定,那么用双向LSTM就可以利用好上下文的信息。

双向LSTM由两个信息传递相反的LSTM循环层构成,其中第一层按时间顺序传递信息,第二层按时间逆序传递信息。

没有去找双向LSTM的图了,就看这个双向RNN的结构来学习吧,理解了双向RNN,那么把循环层的记忆细胞换成LSTM就行。

2、双向LSTM隐状态的计算

关键在于隐状态如何计算。为了简单,还是按照双向RNN的公式进行理解,我们看隐状态如何计算。可以看到t时刻第一层(顺时间循环层)的隐状态ht(1)取决于前一时刻的隐状态ht-1(1)和输入值xt,这一点非常容易理解。

而要注意的是第二层(逆时间循环层)的隐状态则依然取决于前一时刻的隐状态和输入值x,这与堆叠的LSTM不同,堆叠的LSTM其l层的隐状态不由输入值x直接输入得到,而是取决于该层前一时刻的隐状态和当前时刻下一层的隐状态。如下的公式就是堆叠的循环网络层中隐状态的计算过程。

双向LSTM和堆叠的LSTM可以结合使用,在顺时间循环层我们可以构造堆叠多层的LSTM,同样,在逆时间循环层可以堆叠多个。

而双向LSTM的一个循环层中有两个隐状态,长期状态C用于内部传递信息,不抛头露面,而短期状态h则作为该循环层的输出,用于其他循环层或全连接层的计算。因此在对得的双向LSTM的最后一步,会有超过4个隐状态存在。

 

先上结论:

  1. output保存了最后一层,每个time step的输出h,如果是双向LSTM,每个time step的输出h = [h正向, h逆向] (同一个time step的正向和逆向的h连接起来)。
  2. h_n保存了每一层,最后一个time step的输出h,如果是双向LSTM,单独保存前向和后向的最后一个time step的输出h。
  3. c_n与h_n一致,只是它保存的是c的值。

下面单独分析三个输出:

  1. output是一个三维的张量,第一维表示序列长度,第二维表示一批的样本数(batch),第三维是 hidden_size(隐藏层大小) * num_directions ,这里是我遇到的第一个不理解的地方,hidden_sizes由我们自己定义,num_directions这是个什么鬼?翻看源码才明白,先贴出代码,从代码中可以发现num_directions根据是“否为双向”取值为1或2。因此,我们可以知道,output第三个维度的尺寸根据是否为双向而变化,如果不是双向,第三个维度等于我们定义的隐藏层大小;如果是双向的,第三个维度的大小等于2倍的隐藏层大小。为什么使用2倍的隐藏层大小?因为它把每个time step的前向和后向的输出连接起来了,后面会有一个实验,方便我们记忆。

 

 

2. h_n是一个三维的张量,第一维是num_layers*num_directions,num_layers是我们定义的神经网络的层数,num_directions在上面介绍过,取值为1或2,表示是否为双向LSTM。第二维表示一批的样本数量(batch)。第三维表示隐藏层的大小。第一个维度是h_n难理解的地方。首先我们定义当前的LSTM为单向LSTM,则第一维的大小是num_layers,该维度表示第n层最后一个time step的输出。如果是双向LSTM,则第一维的大小是2 * num_layers,此时,该维度依旧表示每一层最后一个time step的输出,同时前向和后向的运算时最后一个time step的输出用了一个该维度。

  • 举个例子,我们定义一个num_layers=3的双向LSTM,h_n第一个维度的大小就等于 6 (2*3),h_n[0]表示第一层前向传播最后一个time
    step的输出,h_n[1]表示第一层后向传播最后一个time step的输出,h_n[2]表示第二层前向传播最后一个time step的输出,h_n[3]表示第二层后向传播最后一个time step的输出,h_n[4]和h_n[5]分别表示第三层前向和后向传播时最后一个time step的输出。

3. c_n与h_n的结构一样,就不重复赘述了。

给出一个样例图(画工太差,如有错误请指正),对比前面的例子自己分析下

最后上一段代码结束战斗

import torch
import torch.nn as nn

定义一个两层双向的LSTM,input size为10,hidden size为20。

随机生成一个输入样本,sequence length为5,batch size为3,input size与定义的网络一致,为10。

手动初始化h0和c0,两个结构一致(num_layers * 2, batch, hidden_size) = (4, 3, 20)。

如果不初始化,PyTorch默认初始化为全零的张量。

bilstm = nn.LSTM(input_size=10, hidden_size=20, num_layers=2, bidirectional=True)
input = torch.randn(5, 3, 10)
h0 = torch.randn(4, 3, 20)
c0 = torch.randn(4, 3, 20)
output, (hn, cn) = bilstm(input, (h0, c0))

查看output,hn,cn的维度

print('output shape: ', output.shape)
print('hn shape: ', hn.shape)
print('cn shape: ', cn.shape)
输出:
output shape:  torch.Size([5, 3, 40])
hn shape:  torch.Size([4, 3, 20])
cn shape:  torch.Size([4, 3, 20])

根据一开始结论,我们来验证下。

1.前向传播时,output中最后一个time step的前20个与hn最后一层前向传播的输出应该一致。

output[4, 0, :20] == hn[2, 0]
输出:
tensor([ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
         1,  1,  1,  1,  1,  1], dtype=torch.uint8)

2.后向传播时,output中最后一个time step的后20个与hn最后一层后向传播的输出应该一致。

output[0, 0, 20:] == hn[3, 0]
输出:
tensor([ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
         1,  1,  1,  1,  1,  1], dtype=torch.uint8)

posted @ 2020-08-14 10:36  繁星春水  阅读(6551)  评论(0编辑  收藏  举报
1 //2 3
//4