这两天对RNN循环神经网络进行了学习,由一无所知到现在对什么是RNN以及它的前向传播和反向传播有了认识,尤其是BPTT算法的推导有些繁琐,但是推过一次后,对RNN反向传播求梯度的过程有了更清晰的认识。

下面是朴素的RNN循环神经网络图。(图1)
RNN循环神经网络里的BPTT算法

我在写博客前,自己先手写了一份推导过程。(图2)
RNN循环神经网络里的BPTT算法

为何BPTT更难?

因为多了状态之间的传递(即隐层单元之间的“交流”),根据前向传播算法,我们知道 st=Wst1+Uxt,st1=f(st1)=f(Wst2+Uxt1),这说明 st1也是关于W的式子。

这样层层嵌套下去……就会追溯到s0。可以意识到我们对WU的梯度求解是繁琐的,而这正是BPTT的难点所在。对于V的梯度求解,并没有受到状态之间传递的影响,因此和我们BP算法求解方式是一样的。

我们用表示element-wise, ×表示矩阵乘法。
我们采用交叉熵损失函数,即Lt=(ytlog(ot)+(1yt)log(1ot))
我们定义隐藏层的**函数为sigmoid函数st=f(st),输出层的**函数也为sigmoid函数 ot=g(ot)f=st(1st),g=ot(1ot) 。具体求导读者自行证明。

由前向传播可知,ot=g(ot)=g(Vst)

那么LtV=Ltototot·otV=(ytot+yt11ot)ot(1ot)·otV=(otyt)×stT

不同时刻的LtV要相加,得到最后的LV

由前向传播可知,对于时刻t而言,st1也是关于W的式子,因此我们在求LtW时,不能简单的将st1视为常量,因此 LtW=k=0tLtsk×sk1T(注意,在我这里是把第一个时刻从0开始)。

Ltst=Ltot·otst=VT×(otyt)st(1st)
Ltsk1=Ltsk·sksk1sk1sk1=sk1(1sk1)WT×Ltsk(k=1,2,3...t)

同理, LtU=k=0tLtsk×xkT

最后不同时刻的 LtU要相加,得到最终的 LU=t=0t=nLtU

最后不同时刻的 LtW要相加,得到最终的 LW=t=0t=nLtW