Back

递归神经网络

Recurrent Neural Network

递归神经网络是神经网络的一种,与其他神经网络不同点在于,它可以很好地处理序列数据,即前面的数据的输入与后面的输出是有关系的,比如一句话的语义理解。本文介绍了递归神经网络及其两个变种——LSTM和GRU,目的是梳理一下自己所理解的RRN,也希望能够给初次接触RRN的同学一点帮助。

其他神经网络的不足——为什么需要RRN?

传统神经网络的结构大多为输入-隐藏层(多个)-输出,即给定一组输入数据,输出结果,隐藏层像一个黑盒子,通过各种运算把输入的数据算成需要的结果。输入不同的数据运行两次,它们的结果是完全无关的。而有的时候我们需要处理一个序列,比如一个句子,它是单词的序列,要理解这句话中各个单词的意思,必须要结合语境,也就是要结合其他的单词的意思,一般情况下要结合这个单词前面的单词。例如前面两个词是我、吃,那么后面的一个词很大概率是一个表示食物的名词。

为了解决一些这样类似的问题,能够更好的处理序列的信息,RNN就诞生了。

RNN的结构

循环神经网络也由输入层、隐藏层和输出层构成,这是神经网络的基本结构,不同的是它的隐藏层(也叫cell)可以连续的接收输入\(x\),输出\(o\),而贯穿其中的\(s\)可以存储这个网络的状态,也就是“记忆”到的前面发生的事情,利用它可以更加精准的预测后面的输出。

一个最简单的RNN结构如图所示,每一个cell输入一个\(x\)和一个\(s\),输出两个同样的\(h\),通过下列算法算出:

$$ \begin{aligned} &s_t = \tanh (Ws_{t-1} + Ux_t) \\&h_t = Vs_t \end{aligned} $$

这种简单的结构虽然可以达到记忆的效果,然而存在着一个致命的问题:梯度爆炸梯度消失。即在多次循环后,利用梯度下降法调整,在求导的时候会出现\(\frac{\partial Loss}{\partial w_i} = \frac{\partial Loss}{\partial f_t}\frac{\partial f_t}{\partial f_{t-1}}…\frac{\partial f_i}{\partial w_i} \),如果\(\frac{\partial f_t}{\partial f_{t-1}}\)部分大于或小于1,会出现类似1.01的99次方(或0.99的99次方)的问题,使得权重过大或过小,无法使用梯度下降。这一问题的根源就在于\(W\)和\(s\)之间的乘法运算。为了解决这一问题,Hochreiter, Schmidhuber(1997)提出了LSTM。

LSTM

LSTM全称Long Short Time Memory RRN,长短期记忆循环神经网络,它本质上也是一个循环神经网络,只是cell不一样而已,如下图:

LSTM的关键之处在于cell的状态,也就是图中贯穿顶部的那条水平线。Cell的状态像是一条传送带,它贯穿整条链,其中只发生一些小的线性作用。信息流过这条线而不改变是非常容易的。但是,LSTM也有能力移除或增加信息到cell状态中,由被称为门的结构精细控制。门是一种让信息可选地通过的方法。它们由一个sigmoid(\( S(t)={\frac {1}{1+e^{-t}}}\))神经网络层和一个点乘操作组成。这里的sigmoid函数取0-1的值,充当了开关的作用,控制影响的程度。

运行过程

从左往右看这幅图,首先第一步是决定我们需要从cell状态中扔掉什么样的信息。这个决策由一个称为“遗忘门(forget gate)”的sigmoid层决定。输入 \(h_{t-1}\) 和 \(x_t\) ,输出一个0和1之间的数。1代表“完全保留这个值”,而0代表“完全扔掉这个值”。比如对于一个基于上文预测最后一个词的语言模型。cell的状态可能包含当前主题的信息,来预测下一个准确的词。而当我们得到一个新的语言主题的时候,我们会想要遗忘旧的主题的记忆,应用新的语言主题的信息来预测准确的词。

第二步是决定我们需要在cell state里存储什么样的信息。这个问题有两个部分。第一,一个sigmoid层调用“输入门(input gate)”以决定哪些数据是需要更新的。然后,一个\(tanh\)层为新的候选值创建一个向量 \(\tilde{C}_t\) ,这些值能够加入state中。下一步,我们要将这两个部分合并以创建对state的更新。

比如还是语言模型,可以表示为想要把新的语言主题的信息加入到cell state中,以替代我们要遗忘的旧的记忆信息。

在决定需要遗忘和需要加入的记忆之后,就可以更新旧的cell state \(C_{t-1}\) 到新的cell state \(C_t\) 了。在这一步,我们把旧的state \(C_{t-1}\) 与 \(f_t\) 相乘,遗忘我们先前决定遗忘的东西,然后我们加上 \(i_t * \tilde{C}_t\) ,这可以理解为新的记忆信息,当然,这里体现了对状态值的更新度是有限制的,我们可以把 \(i_t\) 当成一个权重。

最后,我们需要决定要输出的东西。这个输出基于我们的cell state,但会是一个过滤后的值。首先,我们运行一个sigmoid层,这个也就是输出门(output gate),以决定cell state中的那个部分是我们将要输出的。然后我们把cell state放进\(tanh\)(将数值压到-1和1之间),最后将它与sigmoid门的输出相乘,这样我们就只输出了我们想要的部分了。

在LSTM中,状态\(S\)通过累加的方式来计算,\(S_t = \sum_{\tau=1}^t \Delta S_{\tau}\),这样就不会是一直复合函数的形式了,它的导数也不是乘积的形式,这样就不会发生梯度消失的情况了。(具体论文:An Empirical Exploration of Recurrent Network Architectures 和 Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling)

GRU

GRU全称Gated Recurrent Unit,循环门单元。和LSTM一样,他也只是个cell的种类,本质上是RNN,由 Cho, et al. (2014)提出。它将LSTM的遗忘门和输入门组合成了一个新的更新门,合并了cell state和hidden state,比LSTM更加简单(尽管稍微难理解一些)。

从左往右看,前两个门是reset gate和update gate,计算方法:

$$ \begin{aligned} &r_t = \sigma (W^rx_t + U^rh_{t-1}) \\&z_t = \sigma (W^zx_t + U^zh_{t-1}) \end{aligned} $$

reset gate控制在计算候选状态时使用多少前序的状态,update gate则表示计算新状态时候选状态和原状态各取多少比例(注意特殊的“1-”门,表示把\(z_t\)当作一个比例)。

总结和比较

RRN是神经网络的一个种类,LSTM和GRU是两种特殊的cell。与最基本的cell结构相比,LSTM和GRU都很好的解决了梯度爆炸和梯度消失的问题。对比LSTM,GRU的参数更少,因而训练稍快或需要更少的数据来泛化。另一方面,如果有足够的数据,LSTM的强大表达能力可能会产生更好的结果。Greff, et al. (2015)对流行的变种做了一个很好的比较,发现它们都是一样的。Jozefowicz, et al.(2015)测试了超过一万中RNN结构,发现某些任务情形下,有些比LSTM工作得更好,但那也是比较特殊的时候。

总的来说,没有通用的最好的模型,只能通过具体的数据和问题来选择模型。如果研究的数据序列会相互影响,比如做词语预测,那么LSTM-RRN和GRU-RRN不失为一种很好的选择。

参考:

Built with Hugo
Theme Stack designed by Jimmy