循环神经网络之前向反向传播算法

版权声明: https://blog.csdn.net/XiaoYi_Eric/article/details/83717761

前面我们已经介绍了深度神经网络卷积神经网络,这些算法都是前向反馈,模型的输出和模型本身没有关联关系。今天我们学习输出和模型间有反馈的神经网络,循环神经网络(Recurrent Neual Networks),其广泛应用于自然语言处理中的语音识别,书写识别和机器翻译等领域。

1.RNN简介

前面介绍的DNN和CNN之中,训练样本的输入和输出都是确定的。但对于训练样本输入是连续的序列,训练样本长度不同的样本,比如一段连续的语音和手写文字,DNN和CNN是比较难处理的。而对于上述问题,RNN则是比较擅长,那么RNN是怎么做到的呢?

RNN假设输入样本是基于序列的,比如是从序列索引1到序列索引τ,对于其中的任意序列索引号t,输入是对应样本序列的 x ( t ) x^{(t)} 。而模型在序列索引号t位置的隐藏状态 h ( t ) h^{(t)} ,则由 x ( t ) x^{(t)} 和t-1时刻的隐藏状态 h ( t 1 ) h^{(t-1)} 共同决定。在任意序列索引号t,也有相对应的模型预测输出 o t o^{t} 。通过预测输出 o ( t ) o^{(t)} 和训练序列的真实输出 y ( t ) y^{(t)} ,以及损失函数 L ( t ) L^{(t)} ,我们就可以用和DNN类似的方法来训练模型,接着用来预测测试样本的输出,下面我们来看看循环神经网络的模型。

2.RNN模型

01

循环神经网络有多种模型结构,这里我们介绍最主流的模型结构。上图中左边是没有按时间序列展开的图,右边是按照时间序列展开的结构,我们重点看右边的模型结构。这里描述了在序列索引号t附近的RNN模型,下面针对一些参数做具体说明。

  • x ( t ) x^{(t)} 代表在序列索引号t时训练样本的输入,同样 x ( t 1 ) x^{(t-1)} x ( t + 1 ) x^{(t+1)} 分别代表t-1时刻和t+1时刻训练样本的输入。
  • h ( t ) h^{(t)} 代表在序列索引号t时模型的隐藏状态, h ( t ) h^{(t)} x ( t ) x^{(t)} h ( t 1 ) h^{(t-1)} 共同决定。
  • o ( t ) o^{(t)} 代表在序列索引号t时模型的输出, o ( t ) o^{(t)} 由模型当前的隐藏状态 h ( t ) h^{(t)} 决定。
  • L ( t ) L^{(t)} 代表在序列索引号t时模型的损失函数。
  • y ( t ) y^{(t)} 代表在序列索引号t时训练样本序列的真实输出。
  • U , W , V U,W,V 矩阵是模型的线形关系参数,在整个RNN网络间是共享的,这点和DNN不同。正是因为参数的共享,体现了RNN模型循环反馈的思想。

3.RNN前向传播算法

根据上面介绍的模型,我们来看一下RNN前向传播算法,对于任意时刻序列索引号t,能够得到当前的隐藏状态。其中σ为RNN的激活函数,一般是tanh,b为偏倚系数。
h ( t ) = σ ( z ( t ) ) = σ ( U x ( t ) + W h ( t 1 ) + b ) h^{(t)} = \sigma(z^{(t)}) = \sigma (Ux^{(t)} + Wh^{(t-1)} + b)
序列索引号t时模型的输出 o ( t ) o^{(t)}
o ( t ) = V h ( t ) + c o^{(t)} = Vh^{(t)} + c
最终能够得到模型的预测输出,由于RNN是识别类的分类模型,所以下式激活函数一般是softmax函数。
y ^ ( t ) = σ ( o ( t ) ) \hat{y}^{(t)}= \sigma (o ^{(t)})
最后通过损失函数 L ( t ) L^{(t)} ,比如对数似然损失函数,我们可以量化模型在当前位置的损失,即 y ^ ( t ) \hat{y}^{(t)} y ( t ) y^{(t)} 的差距。

4.RNN反向传播算法

RNN反向传播算法和DNN思路相同,即通过梯度下降法进行迭代,得到合适的RNN模型参数U,W,V,b,c,传播过程中所有的参数在序列中各个位置是共享的,即反向传播中我们更新的是相同的参数。为了简化描述,反向传播时损失函数采用对数损失函数,隐藏层的激活函数为tanh函数,输出的激活函数为softmax函数。

对于RNN,由于我们在序列各位置都有损失函数,因此最终的损失函数L为
L = t = 1 τ L ( t ) L = \sum_{t=1}^{\tau}L^{(t)}
其中V,c的梯度计算比较简单,如下所示
L c = t = 1 τ L t c = t = 1 τ L ( t ) o ( t ) o ( t ) c = t = 1 τ ( y ^ ( t ) y ( t ) ) \frac{\partial L}{\partial c} = \sum _{t=1}^{\tau} \frac{\partial L^{t}}{\partial c} = \sum _{t=1}^{\tau} \frac{\partial L^{(t)}}{o^{(t)}} \frac{\partial o^{(t)}}{\partial c} = \sum_{t=1}^{\tau} (\hat{y}^{(t)} - y^{(t)})

L V = t = 1 τ L t V = t = 1 τ L ( t ) o ( t ) o ( t ) V = t = 1 τ ( y ^ ( t ) y ( t ) ) ( h ( t ) ) T \frac{\partial L}{\partial V} = \sum _{t=1}^{\tau} \frac{\partial L^{t}}{\partial V} = \sum _{t=1}^{\tau} \frac{\partial L^{(t)}}{o^{(t)}} \frac{\partial o^{(t)}}{\partial V} = \sum_{t=1}^{\tau} (\hat{y}^{(t)} - y^{(t)})(h^{(t)})^T

针对W,U,b的梯度计算比较复杂,从RNN模型可以看出,在反向传播时,在某一序列位置t的梯度损失,由当前位置的输出对应的梯度损失和序列索引位置t+1时的梯度损失两部分共同决定。对于W在某一序列位置t的梯度损失需要反向传播一步步来进行计算,此处定义序列索引t位置的隐藏状态梯度为
δ ( t ) = L h ( t ) \delta^{(t)} = \frac{\partial L}{\partial h^{(t)}}
这样便可以像DNN一样从 δ ( t + 1 ) \delta^{(t+1)} 递推得到 δ ( t ) \delta^{(t)}
δ ( t ) = L o ( t ) o ( t ) h ( t ) + L h ( t + 1 ) h ( t + 1 ) h ( t ) = V T ( y ^ ( t ) y ( t ) ) + W T δ ( t + 1 ) d i a g ( 1 ( h ( t + 1 ) ) 2 ) \delta^{(t)} = \frac{\partial L}{\partial o^{(t)}}\frac{\partial o^{(t)}}{\partial h^{(t)}} + \frac{\partial L}{\partial h^{(t + 1)}}\frac{\partial h^{(t + 1)}}{\partial h^{(t)}} = V^T(\hat{y}^{(t)} - y^{(t)}) + W^T \delta^{(t+1)} diag(1-(h^{(t+1)})^2)
对于 δ ( τ ) \delta^{(\tau)} 后面没有其他的序列索引,因此有
δ ( τ ) = L o ( τ ) o ( τ ) h ( τ ) = V T ( y ^ ( τ ) y ( τ ) ) \delta^{(\tau)} = \frac{\partial L}{\partial o^{(\tau)}}\frac{\partial o^{(\tau)}}{\partial h^{(\tau)}} = V^T(\hat{y}^{(\tau)} - y^{(\tau)})
有了 δ ( t ) \delta^{(t)} 之后计算W,U,b也就很方便了,相应表达式如下所示
L W = t = 1 τ L h ( t ) h ( t ) W = t = 1 τ d i a g ( 1 ( h ( t ) ) 2 ) δ ( t ) ( h ( t 1 ) ) T \frac{\partial L}{\partial W} = \sum_{t=1}^{\tau} \frac{\partial L}{\partial h^{(t)}} \frac{\partial h^{(t)}}{\partial W} = \sum _{t=1} ^{\tau}diag(1-(h^{(t)})^2)\delta^{(t)}(h^{(t-1)})^T

L U = t = 1 τ L h ( t ) h ( t ) U = t = 1 τ d i a g ( 1 ( h ( t ) ) 2 ) δ ( t ) ( x ( t ) ) T \frac{\partial L}{\partial U} = \sum_{t=1}^{\tau} \frac{\partial L}{\partial h^{(t)}} \frac{\partial h^{(t)}}{\partial U} = \sum _{t=1} ^{\tau}diag(1-(h^{(t)})^2)\delta^{(t)}(x^{(t)})^T

L b = t = 1 τ L h ( t ) h ( t ) b = t = 1 τ d i a g ( 1 ( h ( t ) ) 2 ) δ ( t ) \frac{\partial L}{\partial b} = \sum_{t=1}^{\tau} \frac{\partial L}{\partial h^{(t)}} \frac{\partial h^{(t)}}{\partial b} = \sum _{t=1} ^{\tau}diag(1-(h^{(t)})^2)\delta^{(t)}

4.RNN梯度爆炸和梯度消失

RNN虽然理论上可以很好的解决序列数据的训练,但存在梯度爆炸和梯度消失问题,当序列很长的时候问题尤为严重。为什么会出现梯度爆炸和梯度消失问题呢?我们来看看反向传播过程中 U U 的变化
L U = t = 1 τ L h ( t ) h ( t ) U = t = 1 τ L h ( t + 1 ) h ( t + 1 ) h ( t ) h ( t ) U = t = 1 τ δ ( t + 1 ) h ( t + 1 ) h ( t ) d i a g ( 1 ( h ( t ) ) 2 ) ( x ( t ) ) T \frac{\partial L}{\partial U} = \sum_{t=1}^{\tau} \frac{\partial L}{\partial h^{(t)}} \frac{\partial h^{(t)}}{\partial U} = \sum _{t=1} ^{\tau}\frac{\partial L}{\partial h^{(t+1)}} \frac{\partial h^{(t+1)}}{\partial h^{(t)}} \frac{\partial h^{(t)}}{\partial U} = \sum _{t=1} ^{\tau}\delta^{(t+1)} \frac{\partial h^{(t+1)}}{\partial h^{(t)}} diag(1-(h^{(t)})^2)(x^{(t)})^T
因为 h ( t ) = tanh ( z ( t ) ) = tanh ( U x ( t ) + W h ( t 1 ) + b ) h^{(t)} = \tanh (z^{(t)}) = \tanh (Ux^{(t)} + Wh^{(t-1)} + b) ,所以 h ( t + 1 ) h ( t ) \frac{\partial h^{(t+1)}}{\partial h^{(t)}}
h ( t + 1 ) h ( t ) = d i a g ( 1 ( h ( t + 1 ) ) 2 ) W T \frac{\partial h^{(t+1)}}{\partial h^{(t)}} = diag(1-(h^{(t+1)})^2)W^T
如下图所示,其中 tanh 1 {\tanh}' \leq 1 ​ 。对于训练过程中大部分情况tanh的导数是小于1的,如果W也是大于0小于1的值,那么传播下去便会趋于0。同理当W很大时,传播下去便会趋于无穷,上述就是RNN之中梯度消失和梯度爆炸的原因。
02

5.其他

03

04

上面总结了通用的RNN模型的前向传播算法和反向传播算法,当然RNN还有很多其他的模型,比如多层RNN、双向循环RNN(如上图所示),在前向和反向传播时公式自然也会不同,但基本原理类似,有兴趣可查询其他资料继续学习。

RNN存在梯度爆炸和梯度消失问题,但怎么解决呢,下篇文章我们来介绍LSTM算法,看如何解决传播时出现的梯度爆炸和梯度消失问题。

6.推广

更多内容请关注公众号谓之小一,若有疑问可在公众号后台提问,随时回答,欢迎关注,内容转载请注明出处。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/XiaoYi_Eric/article/details/83717761