RNN也就是循环神经网络,这个东西有着非常多的用途,尤其是在对于时间序列方面,可变长序列到序列或者说是在上下文模型中有着非常广泛的应用。现在论文中说到RNN,基本上说的就是LSTM,但是最近又有了GRU,用了比LSTM更少的gate,更少的参数,可以达到类似的效果。这篇博客主要是介绍RNN,LSTM的原理,以及举了一个程序的例子来说明如何用TF实现LSTM【1】。
RNN
对于DNN我们都很熟悉了,就是输入feature全链接到下一层的神经元,通过一个linear regression加到神经元,然后神经元上有一个激活函数,(一般来说,使用Sigmod函数做RNN的激活函数,使用ReLU会产生指数爆炸的问题,不过有一篇论文用ReLU训练RNN,居然比LSTM效果还好。CNN用的是ReLU,maxout,各种变形)然后输出的feature按照同样的方法堆几层,最后一个softmax输出结果。我们会发现DNN是insatnce的,他只考虑当前的状态,是一种MDP。所以它没有考虑之前的状态,但是在具体应用的时候,我们会发现在处理有些任务的时候,具有memory的网络才能够解决问题。比如我们进行视频行为分析,一个人的手停在半空中,你说他的手是要往上还是往下呢。只有结合之前的视频才能够更有效做出判断。所以我们给神经网络以记忆。这里还有一个特别有意思的视频,几分钟,但是把RNN和LSTM介绍得非常清楚,例子举的是关于吃饭的【3】,这个人的视频强推,真是不愧为MIT的phd,讲得特别清楚。
所以在RNN中就把前一个输出的hinding layer或者是output保存起来,然后在下一个有输入的时候,把保存的值输入进来。如下图所示:所以呢上一次的输出或者hinding layer就会影响下一个的输出,同时会更新存储的值【4】。
当然,这个RNN可以有多个隐层,如下图:不要看它是有这么多,其实它就是一个网络,表示的是不同的时刻。我们想想CPU的流水线,每过一个时刻,各个寄存器的状态就会更新,这里的寄存器就是memory,蓝色的箭头。
RNN的网络结构还有下图,其实总结起来就是要保存memory,但是这里的RNN一般会保存上一个状态的memory,通俗来说就是它只有上一个时刻的记忆。
这里的双向的RNN,训练的时候,比如训练一个sentence auto-encoder,下面的训练的输入时正向的,上面的输入正好和下面的sentence顺序相反,为什么要这么训练呢?我觉得这样的话就使得这个RNN有了prediction的功能。
其实熟悉DNN的话,其实就是在DNN的基础上加入了memory这个东西,同时把memory作为input。但是在training的时候就有了不少技巧。
RNN在训练的时候,会有gradient vanishing和gradient explode的情况。一个是指数爆炸,一个是后向传递的时候参数接近于0,权值没有被更新。使用LSTM可以解决gradient vanishing的问题,因为memory和input操作都是加法。【7】【8】在RNN的作者训练RNN的时候,增加了一个叫做Clipping的操作,将梯度限制在一定的范围内,不让它超过一定的范围。
LSTM
LSTM的图我们经常可以看到下图,基本上一脸懵逼,这是什么gui【5】【6】。
这里我们先来把整个框架画出来:在输入的地方有一个input gate,来判断输入是否有效。gate打开输入才会进入memory cell。在与memory gate相连的有一个Forget gate,这里的作用是是否把memory置为0,置为0就是Forget了。然后有一个输出Gate,是否对外进行输出。这些gate的开关都是由神经网络决定的(其实就是由输入的feature进行了一个linear regression,再输入到Gate function,某种激活函数,Sigmoid)。
下图中对memory cell进行了详细的解释: zi , z ,