对于一些情景,例如自然语言处理 (NLP, Natural Language Processing) 或者我们需要分析类似于连拍照片这样的数据时,合理运用t或之前的输入来处理t+n时刻显然可以更加合理的运用输入的信息。为了运用到时间维度上信息,人们设计了递归神经网络 (RNN, Recurssion Neural Network)。
-
RNN
在图中, x t x_t xt 是在 t t t时刻的输入信息, h t h_t ht是在 t t t
时刻的输出信息,我们可以看到神经元A会递归的调用自身并且将 t - 1 时刻的信息传递给 t t t时刻。 -
LSTM
是一种特殊的RNN网络。
从被设计之初就被用于解决一般递归神经网络中普遍存在的长期依赖问题,使用LSTM可以有效的传递和表达长时间序列中的信息并且不会导致长时间前的有用信息被忽略(遗忘)。与此同时,LSTM还可以解决RNN中的梯度消失/爆炸问题。
- 在一个时间序列中,不是所有信息都是同等有效的,大多数情况存在“关键词”或者“关键帧”。
- 我们会在从头到尾阅读的时候“自动”概括已阅部分的内容并且用之前的内容帮助理解后文。
基于以上这两点,LSTM的设计者提出了“长短期记忆”的概念——只有一部分的信息需要长期的记忆,而有的信息可以不记下来。同时,我们还需要一套机制可以动态的处理神经网络的“记忆”,因为有的信息可能一开始价值很高,后面价值逐渐衰减,这时候我们也需要让神经网络学会“遗忘”特定的信息。
一个普通的,使用tanh函数的RNN可以这么表示:
在这里,我们可以看到A在t - 1时刻的输出值
h
t
−
1
h_{t - 1}
ht−1被复制到了t时刻,与t时刻的输入
x
t
x_t
xt 整合后经过一个带权重和偏置的tanh函数后形成输出,并继续将数据复制到t + 1时刻……
与上图朴素的RNN相比,单个LSTM单元拥有更加复杂的内部结构和输入输出:
我们可以将神经元的隐藏态简单的理解成递归神经网络对于输入数据的“记忆”,用
C
t
C_t
Ct表示神经元在t时刻过后的“记忆”,这个向量涵盖了在t+1时刻前神经网络对于所有输入信息的“概括总结”。
遗忘门
每一次输入一个新的输入,LSTM会先根据新的输入和上一时刻的输出决定遗忘掉之前的哪些记忆——输入和上一步的输出会整合为一个单独的向量,然后通过sigmoid神经层,最后点对点的乘在单元状态上。
因为sigmoid 函数会将任意输入压缩到 (0 , 1)的区间上,如果整合后的向量某个分量在通过sigmoid层后变为0,那么显然单元状态在对位相乘后对应的分量也会变成0,换句话说,“遗忘”了这个分量上的信息;如果某个分量通过sigmoid层后为1,单元状态会“保持完整记忆”。
不同的sigmoid输出会带来不同信息的记忆与遗忘。通过这种方式,LSTM可以长期记忆重要信息,并且记忆可以随着输入进行动态调整。
下面的公式可以用来描述遗忘门的计算,其中
f
t
f_t
ft
就是sigmoid神经层的输出向量:
f
t
=
σ
(
W
f
.
[
h
t
−
1
,
x
t
]
+
b
f
f_t = \sigma(W_f . [h_{t - 1}, x_t] + b_f
ft=σ(Wf.[ht−1,xt]+bf
记忆门
记忆门是用来控制是否将在 t 时刻(现在)的数据并入单元状态中的控制单位。
首先,用tanh函数层将现在的向量中的有效信息提取出来,然后使用(图上tanh函数层左侧)的sigmoid函数来控制这些记忆要放“多少”进入单元状态。
这两者结合起来就可以做到:
- 从当前输入中提取有效信息
C t ′ = t a n h ( W c . [ h t − 1 , x t ] + b c ) C_t ^{'} = tanh(W_c . [h_{t -1}, x_t] + b_c ) Ct′=tanh(Wc.[ht−1,xt]+bc) - 对提取的有效信息做出筛选,为每个分量做出评级(0 ~ 1),评级越高的最后会有越多的记忆进入单元状态
i t = σ ( W i . [ h t − 1 , x t ] + b i ) i_t = \sigma(W_i . [h_{t-1}, x_t] + b_i) it=σ(Wi.[ht−1,xt]+bi)
单元状态的更新公式如下:
C
t
=
f
t
∗
C
t
−
1
+
i
t
∗
C
~
t
C_t = f_t * C_{t - 1} + i_t * \widetilde{C}_t
Ct=ft∗Ct−1+it∗C
t
输出门
LSTM单元用于计算当前时刻的输出值的神经层。输出层会先将当前输入值与上一时刻输出值整合后的向量(也就是公式中的
[
h
t
−
1
,
x
t
]
[h_{t-1} ,x_t]
[ht−1,xt])用sigmoid函数提取其中的信息,接着,会将当前的单元状态通过tanh函数压缩映射到区间(-1, 1)中。
- 在LSTM的输入和输出门中使用tanh函数有以下几个原因:
- 为了防止梯度消失问题,我们需要一个二次导数在大范围内不为0的函数,而tanh函数可以满足这一点
- 为了便于凸优化,我们需要一个单调函数
- tanh函数一般收敛的更快
- tanh函数的求导占用系统的资源更少
输出门决定下一个隐藏状态是什么。隐藏状态包含有关先前输入的信息。隐藏状态也用于预测。
首先,我们将先前的隐藏状态和当前输入传递给sigmoid函数。然后我们将新的单元状态传递给tanh函数。
将tanh输出与sigmoid输出相乘,以决定隐藏状态应携带的信息。它的输出是隐藏状态。然后将新的单元状态和新的隐藏状态传递到下一个时间步。
o t = σ ( W o [ h t − 1 , x t ] + b o ) h t = o t ∗ t a n h ( C t ) o_t = \sigma( W_o[h_{t - 1}, x_t] + b_o)\\ h_t = o_t * tanh(C_t) ot=σ(Wo[ht−1,xt]+bo)ht=ot∗tanh(Ct)
小结
- 遗忘门决定了哪些内容与前面的时间步相关。
- 输入门决定了从当前时间步添加哪些信息。
- 输出门决定下一个隐藏状态应该是什么。