前言 🏷️在介绍LSTM模型之前,我们再次见一下CNN是什么?RNN主要用于序列处理,比如机器翻译,这种输入输出序列之间具有高度的相关性,RNN可以model这种关系,总结一下,按照输入输出的类型,RNN可以做以下几个事情:
🏷️接下来我们先简单介绍传统的RNN模型,了解其优缺点
根据反向传播算法和链式法则, 梯度的计算可以简化为以下公式
Dn=σ′(z1)w1⋅σ′(z2)w2⋅⋯⋅σ′(zn)wn𝐷𝑛=𝜎′(𝑧1)𝑤1⋅𝜎′(𝑧2)𝑤2⋅⋯⋅𝜎′(𝑧𝑛)𝑤𝑛
LSTM(Long Short-Term Memory)也称长短时记忆结构, 它是传统RNN的变体, 与经典RNN相比能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆炸现象. 同时LSTM的结构更复杂, 它的核心结构可以分为四个部分去解析:
黄色方块:表示一个神经网络层(Neural Network Layer); 粉色圆圈:表示按位操作或逐点操作(pointwise operation),例如向量加和、向量乘积等; 单箭头:表示信号传递(向量传递); 合流箭头:表示两个信号的连接(向量拼接); 分流箭头:表示信号被复制后传递到2个不同的地方
🏷️这里面的计算公式,包括接下来我们也要介绍的,有很多与RNN的计算公式相似,我们也可以通过RNN的思想去一步一步理解每一个结构的含义以及作用
# 定义LSTM的参数含义: (input_size, hidden_size, num_layers)
# 定义输入张量的参数含义: (sequence_length, batch_size, input_size)
# 定义隐藏层初始张量和细胞初始状态张量的参数含义:
# (num_layers * num_directions, batch_size, hidden_size)
>>> import torch.nn as nn
>>> import torch
>>> rnn = nn.LSTM(5, 6, 2)
>>> input = torch.randn(1, 3, 5)
>>> h0 = torch.randn(2, 3, 6)
>>> c0 = torch.randn(2, 3, 6)
>>> output, (hn, cn) = rnn(input, (h0, c0))
>>> output
tensor([[[ 0.0447, -0.0335, 0.1454, 0.0438, 0.0865, 0.0416],
[ 0.0105, 0.1923, 0.5507, -0.1742, 0.1569, -0.0548],
[-0.1186, 0.1835, -0.0022, -0.1388, -0.0877, -0.4007]]],
grad_fn=<StackBackward>)
>>> hn
tensor([[[ 0.4647, -0.2364, 0.0645, -0.3996, -0.0500, -0.0152],
[ 0.3852, 0.0704, 0.2103, -0.2524, 0.0243, 0.0477],
[ 0.2571, 0.0608, 0.2322, 0.1815, -0.0513, -0.0291]],
[[ 0.0447, -0.0335, 0.1454, 0.0438, 0.0865, 0.0416],
[ 0.0105, 0.1923, 0.5507, -0.1742, 0.1569, -0.0548],
[-0.1186, 0.1835, -0.0022, -0.1388, -0.0877, -0.4007]]],
grad_fn=<StackBackward>)
>>> cn
tensor([[[ 0.8083, -0.5500, 0.1009, -0.5806, -0.0668, -0.1161],
[ 0.7438, 0.0957, 0.5509, -0.7725, 0.0824, 0.0626],
[ 0.3131, 0.0920, 0.8359, 0.9187, -0.4826, -0.0717]],
[[ 0.1240, -0.0526, 0.3035, 0.1099, 0.5915, 0.0828],
[ 0.0203, 0.8367, 0.9832, -0.4454, 0.3917, -0.1983],
[-0.2976, 0.7764, -0.0074, -0.1965, -0.1343, -0.6683]]],
grad_fn=<StackBackward>)
LSTM的内部结构可能只通过文字讲述会有些抽象,内部结构相对来说复杂,我们可以通过将其拆分一一分析,我们不难发现他和RNN算法的相同之处,本质都是相同,下节我们介绍复杂度相对来说没有那么复杂的GRU模型