塞进裤子ヾ(≧O≦)〃嗷~

0%

pytorch-lstm理解

pytorch的LSTM比较复杂,所以单独拿出来说了。

LSTM

1
2
3
nn.LSTM()参数:
input_size, hidden_size,num_layers=1, bias=True, batch_first=False,
dropout=0., bidirectional=False

input_size和hidden_size什么区别?

input_size看作embedding dim,hidden_size看作W的第一维(也可能是最后一维).

https://zhuanlan.zhihu.com/p/79064602

  • 输入
    input (seq_len, batch, input_size)

    seq_len:每个句子的长度(句子中单词的个数),batch:每次喂多少个句子,input_size:每个单词用多少维的向量表示。

    h_0 (num_layers * num_directions, batch, hidden_size)
    c_0 (num_layers * num_directions, batch, hidden_size)

    $h_0$和$c_0$是隐藏层的初始状态。num_directions取值为1或2,表示是否为双向LSTM

  • 输出
    output (seq_len, batch, num_directions * hidden_size)
    h_n (num_layers * num_directions, batch, hidden_size)
    c_n (num_layers * num_directions, batch, hidden_size)
1
2
3
4
5
6
7
8
9
lstm = nn.LSTM()
out, (hn,cn) = lstm(input,(h0,c0))

#out是每一个时间步的最后一个隐藏层h的输出,假如有5个时间步(即seq_len=5),则有5个对应的输出,out的维度是:(batch_size,seq_len,hidden_size)
#而hidden=(hn,cn)是个tuple,他自己实现了时间步的迭代,每次迭代需要使用上一步的输出和hidden层,最后一步hidden=(hn,cn)记录了最后一各时间步的隐藏层输出,有几层对应几个输出,如果这个是RNN-encoder,则hn,cn就是中间的编码向量。hn的维度是(num_layers*num_directions,batch_size,hidden_size),cn同。

# LSTM第一个返回的第一个值out是所有时刻的隐藏状态,第二个返回值hidden是最后一个时刻的隐藏状态(所以"out"的最后一个和"hidden"是一样的)
# 之所以这样设计:
# 通过"out"你能取得任何一个时刻的隐藏状态,而"hidden"的值是用来进行序列的反向传播运算, 具体方式就是将它作为参数传入后面的 LSTM 网络.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
torch.manual_seed(666)

lstm = nn.LSTM(input_size=3,hidden_size=3,batch_first = False)
inputs = [torch.randn(1,3) for _ in range(5)] #生成[5,1,3]的tensor
#每个句子由5个单词组成,每次喂一个句子,每个单词用3维向量表示

#LSTM隐藏层初始状态hidden=(h0,c0)
# h0的size【num_layers*num_directions, batch, hidden_size】
hidden = (torch.randn(1,1,3),torch.randn(1,1,3))


for i in inputs:
# print(i.shape)
# print(i.view(1,1,-1).shape)
#原来i是【1,3】,view后【1,1,3】每个句子由一个单词组成,每次喂一个句子,每个单词用3维向量表示
out, hidden = lstm(i.view(1,1,-1), hidden)

print(out)
print(hidden)
============
tensor([[[-0.0829, -0.0303, -0.0159]]], grad_fn=<StackBackward>)
(tensor([[[-0.0829, -0.0303, -0.0159]]], grad_fn=<StackBackward>), tensor([[[-0.2609, -0.1045, -0.0260]]], grad_fn=<StackBackward>))
#因为将inputs拆开了,seqlen=1,所以out大小是【1,1,3】

将inputs作为整个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
lstm = nn.LSTM(input_size=3,hidden_size=3,batch_first = False)
inputs = [torch.randn(1,3) for _ in range(5)] #生成[5,1,3]的tensor
#每个句子由5个单词组成,每次喂一个句子,每个单词用3维向量表示

hidden = (torch.randn(1,1,3),torch.randn(1,1,3))
inputs = torch.cat(inputs).view(len(inputs), 1, -1)# view成【5,1,3】
out,hidden = lstm(inputs , hidden)
print(out)
print(hidden)
=============
tensor([[[-0.0993, -0.0931, -0.0385]],
[[-0.0105, -0.2537, 0.0181]],
[[-0.1399, -0.1463, -0.0351]],
[[-0.3232, 0.0147, -0.1156]],
[[-0.0829, -0.0303, -0.0159]]], grad_fn=<StackBackward>)
(tensor([[[-0.0829, -0.0303, -0.0159]]], grad_fn=<StackBackward>), tensor([[[-0.2609, -0.1045, -0.0260]]], grad_fn=<StackBackward>))
if help:小手一抖点个广告 or 大手一挥资助一下