承接上篇SimpleRNN, PyTorch中对于LSTM也有两个方法,即nn.LSTM和nn.LSTMCell。同样地,我们用两种方法来做一个简单例子的前馈。
先来看LSTMCell,实例化用到的参数如下:

from torch import nn

torch.nn.LSTMCell(input_size: int, hidden_size: int, bias: bool = True)

下面是官方文档中对于公式的说明以及参数的说明。
请注意:实例化后的LSTM(或LSTMCell)对象,其权重是pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习这四个矩阵的拼接,且其拼接顺序也是pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_02

pytorchSimclr损失函数代码实现 pytorch lstmcell_循环神经网络_03


这次我用的是台大李宏毅老师2020机器学习深度学习课程的一个例子,并且我人为做了一些改动。

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_04


规则是这样的:pytorchSimclr损失函数代码实现 pytorch lstmcell_神经网络_05,则更新记忆;pytorchSimclr损失函数代码实现 pytorch lstmcell_神经网络_06,则重置记忆;pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_07,则输出记忆。对于激活函数,老师在三个门控用的是sigmoid,把输入和输出的tanh换成了线性激活(也就是原样输出)。

pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_08


在PyTorch里面似乎是不能人为指定非线性激活函数的,所以只能用tanh函数作为输入和输出时的激活。观察pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_09函数的图像,我们可以发现,在pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_10这个区间里pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_09函数近似可以视作线性函数并且满足pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_12

pytorchSimclr损失函数代码实现 pytorch lstmcell_深度学习_13


因此我们把老师PPT上的输入序列稍微变一下,我们要保证pytorchSimclr损失函数代码实现 pytorch lstmcell_深度学习_14pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_10这个区间里。

pytorchSimclr损失函数代码实现 pytorch lstmcell_深度学习_16

0.2

0.1

-0.1

-0.2

0.25

pytorchSimclr损失函数代码实现 pytorch lstmcell_神经网络_17

1

1

0

0

-1

pytorchSimclr损失函数代码实现 pytorch lstmcell_深度学习_18

0

0

0

1

0

现在就让我们手动运作一下LSTMCell吧!

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_19

1

2

3

4

5







pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_20

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_21

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_21

pytorchSimclr损失函数代码实现 pytorch lstmcell_循环神经网络_23

0

0

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_24

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_25

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_25

pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_27

1

0

pytorchSimclr损失函数代码实现 pytorch lstmcell_神经网络_28

pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_29

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_30

pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_31

-0.2

0.25

pytorchSimclr损失函数代码实现 pytorch lstmcell_深度学习_32

pytorchSimclr损失函数代码实现 pytorch lstmcell_循环神经网络_23

pytorchSimclr损失函数代码实现 pytorch lstmcell_循环神经网络_23

pytorchSimclr损失函数代码实现 pytorch lstmcell_循环神经网络_23

1

0

pytorchSimclr损失函数代码实现 pytorch lstmcell_深度学习_36

pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_37

pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_38

pytorchSimclr损失函数代码实现 pytorch lstmcell_循环神经网络_39

0.3

0

pytorchSimclr损失函数代码实现 pytorch lstmcell_神经网络_40

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_41

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_41

pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_41

0.3

0

记住这里的pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_44,马上我们将拿他们与PyTorch运算结果对比。

import torch
from torch import nn
from torch.autograd import Variable


batch_size = 1
seq = 5
input_size, hidden = 3, 1
lstm_cell = nn.LSTMCell(input_size=input_size, hidden_size=hidden, bias=True)
lstm_cell.weight_ih.data = torch.Tensor([[0, 100, 0], [0, 100, 0],
                                         [1, 0, 0], [0, 0, 100]])  # 1
lstm_cell.weight_hh.data = torch.zeros(4, 1)  # 2
lstm_cell.bias_ih.data = torch.Tensor([-10, 10, 0, -10])  # 3
lstm_cell.bias_hh.data = torch.zeros(4)  # 4
x = Variable(torch.Tensor([[[0.2, 1, 0]],
                           [[0.1, 1, 0]],
                           [[-0.1, 0, 0]],
                           [[-0.2, 0, 1]],
                           [[0.25, -1, 0]]]))
h_n = Variable(torch.zeros(1, 1))
c_n = h_n.clone()
for step in range(seq):
    h_n, c_n = lstm_cell(x[step], (h_n, c_n))
    print('t=%d' % step)
    print('c=%.1f' % c_n.data)
    print('h=%.1f' % h_n.data)
    print('-' * 40)
nn.LSTM()

再次强调一下,实例化后的LSTM(或LSTMCell)对象,其权重是pytorchSimclr损失函数代码实现 pytorch lstmcell_机器学习_45这四个矩阵的拼接,且其拼接顺序也是pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_46,在#1处与#3处我是严格按照这个顺序赋值的。

在#2处和#4处,由于我们规则里当前时刻的行动(更新/重置/输出)只取决于当前时刻输入而与历史输入无关,所以理应给pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_47这些权重以及pytorchSimclr损失函数代码实现 pytorch lstmcell_循环神经网络_48这些偏置置零。

看一下运行结果:

pytorchSimclr损失函数代码实现 pytorch lstmcell_pytorch_49


如果我们用更简单的LSTM而不是LSTMCell:

batch_size = 1
seq = 5
input_size, hidden = 3, 1
lstm = nn.LSTM(input_size=input_size, hidden_size=hidden, bias=True, num_layers=1)
lstm.weight_ih_l0.data = torch.Tensor([[0, 100, 0], [0, 100, 0],
                                            [1, 0, 0], [0, 0, 100]])
lstm.weight_hh_l0.data = torch.zeros(4, 1)
lstm.bias_ih_l0.data = torch.Tensor([-10, 10, 0, -10])
lstm.bias_hh_l0.data = torch.zeros(4)
x = Variable(torch.Tensor([[[0.2, 1, 0]],
                           [[0.1, 1, 0]],
                           [[-0.1, 0, 0]],
                           [[-0.2, 0, 1]],
                           [[0.25, -1, 0]]]))
h_0 = Variable(torch.zeros(1, 1, 1))  # 1
c_0 = h_0.clone()
output, (h_n, c_n) = lstm(x, (h_0, c_0))
torch.set_printoptions(precision=1, sci_mode=False)
print('this is output:\n', output.data)
print('this is c_n:\n', c_n.data)
print('this is h_n:\n', h_n.data)

#1处的0初始化有没有都可以,如果不对pytorchSimclr损失函数代码实现 pytorch lstmcell_深度学习_50初始化的话,缺省值也是零向量或零矩阵。

运行结果:

pytorchSimclr损失函数代码实现 pytorch lstmcell_神经网络_51

c_n和h_n用于下一时间步输入,虽然这里已经结束了。

我们可以看到,这三次结果是相吻合的✌