您好,欢迎访问三七文档
RNN循环神经网络(RecurrentNeuralNetworks,RNNs)已经在众多自然语言处理(NaturalLanguageProcessing,NLP)中取得了巨大成功以及广泛应用,RNNs主要用来处理序列数据。RNNs包含输入单元(Inputunits),输入集标记为011{,,...,,,...}ttxxxx;输出单元(Outputunits)的输出集则被标记为011{,,...,,,...}ttyyyy;隐藏单元(Hiddenunits),将其输出集标记为011{,,...,,,...}ttssss。在图中:有一条单向流动的信息流是从输入单元到达隐藏单元的,与此同时另一条单向流动的信息流从隐藏单元到达输出单元。在某些情况下,RNNs会打破后者的限制,引导信息从输出单元返回隐藏单元,这些被称为“BackProjections”,并且隐藏层的输入还包括上一隐藏层的状态,即隐藏层内的节点可以自连也可以互连。上图将循环神经网络进行展开成一个全神经网络。例如,对一个包含5个单词的语句,那么展开的网络便是一个五层的神经网络,每一层代表一个单词。对于该网络的计算过程如下:1.tx表示第t,t=1,2,3...步(step)的输入。比如1x为第二个词的one-hot向量(根据上图,0x为第一个词);2.ts为隐藏层的第t步的状态,它是网络的记忆单元。ts根据当前输入层的输出与上一步隐藏层的状态进行计算。1()tttsfUxWs,其中f一般是非线性的激活函数,如tanh或ReLU,在计算0s时,即第一个单词的隐藏层状态,需要用到-1s,但是其并不存在,在实现中一般置为0向量;3.to是第t步的输出,如下个单词的向量表示,Softmax()ttoVs需要注意的是:1.你可以认为隐藏层状态ts是网络的记忆单元。ts包含了前面所有步的隐藏层状态。而输出层的输出to只与当前步的ts有关,在实践中,为了降低网络的复杂度,往往ts只包含前面若干步而不是所有步的隐藏层状态;2.在RNNs中,每输入一步,每一层各自都共享参数U、V、W。其反应了RNNs中的每一步都在做相同的事,只是输入不同,因此大大地降低了网络中需要学习的参数。3.上图中每一步都会有输出,但不是必须的。比如我们需要预测一条语句所表达的情绪,我们仅仅需要关心最后一个单词输入后的输出,而不需要知道每个单词输入后的输出,同理每步都需要输入也不是必须的。RNNs的关键之处在于隐藏层,隐藏层能够捕捉序列的信息。这个网络在t时刻接收到输入tx之后,隐藏层的值是ts,输出值是to。关键一点是,ts的值不仅仅取决于tx,还取决于-1ts。我们可以用下面的公式来表示循环神经网络的计算方法:()ttogVs(式1)(1)1()tttsfUxWs(式2)(2)式1是输出层的计算公式,输出层是一个全连接层,也就是它的每个节点都和隐藏层的每个节点相连。V是输出层的权重矩阵,g是激活函数。式2是隐藏层的计算公式,它是循环层。U是输入x的权重矩阵,W是上一次的值1ts作为这一次的输入的权重矩阵,f是激活函数。从上面的公式我们可以看出,循环层和全连接层的区别就是循环层多了一个权重矩阵W。如果反复把式2带入到式1,我们将得到:()ttogVs(3)1(())ttgVfUxWs(4)12(((()))tttgVfUxWfUxWs(5)123(((((())))ttttgVfUxWfUxWfUxWs(6)123((((((((...)))))ttttgVfUxWfUxWfUxWfUx(7)从上面可以看出,循环神经网络的输出值to,是受前面历次输入值123ttttxxxx、、、、...影响的,这就是为什么循环神经网络可以往前看任意多个输入值的原因。1.训练算法如果将RNNs进行网络展开,那么参数W、U、V是共享的,并且在使用梯度下降算法中,每一步的输出不仅依赖当前步的网络,还依赖前面若干步网络的状态。比如,在t=4时,我们还需要向后传递三步,后面的三步都需要加上各种的梯度。该学习算法称为BackpropagationThroughTime(BPTT)。BPTT算法是针对循环层的训练算法,它的基本原理和BP算法是一样的,也包含同样的三个步骤:1)前向计算每个神经元的输出值;2)反向计算每个神经元的误差项值j,它是误差函数E对神经元j的加权输入的jnet偏导数;3)计算每个权重的梯度。最后再用随机梯度下降算法更新权重。需要意识到的是,在vanillaRNNs训练中,BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来所谓的梯度消失或梯度爆炸问题(thevanishing/explodinggradientproblem)。2.前向计算使用前面的式2对循环层进行前向计算:1()tttsfUxWs注意,上面的1tttsxs、、都是向量,用黑体字母表示;而U、V是矩阵,用大写字母表示。向量的下标表示时刻,例如,ts表示在t时刻向量s的值。我们假设输入向量x的维度是m,输出向量s的维度是n,则矩阵U的维度是nm,矩阵W的维度是nn。下面是上式展开成矩阵的样子,看起来更直观一些:3.误差项的计算BTPP算法将第l层t时刻的误差项值lt沿两个方向传播,一个方向是其传递到上一层网络,得到-1lt,这部分只和权重矩阵U有关;另一个是方向是将其沿时间线传递到初始时刻1t,得到1l,这部分只和权重矩阵W有关。我们用向量tnet表示神经元在t时刻的加权输入,因为:因此:我们用a表示列向量,Ta用表示行向量。上式的第一项是向量函数对向量求导,其结果为Jacobian矩阵:同理,上式第二项也是一个Jacobian矩阵:其中,diag[a]表示根据向量a创建一个对角矩阵,即最后,将两项合在一起,可得:上式描述了将沿时间往前传递一个时刻的规律,有了这个规律,我们就可以求得任意时刻k的误差项k:式3就是将误差项沿时间反向传播的算法。循环层将误差项反向传递到上一层网络,与普通的全连接层是完全一样的,这在前面的文章零基础入门深度学习(3)---神经网络和反向传播算法中已经详细讲过了,在此仅简要描述一下。循环层的加权输入lnet与上一层的加权输入-1lnet关系如下:上式中ltnet是第l层神经元的加权输入(假设第l层是循环层);-1ltnet是第l-1层神经元的加权输入;-1lta是第l-1层神经元的输出;1lf是第l-1层的激活函数。所以,式4就是将误差项传递到上一层算法。4.权重梯度的计算现在,我们终于来到了BPTT算法的最后一步:计算每个权重的梯度。首先,我们计算误差函数E对权重矩阵W的梯度EW。上图展示了我们到目前为止,在前两步中已经计算得到的量,包括每个时刻t循环层的输出值ts,以及误差项t。全连接网络的权重梯度计算算法:只要知道了任意一个时刻的误差项t,以及上一个时刻循环层的输出值1ts,就可以按照下面的公式求出权重矩阵在t时刻的梯度tWE:在式5中,ti表示t时刻误差项向量的第i个分量;1tis表示t-1时刻循环层第i个神经元的输出值。我们下面可以简单推导一下式5。我们知道:因为对W求导与tUx无关,我们不再考虑。现在,我们考虑对权重项jiw求导。通过观察上式我们可以看到jiw只与tjnet有关,所以:按照上面的规律就可以生成式5里面的矩阵。我们已经求得了权重矩阵W在t时刻的梯度tWE,最终的梯度WE是各个时刻的梯度之和:式6就是计算循环层权重矩阵W的梯度的公式。下面解释为什么最终的梯度是各个时刻的梯度之和?我们还是从这个式子开始:1()tttnetUxWfnet因为tUx与W完全无关,我们把它看做常量。现在,考虑第一个式子加号右边的部分,因为W和1()tfnet都是W的函数,因此我们要用到大学里面都学过的导数乘法运算:()uvuvuv因此,上面第一个式子写成:11()=()tttnetfnetWfnet我们最终需要计算的是WE:我们先计算式7加号左边的部分。WW是矩阵对矩阵求导,其结果是一个四维张量(tensor),如下所示:接下来,我们知道11()ttsfnet,它是一个列向量。我们让上面的四维张量与这个向量相乘,得到了一个三维张量,再左乘行向量Tt,最终得到一个矩阵:接下来,我们计算式7加号右边的部分:于是,我们得到了如下递推公式:这样,我们就证明了:最终的梯度WE是各个时刻的梯度之和。同权重矩阵W类似,我们可以得到权重矩阵U的计算方法。式8是误差函数在t时刻对权重矩阵U的梯度。和权重矩阵W一样,最终的梯度也是各个时刻的梯度之和:1=itUUiEE5.梯度爆炸和消失问题不幸的是,实践中前面介绍RNN并不能很好的处理较长的序列。一个主要的原因是,RNN在训练中很容易发生梯度爆炸和梯度消失,这导致训练时梯度不能在较长序列中一直传递下去,从而使RNN无法捕捉到长距离的影响。为什么RNN会产生梯度爆炸和消失问题呢?我们接下来将详细分析一下原因。我们根据式3可得:上式的定义为矩阵的模的上界。因为上式是一个指数函数,如果t-k很大的话(也就是向前看很远的时候),会导致对应的误差项的值增长或缩小的非常快,这样就会导致相应的梯度爆炸和梯度消失问题(取决于大于1还是小于1)。通常来说,梯度爆炸更容易处理一些。因为梯度爆炸的时候,我们的程序会收到NaN错误。我们也可以设置一个梯度阈值,当梯度超过这个阈值的时候可以直接截取。梯度消失更难检测,而且也更难处理一些。总的来说,我们有三种方法应对梯度消失问题:1)合理的初始化权重值。初始化权重,使每个神经元尽可能不要取极大或极小值,以躲开梯度消失的区域。2)使用relu代替sigmoid和tanh作为激活函数。3)使用其他结构的RNNs,比如长短时记忆网络(LTSM)和GatedRecurrentUnit(GRU),这是最流行的做法。LSTM长短时记忆网络(LongShortTermMemoryNetwork,LSTM),它成功的解决了原始循环神经网络的缺陷,成为当前最流行的RNN,在语音识别、图片描述、自然语言处理等许多领域中成功应用。原始RNN的隐藏层只有一个状态h,它对于短期的输入非常敏感。那么,假如我们再增加一个状态c,让它来保存长期的状态。如下图所示:新增加的状态c,称为单元状态(cellstate)。我们把上图按照时间维度展开:上图仅仅是一个示意图,我们可以看出,在t时刻,LSTM的输入有三个:当前时刻网络的输入值tx、上一时刻LSTM的输出值1th以及上一时刻的单元状态1tc;LSTM的输出有两个:当前时刻LSTM输出值th和当前时刻的单元状态tc。注意x、c、h都是向量。LSTM的关键,就是怎样控制长期状态c。在这里,LSTM的思路是使用三个控制开关。第一个开关,负责控制继续保存长期状态c;第二个开关,负责控制把即时状态输入到长期状态c;第三个开关,负责控制是否把长期状态c作为当前的LSTM的输出。三个开关的作用如下图所示:1.前向计算前面描述的开关是怎样在算法中实现的呢?这就用到了门(gate)的概念。门实际上就是一层全连接层,它的输入是一个向量,输出是一个0到1之间的实数向量。假设W是门的权重向量,b是偏置项,那么门可以表示为:()()gxWxb门的使用,就是用门的输出向量按元素乘以我们需要控制的那个向量。因为门的输出是0到1之间的实数向量,那么,当门输出为0时,任何向量与之相乘都会得到0向量,这就相当于啥都不能通过;输出为1时,任何向量与之相乘都不会有任何改变,这就相当于啥都可以通过。因为(也就是sigmoid函数)的值域是(0,1),所以门的状态都是半开半闭的。LSTM用两个门来控制单元状态c的内容,一个是遗忘门(forgetgate),它决定了上一时刻的单元状态1tc有多少保留到当前时刻tc;另一个是输入
本文标题:RNN及LSTM
链接地址:https://www.777doc.com/doc-3942591 .html