定义模型

简单起见,我们考虑一个无偏差项的循环神经网络,且**函数为恒等映射(ϕ(x)=xphi(x)=x)。设时间步 tt 的输入为单样本 xtRdboldsymbol{x}_t in mathbb{R}^d,标签为 yty_t,那么隐藏状态 htRhboldsymbol{h}_t in mathbb{R}^h的计算表达式为

ht=Whxxt+Whhht1, boldsymbol{h}_t = boldsymbol{W}_{hx} boldsymbol{x}_t + boldsymbol{W}_{hh} boldsymbol{h}_{t-1},

其中WhxRh×dboldsymbol{W}_{hx} in mathbb{R}^{h times d}WhhRh×hboldsymbol{W}_{hh} in mathbb{R}^{h times h}是隐藏层权重参数。设输出层权重参数WqhRq×hboldsymbol{W}_{qh} in mathbb{R}^{q times h},时间步tt的输出层变量otRqboldsymbol{o}_t in mathbb{R}^q计算为

ot=Wqhht. boldsymbol{o}_t = boldsymbol{W}_{qh} boldsymbol{h}_{t}.

设时间步tt的损失为(ot,yt)ell(boldsymbol{o}_t, y_t)。时间步数为TT的损失函数LL定义为

L=1Tt=1T(ot,yt). L = frac{1}{T} sum_{t=1}^T ell (boldsymbol{o}_t, y_t).

我们将LL称为有关给定时间步的数据样本的目标函数,并在本节后续讨论中简称为目标函数。

模型计算图

为了可视化循环神经网络中模型变量和参数在计算中的依赖关系,我们可以绘制模型计算图,如图所示。例如,时间步3的隐藏状态h3boldsymbol{h}_3的计算依赖模型参数Whxboldsymbol{W}_{hx}Whhboldsymbol{W}_{hh}、上一时间步隐藏状态h2boldsymbol{h}_2以及当前时间步输入x3boldsymbol{x}_3
循环神经网络中如何通过时间反向传播?

方法

刚刚提到,图6.3中的模型的参数是 Whxboldsymbol{W}_{hx}, Whhboldsymbol{W}_{hh}Wqhboldsymbol{W}_{qh}。与一般的反向传播类似,训练模型通常需要模型参数的梯度LWhxfrac{partial L}{partial boldsymbol{W}_{hx}}LWhhfrac{partial L}{partial boldsymbol{W}_{hh}}LWqhfrac{partial L}{partial boldsymbol{W}_{qh}}。 根据上图的依赖关系,我们可以按照其中箭头所指的反方向依次计算并存储梯度。

首先,目标函数有关各时间步输出层变量的梯度LotRqfrac{partial L}{partial boldsymbol{o}_t} in mathbb{R}^q很容易计算:

Lot=(ot,yt)Tot.frac{partial L}{partial boldsymbol{o}_t} = frac{partial ell (boldsymbol{o}_t, y_t)}{T cdot partial boldsymbol{o}_t}.

下面,我们可以计算目标函数有关模型参数Wqhboldsymbol{W}_{qh}的梯度LWqhRq×hfrac{partial L}{partial boldsymbol{W}_{qh}} in mathbb{R}^{q times h}。根据计算图,LL通过o1,,oTboldsymbol{o}_1, ldots, boldsymbol{o}_T依赖Wqhboldsymbol{W}_{qh}。依据链式法则,

LWqh=t=1Tprod(Lot,otWqh)=t=1TLotht. frac{partial L}{partial boldsymbol{W}{qh}} = sum_{t=1}^T text{prod}left(frac{partial L}{partial boldsymbol{o}_t}, frac{partial boldsymbol{o}_t}{partial boldsymbol{W}_{qh}}right) = sum_{t=1}^T frac{partial L}{partial boldsymbol{o}_t} boldsymbol{h}_t^top.

其次,我们注意到隐藏状态之间也存在依赖关系。 在计算图中,LL只通过oTboldsymbol{o}_T依赖最终时间步TT的隐藏状态hTboldsymbol{h}_T。因此,我们先计算目标函数有关最终时间步隐藏状态的梯度LhTRhfrac{partial L}{partial boldsymbol{h}_T} in mathbb{R}^h。依据链式法则,我们得到

LhT=prod(LoT,oThT)=WqhLoT. frac{partial L}{partial boldsymbol{h}_T} = text{prod}left(frac{partial L}{partial boldsymbol{o}_T}, frac{partial boldsymbol{o}_T}{partial boldsymbol{h}_T} right) = boldsymbol{W}_{qh}^top frac{partial L}{partial boldsymbol{o}_T}.

接下来对于时间步t<Tt < T, 在计算图中,LL通过ht+1boldsymbol{h}_{t+1}otboldsymbol{o}_t依赖htboldsymbol{h}_t。依据链式法则, 目标函数有关时间步t<Tt < T的隐藏状态的梯度LhTRhfrac{partial L}{partial boldsymbol{h}_T} in mathbb{R}^h需要按照时间步从大到小依次计算: Lht=prod(Lht+1,ht+1ht)+prod(Lot,otht)=WhhLht+1+WqhLot frac{partial L}{partial boldsymbol{h}_t} = text{prod} (frac{partial L}{partial boldsymbol{h}_{t+1}}, frac{partial boldsymbol{h}_{t+1}}{partial boldsymbol{h}_t}) + text{prod} (frac{partial L}{partial boldsymbol{o}_t}, frac{partial boldsymbol{o}_t}{partial boldsymbol{h}_t} ) = boldsymbol{W}_{hh}^top frac{partial L}{partial boldsymbol{h}_{t+1}} + boldsymbol{W}_{qh}^top frac{partial L}{partial boldsymbol{o}_t}

将上面的递归公式展开,对任意时间步1tT1 leq t leq T,我们可以得到目标函数有关隐藏状态梯度的通项公式

Lht=i=tT(Whh)TiWqhLoT+ti. frac{partial L}{partial boldsymbol{h}_t} = sum_{i=t}^T {left(boldsymbol{W}_{hh}^topright)}^{T-i} boldsymbol{W}_{qh}^top frac{partial L}{partial boldsymbol{o}_{T+t-i}}.

由上式中的指数项可见,当时间步数 TT 较大或者时间步 tt 较小时,目标函数有关隐藏状态的梯度较容易出现衰减和爆炸。这也会影响其他包含LhTfrac{partial L}{partial boldsymbol{h}_T}项的梯度,例如隐藏层中模型参数的梯度LWhxRh×dfrac{partial L}{partial boldsymbol{W}_{hx}} in mathbb{R}^{h times d}LWhhRh×hfrac{partial L } {partial boldsymbol{W}_{hh}} in mathbb{R}^{h times h}。 在计算图中,LL通过h1,,hTboldsymbol{h}_1, ldots, boldsymbol{h}_T依赖这些模型参数。 依据链式法则,我们有

LWhx=t=1Tprod(Lht,htWhx)=t=1TLhtxt frac{partial L}{partial boldsymbol{W}_{hx}} = sum_{t=1}^T text{prod}left(frac{partial L}{partial boldsymbol{h}_t}, frac{partial boldsymbol{h}_t}{partial boldsymbol{W}_{hx}}right) = sum_{t=1}^T frac{partial L}{partial boldsymbol{h}_t} boldsymbol{x}t^top
LWhh=t=1Tprod(Lht,htWhh)=t=1TLhtht1frac{partial L}{partial boldsymbol{W}_{hh}} = sum_{t=1}^T text{prod}left(frac{partial L}{partial boldsymbol{h}_t}, frac{partial boldsymbol{h}_t}{partial boldsymbol{W}_{hh}}right) = sum_{t=1}^T frac{partial L}{partial boldsymbol{h}_t} boldsymbol{h}_{t-1}^top

每次迭代中,我们在依次计算完以上各个梯度后,会将它们存储起来,从而避免重复计算。例如,由于隐藏状态梯度Lhtfrac{partial L}{partial boldsymbol{h}_t}被计算和存储,之后的模型参数梯度LWhxfrac{partial L}{partial boldsymbol{W}_{hx}}LWhhfrac{partial L}{partial boldsymbol{W}_{hh}}的计算可以直接读取Lhtfrac{partial L}{partial boldsymbol{h}_t}的值,而无须重复计算它们。此外,反向传播中的梯度计算可能会依赖变量的当前值。它们正是通过正向传播计算出来的。 举例来说,参数梯度LWhhfrac{partial L}{partial boldsymbol{W}_{hh}}的计算需要依赖隐藏状态在时间步t=0,,T1t = 0, ldots, T-1的当前值htboldsymbol{h}_th0boldsymbol{h}_0是初始化得到的)。这些值是通过从输入层到输出层的正向传播计算并存储得到的。

参考资料

反向传播