版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_41510260/article/details/99635435
循环神经网络(Recurrent Neural Network, RNN)是一类以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network)
首先先上图,然后再解释:
现在我们考虑输⼊数据存在时间相关性的情况。假设 Xt∈Rn∗dX_t\in_{}\mathbb{R}^{n*d}Xt∈Rn∗d 是序列中时间步t的小批量输⼊,Ht∈Rn∗hH_t\in_{}\mathbb{R}^{n*h}Ht∈Rn∗h 是该时间步的隐藏变量。那么根据以上结构图当前的隐藏变量的公式如下:
Ht=ϕ(XtWxh+Ht−1Whh+bh)H_t=\phi(X_tW_{xh}+H_{t-1}W_{hh}+b_h)Ht=ϕ(XtWxh+Ht−1Whh+bh)
从以上公式我们可以看出,这⾥我们保存上⼀时间步的隐藏变量 Ht−1H_{t-1}Ht−1,并引⼊⼀个新的权重参数,该参数⽤来描述在当前时间步如何使⽤上⼀时间步的隐藏变量。具体来说,时间步 t 的隐藏变量的计算由当前时间步的输⼊和上⼀时间步的隐藏变量共同决定。 ϕ\phiϕ 函数其实就是激活函数。
我们在这⾥添加了 Ht−1WhhH_{t-1}W_{hh}Ht−1Whh ⼀项。由上式中相邻时间步的隐藏变量 Ht和Ht−1H_t 和H_{t-1}Ht和Ht−1 之间的关系可知,这⾥的隐藏变量能够捕捉截⾄当前时间步的序列的历史信息,就像是神经⽹络当前时间步的状态或记忆⼀样。因此,该隐藏变量也称为隐藏状态。由于隐藏状态在当前时间步的定义使⽤了上⼀时间步的隐藏状态,上式的计算是循环的。使⽤循环计算的⽹络即循环神经⽹络(recurrent neural network)。
在时间步t,输出层的输出和多层感知机中的计算类似:
Ot=HtWhq+bqO_t=H_tW_{hq}+b_qOt=HtWhq+bq
之前介绍的循环神经⽹络模型都是假设当前时间步是由前⾯的较早时间步的序列决定的,因此它
们都将信息通过隐藏状态从前往后传递。有时候,当前时间步也可能由后⾯时间步决定。例如,
当我们写下⼀个句⼦时,可能会根据句⼦后⾯的词来修改句⼦前⾯的⽤词。**双向循环神经⽹络通过增加从后往前传递信息的隐藏层来更灵活地处理这类信息。**下图演⽰了⼀个含单隐藏层的双向循环神经⽹络的架构。
在双向循环神经⽹络的架构中,设该时间步正向隐藏状态为 H→t∈Rn∗h\overrightarrow{H}_t\in_{}\mathbb{R}^{n*h}Ht∈Rn∗h(正向隐藏单元个数为h),反向隐藏状态为 H←t∈Rn∗h\overleftarrow{H}_t\in_{}\mathbb{R}^{n*h}Ht∈Rn∗h(反向隐藏单元个数为h)。我们可以分别
计算正向隐藏状态和反向隐藏状态:
H→t=ϕ(XtWxh(f)+H→t−1Whh(f)+bh(f))\overrightarrow{H}_t=\phi(X_tW_{xh}^{(f)}+\overrightarrow{H}_{t-1}W_{hh}^{(f)}+b_h^{(f)})Ht=ϕ(XtWxh(f)+Ht−1Whh(f)+bh(f))
H←t=ϕ(XtWxh(b)+H←t−1Whh(b)+bh(b))\overleftarrow{H}_t=\phi(X_tW_{xh}^{(b)}+\overleftarrow{H}_{t-1}W_{hh}^{(b)}+b_h^{(b)})Ht=ϕ(XtWxh(b)+Ht−1Whh(b)+bh(b))
然后我们连结两个⽅向的隐藏状态 H→t和H←t\overrightarrow{H}_t和\overleftarrow{H}_tHt和Ht 来得到隐藏状态 Ht∈Rn∗2hH_t\in_{}\mathbb{R}^{n*2h}Ht∈Rn∗2h,并将其输⼊到输出层。输出层计算输出 Ot∈Rn∗qO_t\in_{}\mathbb{R}^{n*q}Ot∈Rn∗q(输出个数为q):
Ot=HtWhq+bqO_t=H_tW_{hq}+b_qOt=HtWhq+bq
双向循环神经⽹络在每个时间步的隐藏状态同时取决于该时间步之前和之后的⼦序列(包
括当前时间步的输⼊)。
在之前你已经见过对于前向传播(上图蓝色箭头所指方向)怎样在神经网络中从左到右地计算这些激活项,直到输出所有地预测结果。而对于反向传播,我想你已经猜到了,反向传播地计算方向(上图红色箭头所指方向)与前向传播基本上是相反的。
我们先定义一个元素损失函数:
L(t)(y′(t),y(t))=−y(t)logy′(t)−(1−y′(t))log(1−y′(t))L^{(t)}(y^{'(t)},y^{(t)})=-y^{(t)}logy^{'(t)}-(1-y^{'(t)})log(1-y^{'(t)})L(t)(y′(t),y(t))=−y(t)logy′(t)−(1−y′(t))log(1−y′(t))
整个序列的损失函数:
L(y′,y)=∑t=1TxL(t)(y′(t),y(t))L(y^{'},y)=\sum_{t=1}^{T_x}L^{(t)}(y^{'(t)},y^{(t)})L(y′,y)=t=1∑TxL(t)(y′(t),y(t))$
在这个计算图中,通过y′(1)y^{'(1)}y′(1)可以计算对应的损失函数,于是计算出第一个时间步的损失函数,然后计算出第二个时间步的损失函数,然后是第三个时间步,一直到最后一个时间步,最后为了计算出总体损失函数,我们要把它们都加起来,通过等式计算出最后的?,也就是把每个单独时间步的损失函数都加起来。然后你就可以通过导数相关的参数,用梯度下降法来更新参数。
在这个反向传播的过程中,最重要的信息传递或者说最重要的递归运算就是这个从右到左的运算,这也就是为什么这个算法有一个很别致的名字,叫做**“通过(穿越)时间反向传播(backpropagation through time)”。**取这个名字的原因是对于前向传播,你需要从左到右进行计算,在这个过程中,时刻?不断增加。而对于反向传播,你需要从右到左进行计算,就像时间倒流。“通过时间反向传播”,就像穿越时光,这种说法听起来就像是你需要一台时光机来实现这个算法一样。
类别 | 特点描述 |
---|---|
相同点 | 1、传统神经网络的扩展。2、前向计算产生结果,反向计算模型更新。3、每层神经网络横向可以多个神经元共存,纵向可以有多层神经网络连接。 |
不同点 | 1、CNN空间扩展,神经元与特征卷积;RNN时间扩展,神经元与多个时间输出计算2、RNN可以用于描述时间上连续状态的输出,有记忆功能,CNN用于静态输出 |
由于RNN特有的memory会影响后期其他的RNN的特点,梯度时大时小,learning rate没法个性化的调整,导致RNN在train的过程中,Loss会震荡起伏,为了解决RNN的这个问题,在训练的时候,可以设置临界值,当梯度大于某个临界值,直接截断,用这个临界值作为梯度的大小,防止大幅震荡。
作者:@mantchs