一、pytorch中LSTM实现原理:

对于输入序列中的每个元素,每层计算以下函数:
i t = σ ( W i i x t + b i i + W h i h t − 1 + b h i ) i_t = \sigma(W_{ii}x_t + b_{ii} + W_{hi}h_{t-1}+b_{hi}) it=σ(Wiixt+bii+Whiht1+bhi)
f t = σ ( W i f x t + b i f + W h f h t − 1 + b h f ) f_t = \sigma(W_{if}x_t + b_{if} + W_{hf}h_{t-1}+b_{hf}) ft=σ(Wifxt+bif+Whfht1+bhf)
o t = σ ( W i o x t + b i o + W h o h t − 1 + b h o ) o_t = \sigma(W_{io}x_t + b_{io} + W_{ho}h_{t-1}+b_{ho}) ot=σ(Wioxt+bio+Whoht1+bho)
g t = t a n h ( W i g x t + b i g + W h g h t − 1 + b h g ) g_t=tanh(W_{ig}x_t + b_{ig} + W_{hg}h_{t-1} + b_{hg}) gt=tanh(Wigxt+big+Whght1+bhg)
c t = f t ⊙ c t − 1 + i t ⊙ g t c_t=f_t \odot c_{t-1} + i_t \odot g_t ct=ftct1+itgt
h t = o t ⊙ t a n h ( c t ) h_t = o_t \odot tanh(c_t) ht=ottanh(ct)
其中各个变量的含义如下:

  • h t h_t ht:表示在t时间步的hidden state
  • c t c_t ct:表示在t时间步的cell state
  • x t x_t xt:表示在t时间步的输入
  • h t − 1 h_{t-1} ht1:表示在上个时间步的hidden state 或者在初始时间步的hidden state
  • i t i_t it, f t f_t ft, o t o_t ot表示输入门,遗忘门,输出门
  • σ \sigma σ:表示sigmoid函数
  • ⊙ \odot :表示点积
    在多层LSTM中, 第 l l l层的输入 x t ( l ) x_t^{(l)} xt(l)( l l l>=2)来自于前一层对应时间步的hidden state做dorpout的结果。

二、参数

1. 初始化参数
  • input_size:输入x的 维度
  • hidden_size:hidden state 的维度
  • num_layers:LSTM堆叠层数,设置num_layers=2 的话,表示堆叠两层LSTM到一起,第二个 LSTM 接收第一个 LSTM 的输出并计算最终结果;默认为1
  • bias:如果是False,将不再加入 b_h和b_hh,默认为True
  • batch_first:如果为True,则输入和输出的tensors的维度为(batch,seq,feature)而不是(seq,batch,feature)。注意:此标识只对output有效,对hidden state 和 cell state无效,默认为False
  • dorpout:如果为非0,在每个 LSTM 层(最后一层除外)的输出上引入一个dropout层,dropout概率等于此参数值。默认值:0,只对多层LSTM有效。
  • bidirectional:如果为True,则是双向LSTM,默认为False
  • proj_size:如果>0,将使用具有相应大小的投影的 LSTM。
2. forward入参
  • Input:单个样本(unbatched)输入,则形状为 ( L , H i n ) (L, H_{in}) (L,Hin);batch_first=False,则形状为 ( L , N , H i n ) (L,N,H_{in}) (L,N,Hin);batch_first=True,则形状为 ( N , L , H i n ) (N,L,H_{in}) (N,L,Hin)。输入也可以是打包的可变长度序列。参考packedtorch.nn.utils.rnn.pack_padded_sequence() h或者torch.nn.utils.rnn.pack_sequence() 方法。
  • h_0:单个样本(unbatched)输入,形状为 ( D ∗ n u m l a y e r s , H o u t ) (D*num_layers, H_out) (Dnumlayers,Hout);batch样本输入,则形状为 ( D ∗ n u m l a y e r s , N , H o u t ) (D*num_layers, N, H_out) (Dnumlayers,N,Hout)也就是初始化的hidden state, 默认为0(h_0, c_0)。
  • c_0:单个样本(unbatched)输入,形状为 ( D ∗ n u m l a y e r s , H c e l l ) (D*num_layers, H_cell) (Dnumlayers,Hcell);batch样本输入,则形状为 ( D ∗ n u m l a y e r s , N , H c e l l ) (D*num_layers, N, H_cell) (Dnumlayers,N,Hcell)也就是初始化的hidden state, 默认为0(h_0, c_0)。
    其中:
  • N=batch size
  • L=sequence length
  • D=2 if bidirectional=True otherwise 1
  • H i n H_{in} Hin=input_size
  • H c e l l H_{cell} Hcell=hidden_size
  • H o u t H_{out} Hout=hidden_size
3. 输出
  • output:单个样本(unbatched)输入,则形状为 ( L , D ∗ H o u t ) (L, D*H_{out}) (L,DHout);batch_first=False,则形状为 ( L , N , D ∗ H o u t ) (L,N,D*H_{out}) (L,N,DHout);batch_first=True,则形状为 ( N , L , D ∗ H o u t ) (N,L,D*H_{out}) (N,L,DHout)。输入也可以是打包的可变长度序列。参考packedtorch.nn.utils.rnn.pack_padded_sequence() h或者torch.nn.utils.rnn.pack_sequence() 方法。
  • h_0:单个样本(unbatched)输入,形状为 ( D ∗ n u m l a y e r s , H o u t ) (D*num_layers, H_out) (Dnumlayers,Hout);batch样本输入,则形状为 ( D ∗ n u m l a y e r s , N , H o u t ) (D*num_layers, N, H_out) (Dnumlayers,N,Hout),包含序列中每个元素的最终隐藏状态。当双向 = True 时,h_n将分别包含最终正向和反向隐藏状态的串联。
  • c_0:单个样本(unbatched)输入,形状为 ( D ∗ n u m l a y e r s , H c e l l ) (D*num_layers, H_cell) (Dnumlayers,Hcell);batch样本输入,则形状为 ( D ∗ n u m l a y e r s , N , H c e l l ) (D*num_layers, N, H_cell) (Dnumlayers,N,Hcell),包含序列中每个元素的最终cell状态。

三、实例

1)
import torch.nn as nn
import torch
rnn = nn.LSTM(10, 20, 2)# embedding_size, hidden_size, num_layer
input = torch.randn(5, 3, 10)# sequence length, batch size, embedding_size
h0 = torch.randn(2, 3, 20)# num_layer*dirc, batch size, hidden_size
c0 = torch.randn(2, 3, 20)# num_layer*dirc, batch size, hidden_size
output, (hn, cn) = rnn(input, (h0, c0))
output.shape
Out[8]: torch.Size([5, 3, 20])# # sequence length, batch size, hidden_size
hn.shape
Out[9]: torch.Size([2, 3, 20])# num_layer*dirc, batch size, hidden_size
c0.shape
Out[10]: torch.Size([2, 3, 20])# num_layer*dirc, batch size, hidden_size
2)
rnn = nn.LSTM(input_size=1, hidden_size=20, num_layers=2)
input = torch.tensor([[1,2,0], [3,0,0], [4,5,6]], dtype=torch.float)
lens = [2, 1, 3]
# 构建输入数据,维度为:torch.Size([3, 3, 1]), 即 bactch_size=3, sequence length=3, embedding size=1
input = input.unsqueeze(2)
input
Out[68]: 
tensor([[[1.],
         [2.],
         [0.]],
        [[3.],
         [0.],
         [0.]],
        [[4.],
         [5.],
         [6.]]])
# 第一维是 batch,则batch_first=True,
padded_seq = pack_padded_sequence(input, lens, batch_first=True, enforce_sorted=False)
# 将 padded_seq输入,并且不对hidden和cell进行初始化
output, (hn, cn) = rnn(padded_seq)
# 进行逆操作拆箱
output = pad_packed_sequence(output, batch_first=True)
# output[0] LSTM输出,output[1]为batch中样本长度
output[0].shape
Out[72]: torch.Size([3, 3, 20])
output[1]
Out[73]: tensor([2, 1, 3])
hn.shape
Out[76]: torch.Size([2, 3, 20])
cn.shape
Out[77]: torch.Size([2, 3, 20])

未完待续。。。

10-10 18:58