RNN、LSTM、GRU学习资料记录

RNN、LSTM:人人都能看懂的LSTM
GRU:人人都能看懂的GRU
其他参考:
1、深度学习笔记——RNN(LSTM、GRU、双向RNN)学习总结
2、[tensorflow应用之路]RNN预测时间序列原理及LSTM/GRU算法实现
3、pytorch LSTM用于时间序列的分析

一、RNN

RNN:循环神经网络(Recurrent Neural Network,RNN)是一种用于处理序列数据的神经网络。

1、单个输入xx
RNN、LSTM、GRU学习资料记录
公式:f:h,y=f(h,x)f: h',y = f(h,x)
输入:xx为当前状态下数据的输入,hh为接收到上一个节点的输入
输出:yy为当前状态下本节点的输出,hh'为传递到下一个节点的输出

公式1:h=σ(Whh+Wix)h'=\sigma(W^hh+W^ix)
可以看出,输出hh',与hhxx的值都有关

公式2:y=σ(Woh)y=\sigma(W^oh')
yy则常常使用hh'投入到一个线性层(主要是进行维度映射)然后使用softmax进行分类得到需要的数据。
对这里的yy如何通过hh'计算得到往往看具体模型的使用方式。

2、序列输入x1,x2,x3...x^1,x^2,x^3...:
RNN、LSTM、GRU学习资料记录

二、LSTM

LSTM:长短期记忆(Long short-term memory, LSTM)是一种特殊的RNN,主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题。
简单来说,就是相比普通的RNN,LSTM能够在更长的序列中有更好的表现。

2.1 LSTM的输入输出

LSTM结构(图右)和普通RNN(图左)的主要输入输出区别如下所示。
RNN、LSTM、GRU学习资料记录
RNN只有一个传递状态hth^t,而LSTM有两个传递状态,一个ctc^t(cell state),和一个hth^t(hidden state)。(Tips:RNN中的hth^t对应于LSTM中的ctc^t
其中对于传递下去的ctc^t改变得很慢,通常输出的ctc^t是上一个状态传过来的ct1c^{t-1}加上一些数值。
hth^t则在不同节点下往往会有很大的区别。

2.2 LSTM的内部结构(计算公式)

1、首先使用LSTM的当前输入xtx^t和上一个状态传递下来的ht1h^{t-1}拼接训练,得到以下四个状态:
RNN、LSTM、GRU学习资料记录
RNN、LSTM、GRU学习资料记录
其中,ziz^izfz^fzoz^o 是由拼接向量乘以权重矩阵之后,再通过一个 sigmoidsigmoid**函数转换成0到1之间的数值,来作为一种门控状态。
sigmoid:s(x)=1/(1+e(x))sigmoid:s(x)=1/(1+e^{(-x)})
zz则是将结果通过一个tanhtanh**函数将转换成-1到1之间的值(这里使用tanhtanh是因为这里是将其做为输入数据,而不是门控信号)。

2、通过以下公式计算得到ctc^thth^tyty^t
RNN、LSTM、GRU学习资料记录
\bigodot是Hadamard Product,也就是操作矩阵中对应的元素相乘,因此要求两个相乘矩阵是同型的。
\bigoplus则代表进行矩阵加法。

2.3 LSTM原理解释

LSTM内部主要有三个阶段:
1、忘记阶段。
这个阶段主要是对上一个节点传进来的输入进行选择性忘记。简单来说就是会 “忘记不重要的,记住重要的”。

具体来说是通过计算得到的zfz^f(f表示forget)来作为忘记门控,来控制上一个状态的c(t1)c^{(t-1)}哪些需要留哪些需要忘。

2、选择记忆阶段。
这个阶段将这个阶段的输入有选择性地进行“记忆”。主要是会对输入xtx^t进行选择记忆。哪些重要则着重记录下来,哪些不重要,则少记一些。当前的输入内容由前面计算得到的zz表示。而选择的门控信号则是由ziz^i(i代表information)来进行控制。

将上面两步得到的结果相加,即可得到传输给下一个状态的ctc^t。也就是上图中的第一个公式。

3、输出阶段。
这个阶段将决定哪些将会被当成当前状态的输出。主要是通过zoz^o来进行控制的。并且还对上一阶段得到的coc^o进行了放缩(通过一个tanh**函数进行变化)。(上图中的第二个公式)

与普通RNN类似,输出yty^t往往最终也是通过hth^t变化得到。(上图中的第三个公式)

三、RNN和LSTM的总结、GRU的引入

以上,就是LSTM的内部结构。通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。

但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。

四、GRU

GRU(Gate Recurrent Unit)是RNN的一种。和LSTM一样,也是为了解决长期记忆和反向传播中的梯度等问题而提出来的。
相比LSTM,使用GRU能够达到相当的效果,并且相比之下更容易进行训练,能够很大程度上提高训练效率,因此很多时候会更倾向于使用GRU。

4.1 GRU的输入输出

和RNN一样:
RNN、LSTM、GRU学习资料记录

4.2 GRU的内部结构(计算公式)

1、通过上一个传输下来的状态h(t1)h^{(t-1)}和当前节点的输入xtx^t来获取两个门控状态。
如下图所示,其中rr控制重置的门控(reset gate),zz为控制更新的门控(update gate)。
RNN、LSTM、GRU学习资料记录
2、得到门控信号之后,首先使用重置门控来得到“重置”之后的数据 ht1=ht1r{h^{t-1}}' = h^{t-1}\bigodot r
再将ht1{h^{t-1}}'与输入xtx^t进行拼接,再通过一个tanh**函数来将数据放缩到-1~1的范围内。即得到如下图所示的hh'
RNN、LSTM、GRU学习资料记录
这里的hh'主要是包含了当前输入的xtx^t数据。有针对性地对hh'添加到当前的隐藏状态,相当于”记忆了当前时刻的状态“。类似于LSTM的选择记忆阶段。
RNN、LSTM、GRU学习资料记录
3、最后介绍GRU最关键的一个步骤,我们可以称之为”更新记忆“阶段。

在这个阶段,我们同时进行了遗忘和记忆两个步骤。我们使用了先前得到的更新门控zz(update gate)。

更新表达式:ht=zht1+(1z)hh^t = z \bigodot h^{t-1}+(1-z) \bigodot h'
输出表达式:yt=σ(Wht)y^t=\sigma(Wh^t)

首先再次强调一下,门控信号(这里的zz)的范围为0~1。门控信号越接近1,代表”记忆“下来的数据越多;而越接近0则代表”遗忘“的越多。

GRU很聪明的一点就在于,我们使用了同一个门控zz就同时可以进行遗忘和选择记忆(LSTM则要使用多个门控)。

  • zht1z \bigodot h^{t-1}:表示对原本隐藏状态的选择性“遗忘”。这里的 zz 可以想象成遗忘门(forget gate),忘记 ht1h^{t-1} 维度中一些不重要的信息。
  • (1z)h(1-z) \bigodot h' : 表示对包含当前节点信息的 hh' 进行选择性”记忆“。与上面类似,这里的 (1z)(1-z) 同理会忘记 hh' 维度中的一些不重要的信息。或者,这里我们更应当看做是对 hh' 维度中的某些信息进行选择。

结合上述,这一步的操作就是忘记传递下来的 ht1h^{t-1} 中的某些维度信息,并加入当前节点输入 hh' 的某些维度信息。

可以看到,这里的遗忘 zz 和选择 (1z)(1-z) 是联动的。也就是说,对于传递进来的维度信息,我们会进行选择性遗忘,则遗忘了多少权重 (zz),我们就会使用包含当前输入的 hh' 中所对应的权重进行弥补 (1z)(1-z) 。以保持一种”恒定“状态。

4.3 LSTM与GRU的关系

GRU是在2014年提出来的,而LSTM是1997年。
rr (reset gate)实际上与他的名字有点不符。我们仅仅使用它来获得了 hh'
那么这里的 hh' 实际上可以看成对应于LSTM中的 hth^t(hidden state);上一个节点传下来的 ht1h^{t-1} 则对应于LSTM中的 ctc^t(cell state)。
zz 对应的则是LSTM中的 zfz^f(forget gate),那么 (1z)(1-z) 我们似乎就可以看成是选择门 ziz^i 了。