深度学习——循环神经网络RNN(一)_反向传播算法

RNN网络结构

Elman神经网络是最早的循环神经网络,由Elman于1990年提出,又称为SRN(Simple Recurrent Network, 简单循环网络)。RNN考虑了时序信息,当前时刻的输出不仅和当前时刻的输入有关,还和前面所有时刻的输入有关。

RNN的结构图(引用[2]中的图)如下:
深度学习——循环神经网络RNN(一)_反向传播算法

  • xt表示t时刻的输入向量;

  • ht表示t时刻的隐藏层向量:
    隐层计算公式为

    ht=f(Whhht1+Wxhxt+bh)(1)

    f是隐层的**函数。h0一般初始化为0。
    我们可以认为ht包含了当前时刻及以前的所有记忆。虽然理论上这句话没问题,但是在实际中,由于梯度消失/爆炸问题的存在,ht只包含了有限步的信息,并不能捕获太久之前的信息。这被称为长时依赖问题。

  • yt表示t时刻的输出向量:
    输出yt的计算公式为

    yt=g(Whyht+by)(2)

    g一般为softmax函数。

在训练RNN时,一个输入序列看做一个实例,其误差由各时刻误差之和组成:

J=t=1TJt(3)

梯度计算

RNN的梯度计算比多层前馈神经网络要复杂一些,其反向传播算法有个特有的名字:随时间反向传播算法(Backpropagation Through Time,BPTT)[Werbos, 1990]。

这里会介绍两种计算RNN梯度的方法,并且仅以Whh的梯度为例进行说明。

暴力求解

深度学习——循环神经网络RNN(一)_反向传播算法

我们暂且把t步的Whh写成Whht,于是:

JWhh=t=1TJWhht=t=1ThtWhhtJht(4)

Jht=Jytytht+Jht+1ht+1ht=Jtht+WhhTdiag(f(ht))Jht+1=Jtht+WhhTdiag(f(ht))Jt+1ht+1  +(WhhTdiag(f(ht)))(WhhTdiag(f(ht+1)))Jt+2ht+2  ++i=tT1(WhhTdiag(f(hi)))JThT=k=tTi=tk1(WhhTdiag(f(hi)))Jkhk(5)

把(5)代入(4)中,得到

JWhh=t=1ThtWhh[k=tTi=tk1(WhhTdiag(f(hi)))Jkhk](6)

BPTT

深度学习——循环神经网络RNN(一)_反向传播算法

仍暂且把t步的Whh写成Whht,那么t时刻的误差会影响到{Whhk,k=1,2,...,t1},所以

JWhh=t=1Tk=1tJtWhhk1=t=1Tk=1thkWhhk1hthkJtht=t=1Tk=1thkWhhk1[i=kt1hi+1hi]Jtht=t=1Tk=1thkWhhk1[i=kt1WhhiTdiag(f(hi))]Jtht=t=1Tk=1thkWhh[i=kt1WhhTdiag(f(hi))]Jtht(7)

可以证明公式(6)和(7)等价。

hthk是矩阵的累乘,极容易出现趋于0的情况,这时当前时刻的误差传播不到比较久远的时刻,意味着RNN没有学到长时依赖关系。

参考

[1] Finding Structure in Time. JEFFREY L. ELMAN. 1990.
[2] 《神经网络与深度学习》讲义. 邱锡鹏. 2015.
[3] Recurrent Neural Networks Tutorial, Part 1 – Introduction to RNNs. WILDML. 2015.
[4] 博文Anyone Can Learn To Code an LSTM-RNN in Python (Part 1: RNN). 2015.