深度学习入门(五十九)循环神经网络——通过时间反向传播

news2024/10/7 9:17:17

深度学习入门(五十九)循环神经网络——通过时间反向传播

  • 前言
  • 循环神经网络——通过时间反向传播
    • 教材
      • 1 循环神经网络的梯度分析
        • 1.1 完全计算
        • 1.2 截断时间步
        • 1.3 随机截断
        • 1.4 比较策略
      • 2 通过时间反向传播的细节
      • 3 小结

前言

核心内容来自博客链接1博客连接2希望大家多多支持作者
本文记录用,防止遗忘

循环神经网络——通过时间反向传播

教材

到目前为止,我们已经反复提到像梯度爆炸梯度消失, 以及需要对循环神经网络分离梯度。 例如,在RNN从零实现一节中, 我们在序列上调用了detach函数。 为了能够快速构建模型并了解其工作原理, 上面所说的这些概念都没有得到充分的解释。 本节将更深入地探讨序列模型反向传播的细节, 以及相关的数学原理。

当我们首次实现循环神经网络时, 遇到了梯度爆炸的问题。我们发现梯度截断对于确保模型收敛至关重要。 为了更好地理解此问题,本节将回顾序列模型梯度的计算方式, 它的工作原理没有什么新概念,毕竟我们使用的仍然是链式法则来计算梯度。

我们在之前描述了多层感知机中的前向与反向传播及相关的计算图。 循环神经网络中的前向传播相对简单。 通过时间反向传播(backpropagation through time,BPTT) 实际上是循环神经网络中反向传播技术的一个特定应用。 它要求我们将循环神经网络的计算图一次展开一个时间步, 以获得模型变量和参数之间的依赖关系。 然后,基于链式法则,应用反向传播来计算和存储梯度。 由于序列可能相当长,因此依赖关系也可能相当长。 例如,某个1000个字符的序列, 其第一个词元可能会对最后位置的词元产生重大影响。 这在计算上是不可行的(它需要的时间和内存都太多了), 并且还需要超过1000个矩阵的乘积才能得到非常难以捉摸的梯度。 这个过程充满了计算与统计的不确定性。 在下文中,我们将阐明会发生什么以及如何在实践中解决它们。

1 循环神经网络的梯度分析

我们从一个描述循环神经网络工作原理的简化模型开始, 此模型忽略了隐状态的特性及其更新方式的细节。 这里的数学表示没有像过去那样明确地区分标量、向量和矩阵, 因为这些细节对于分析并不重要, 反而只会使本小节中的符号变得混乱。

在这个简化模型中,我们将时间步 t t t的隐状态表示为 h t h_t ht, 输入表示为 x t x_t xt,输出表示为 o t o_t ot。 回想一下我们在RNN一节中的讨论, 输入和隐状态可以拼接后与隐藏层中的一个权重变量相乘。 因此,我们分别使用 w h w_h wh w o w_o wo来表示隐藏层和输出层的权重。 每个时间步的隐状态和输出可以写为:
h t = f ( x t , h t − 1 , w h ) , o t = g ( h t , w o ) , \begin{aligned}h_t &= f(x_t, h_{t-1}, w_h),\\o_t &= g(h_t, w_o),\end{aligned} htot=f(xt,ht1,wh),=g(ht,wo),

其中 f f f g g g分别是隐藏层和输出层的变换。 因此,我们有一个链 { … , ( x t − 1 , h t − 1 , o t − 1 ) , ( x t , h t , o t ) , … } \{\ldots, (x_{t-1}, h_{t-1}, o_{t-1}), (x_{t}, h_{t}, o_t), \ldots\} {,(xt1,ht1,ot1),(xt,ht,ot),}, 它们通过循环计算彼此依赖。 前向传播相当简单,一次一个时间步的遍历三元组 ( x t , h t , o t ) (x_t, h_t, o_t) (xt,ht,ot), 然后通过一个目标函数在所有 T T T个时间步内评估输出 o t o_t ot和对应的标签 y t y_t yt之间的差异:
L ( x 1 , … , x T , y 1 , … , y T , w h , w o ) = 1 T ∑ t = 1 T l ( y t , o t ) . L(x_1, \ldots, x_T, y_1, \ldots, y_T, w_h, w_o) = \frac{1}{T}\sum_{t=1}^T l(y_t, o_t). L(x1,,xT,y1,,yT,wh,wo)=T1t=1Tl(yt,ot).
对于反向传播,问题则有点棘手, 特别是当我们计算目标函数 L L L关于参数 w h w_h wh的梯度时。 具体来说,按照链式法则:
∂ L ∂ w h = 1 T ∑ t = 1 T ∂ l ( y t , o t ) ∂ w h = 1 T ∑ t = 1 T ∂ l ( y t , o t ) ∂ o t ∂ g ( h t , w o ) ∂ h t ∂ h t ∂ w h . \begin{aligned}\begin{aligned}\frac{\partial L}{\partial w_h} & = \frac{1}{T}\sum_{t=1}^T \frac{\partial l(y_t, o_t)}{\partial w_h} \\& = \frac{1}{T}\sum_{t=1}^T \frac{\partial l(y_t, o_t)}{\partial o_t} \frac{\partial g(h_t, w_o)}{\partial h_t} \frac{\partial h_t}{\partial w_h}.\end{aligned}\end{aligned} whL=T1t=1Twhl(yt,ot)=T1t=1Totl(yt,ot)htg(ht,wo)whht.
在上式中乘积的第一项和第二项很容易计算, 而第三项 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh是使事情变得棘手的地方, 因为我们需要循环地计算参数 w h w_h wh h t h_t ht的影响。 根据 h t = f ( x t , h t − 1 , w h ) , o t = g ( h t , w o ) , \begin{aligned}h_t &= f(x_t, h_{t-1}, w_h),\\o_t &= g(h_t, w_o),\end{aligned} htot=f(xt,ht1,wh),=g(ht,wo),中的递归计算, h t h_t ht既依赖于 h t − 1 h_{t-1} ht1又依赖于 w h w_h wh, 其中 h t − 1 h_{t-1} ht1的计算也依赖于 w h w_h wh。 因此,使用链式法则产生:
∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 ∂ h t − 1 ∂ w h . \frac{\partial h_t}{\partial w_h}= \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h} +\frac{\partial f(x_{t},h_{t-1},w_h)}{\partial h_{t-1}} \frac{\partial h_{t-1}}{\partial w_h}. whht=whf(xt,ht1,wh)+ht1f(xt,ht1,wh)whht1.
为了导出上述梯度,假设我们有三个序列 { a t } , { b t } , { c t } \{a_{t}\},\{b_{t}\},\{c_{t}\} {at},{bt},{ct}, 当 t = 1 , 2 , … t=1,2,\ldots t=1,2,时,序列满足 a 0 = 0 a_{0}=0 a0=0 a t = b t + c t a t − 1 a_{t}=b_{t}+c_{t}a_{t-1} at=bt+ctat1。 对于 t ≥ 1 t\geq 1 t1,就很容易得出:
a t = b t + ∑ i = 1 t − 1 ( ∏ j = i + 1 t c j ) b i . a_{t}=b_{t}+\sum_{i=1}^{t-1}\left(\prod_{j=i+1}^{t}c_{j}\right)b_{i}. at=bt+i=1t1(j=i+1tcj)bi.
基于下列公式替换 a t a_t at b t b_t bt c t c_t ct
a t = ∂ h t ∂ w h , b t = ∂ f ( x t , h t − 1 , w h ) ∂ w h , c t = ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 , \begin{aligned}\begin{aligned}a_t &= \frac{\partial h_t}{\partial w_h},\\ b_t &= \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h}, \\ c_t &= \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial h_{t-1}},\end{aligned}\end{aligned} atbtct=whht,=whf(xt,ht1,wh),=ht1f(xt,ht1,wh),

公式 ∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 ∂ h t − 1 ∂ w h . \frac{\partial h_t}{\partial w_h}= \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h} +\frac{\partial f(x_{t},h_{t-1},w_h)}{\partial h_{t-1}} \frac{\partial h_{t-1}}{\partial w_h}. whht=whf(xt,ht1,wh)+ht1f(xt,ht1,wh)whht1.中的梯度计算满足 a t = b t + c t a t − 1 a_{t}=b_{t}+c_{t}a_{t-1} at=bt+ctat1。 因此,对于每个 a t = b t + ∑ i = 1 t − 1 ( ∏ j = i + 1 t c j ) b i . a_{t}=b_{t}+\sum_{i=1}^{t-1}\left(\prod_{j=i+1}^{t}c_{j}\right)b_{i}. at=bt+i=1t1(j=i+1tcj)bi., 我们可以使用下面的公式移除 ∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 ∂ h t − 1 ∂ w h . \frac{\partial h_t}{\partial w_h}= \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h} +\frac{\partial f(x_{t},h_{t-1},w_h)}{\partial h_{t-1}} \frac{\partial h_{t-1}}{\partial w_h}. whht=whf(xt,ht1,wh)+ht1f(xt,ht1,wh)whht1.中的循环计算
∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∑ i = 1 t − 1 ( ∏ j = i + 1 t ∂ f ( x j , h j − 1 , w h ) ∂ h j − 1 ) ∂ f ( x i , h i − 1 , w h ) ∂ w h . \frac{\partial h_t}{\partial w_h}=\frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h}+\sum_{i=1}^{t-1}\left(\prod_{j=i+1}^{t} \frac{\partial f(x_{j},h_{j-1},w_h)}{\partial h_{j-1}} \right) \frac{\partial f(x_{i},h_{i-1},w_h)}{\partial w_h}. whht=whf(xt,ht1,wh)+i=1t1(j=i+1thj1f(xj,hj1,wh))whf(xi,hi1,wh).
虽然我们可以使用链式法则递归地计算 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh, 但当$t很大时这个链就会变得很长。 我们需要想想办法来处理这一问题.

1.1 完全计算

显然,我们可以仅仅计算 ∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∑ i = 1 t − 1 ( ∏ j = i + 1 t ∂ f ( x j , h j − 1 , w h ) ∂ h j − 1 ) ∂ f ( x i , h i − 1 , w h ) ∂ w h . \frac{\partial h_t}{\partial w_h}=\frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h}+\sum_{i=1}^{t-1}\left(\prod_{j=i+1}^{t} \frac{\partial f(x_{j},h_{j-1},w_h)}{\partial h_{j-1}} \right) \frac{\partial f(x_{i},h_{i-1},w_h)}{\partial w_h}. whht=whf(xt,ht1,wh)+i=1t1(j=i+1thj1f(xj,hj1,wh))whf(xi,hi1,wh).中的全部总和, 然而,这样的计算非常缓慢,并且可能会发生梯度爆炸, 因为初始条件的微小变化就可能会对结果产生巨大的影响。 也就是说,我们可以观察到类似于蝴蝶效应的现象, 即初始条件的很小变化就会导致结果发生不成比例的变化。 这对于我们想要估计的模型而言是非常不可取的。 毕竟,我们正在寻找的是能够很好地泛化高稳定性模型的估计器。 因此,在实践中,这种方法几乎从未使用过。

1.2 截断时间步

或者,我们可以在 τ \tau τ步后截断 ∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∑ i = 1 t − 1 ( ∏ j = i + 1 t ∂ f ( x j , h j − 1 , w h ) ∂ h j − 1 ) ∂ f ( x i , h i − 1 , w h ) ∂ w h . \frac{\partial h_t}{\partial w_h}=\frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h}+\sum_{i=1}^{t-1}\left(\prod_{j=i+1}^{t} \frac{\partial f(x_{j},h_{j-1},w_h)}{\partial h_{j-1}} \right) \frac{\partial f(x_{i},h_{i-1},w_h)}{\partial w_h}. whht=whf(xt,ht1,wh)+i=1t1(j=i+1thj1f(xj,hj1,wh))whf(xi,hi1,wh).中的求和计算。 这是我们到目前为止一直在讨论的内容, 例如在RNN从零实现一节中分离梯度时。 这会带来真实梯度的近似, 只需将求和终止为 ∂ h t − τ / ∂ w h \partial h_{t-\tau}/\partial w_h htτ/wh。 在实践中,这种方式工作得很好。 它通常被称为截断的通过时间反向传播。 这样做导致该模型主要侧重于短期影响,而不是长期影响。 这在现实中是可取的,因为它会将估计值偏向更简单和更稳定的模型

1.3 随机截断

最后,我们可以用一个随机变量替换 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh, 该随机变量在预期中是正确的,但是会截断序列。 这个随机变量是通过使用序列 ξ t \xi_t ξt来实现的, 序列预定义了 0 ≤ π t ≤ 1 0 \leq \pi_t \leq 1 0πt1, 其中 P ( ξ t = 0 ) = 1 − π t P(\xi_t = 0) = 1-\pi_t P(ξt=0)=1πt P ( ξ t = π t − 1 ) = π t P(\xi_t = \pi_t^{-1}) = \pi_t P(ξt=πt1)=πt, 因此 E [ ξ t ] = 1 E[\xi_t] = 1 E[ξt]=1。 我们使用它来替换 ∂ h t ∂ w h = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 ∂ h t − 1 ∂ w h . \frac{\partial h_t}{\partial w_h}= \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h} +\frac{\partial f(x_{t},h_{t-1},w_h)}{\partial h_{t-1}} \frac{\partial h_{t-1}}{\partial w_h}. whht=whf(xt,ht1,wh)+ht1f(xt,ht1,wh)whht1.中的梯度 ∂ h t / ∂ w h \partial h_t/\partial w_h ht/wh得到:
z t = ∂ f ( x t , h t − 1 , w h ) ∂ w h + ξ t ∂ f ( x t , h t − 1 , w h ) ∂ h t − 1 ∂ h t − 1 ∂ w h . z_t= \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial w_h} +\xi_t \frac{\partial f(x_{t},h_{t-1},w_h)}{\partial h_{t-1}} \frac{\partial h_{t-1}}{\partial w_h}. zt=whf(xt,ht1,wh)+ξtht1f(xt,ht1,wh)whht1.
ξ t \xi_t ξt的定义中推导出来 E [ z t ] = ∂ h t / ∂ w h E[z_t] = \partial h_t/\partial w_h E[zt]=ht/wh。 每当 ξ t = 0 \xi_t = 0 ξt=0时,递归计算终止在这个 t t t时间步。 这导致了不同长度序列的加权和,其中长序列出现的很少, 所以将适当地加大权重。

1.4 比较策略

在这里插入图片描述
比较RNN中计算梯度的策略,3行自上而下分别为:随机截断、常规截断、完整计算

上图说明了 当基于循环神经网络使用通过时间反向传播 分析《时间机器》书中前几个字符的三种策略:

  • 第一行采用随机截断,方法是将文本划分为不同长度的片断;

  • 第二行采用常规截断,方法是将文本分解为相同长度的子序列。 这也是我们在循环神经网络实验中一直在做的;

  • 第三行采用通过时间的完全反向传播,结果是产生了在计算上不可行的表达式。

遗憾的是,虽然随机截断在理论上具有吸引力, 但很可能是由于多种因素在实践中并不比常规截断更好。 首先,在对过去若干个时间步经过反向传播后, 观测结果足以捕获实际的依赖关系。 其次,增加的方差抵消了时间步数越多梯度越精确的事实。 第三,我们真正想要的是只有短范围交互的模型。 因此,模型需要的正是截断的通过时间反向传播方法所具备的轻度正则化效果。

2 通过时间反向传播的细节

在讨论一般性原则之后,我们看一下通过时间反向传播问题的细节。 与上面中的分析不同, 下面我们将展示如何计算目标函数相对于所有分解模型参数的梯度。 为了保持简单,我们考虑一个没有偏置参数的循环神经网络, 其在隐藏层中的激活函数使用恒等映射 ϕ ( x ) = x \phi(x)=x ϕ(x)=x。 对于时间步 t t t,设单个样本的输入及其对应的标签分别为 x t ∈ R d \mathbf{x}_t \in \mathbb{R}^d xtRd y t y_t yt。 计算隐状态 h t ∈ R h \mathbf{h}_t \in \mathbb{R}^h htRh和 输出 o t ∈ R q \mathbf{o}_t \in \mathbb{R}^q otRq的方式为:
h t = W h x x t + W h h h t − 1 , o t = W q h h t , \begin{aligned}\mathbf{h}_t &= \mathbf{W}_{hx} \mathbf{x}_t + \mathbf{W}_{hh} \mathbf{h}_{t-1},\\ \mathbf{o}_t &= \mathbf{W}_{qh} \mathbf{h}_{t},\end{aligned} htot=Whxxt+Whhht1,=Wqhht,
其中权重参数为 W h x ∈ R h × d \mathbf{W}_{hx} \in \mathbb{R}^{h \times d} WhxRh×d W h h ∈ R h × h \mathbf{W}_{hh} \in \mathbb{R}^{h \times h} WhhRh×h W q h ∈ R q × h \mathbf{W}_{qh} \in \mathbb{R}^{q \times h} WqhRq×h 。 用 l ( o t , y t ) l(\mathbf{o}_t, y_t) l(ot,yt)表示时间步 t t t处 (即从序列开始起的超过 T T T个时间步)的损失函数, 则我们的目标函数的总体损失是:
L = 1 T ∑ t = 1 T l ( o t , y t ) . L = \frac{1}{T} \sum_{t=1}^T l(\mathbf{o}_t, y_t). L=T1t=1Tl(ot,yt).

为了在循环神经网络的计算过程中可视化模型变量和参数之间的依赖关系, 我们可以为模型绘制一个计算图, 如下图所示。 例如,时间步3的隐状态 h 3 \mathbf{h}_3 h3的计算 取决于模型参数 W h x \mathbf{W}_{hx} Whx W h h \mathbf{W}_{hh} Whh, 以及最终时间步的隐状态 h 2 \mathbf{h}_2 h2以及当前时间步的输入 x 3 \mathbf{x}_3 x3

在这里插入图片描述
上图表示具有三个时间步的循环神经网络模型依赖关系的计算图。未着色的方框表示变量,着色的方框表示参数,圆表示运算符

正如刚才所说, 上图的模型参数是 W h x \mathbf{W}_{hx} Whx W h h \mathbf{W}_{hh} Whh W q h \mathbf{W}_{qh} Wqh。 通常,训练该模型需要对这些参数进行梯度计算: ∂ L / ∂ W h x \partial L/\partial \mathbf{W}_{hx} L/Whx ∂ L / ∂ W h h \partial L/\partial \mathbf{W}_{hh} L/Whh ∂ L / ∂ W q h \partial L/\partial \mathbf{W}_{qh} L/Wqh 。 根据上图中的依赖关系, 我们可以沿箭头的相反方向遍历计算图,依次计算和存储梯度。 为了灵活地表示链式法则中不同形状的矩阵、向量和标量的乘法, 我们继续使用之前所述的 prod \text{prod} prod运算符。

首先,在任意时间步 t t t, 目标函数关于模型输出的微分计算是相当简单的:

∂ L ∂ o t = ∂ l ( o t , y t ) T ⋅ ∂ o t ∈ R q . \frac{\partial L}{\partial \mathbf{o}_t} = \frac{\partial l (\mathbf{o}_t, y_t)}{T \cdot \partial \mathbf{o}_t} \in \mathbb{R}^q. otL=Totl(ot,yt)Rq.

现在,我们可以计算目标函数关于输出层中参数 W q h \mathbf{W}_{qh} Wqh的梯度: ∂ L / ∂ W q h ∈ R q × h \partial L/\partial \mathbf{W}_{qh} \in \mathbb{R}^{q \times h} L/WqhRq×h 。 基于上图, 目标函数 L L L通过 o 1 , … , o T \mathbf{o}_1, \ldots, \mathbf{o}_T o1,,oT依赖于 W q h \mathbf{W}_{qh} Wqh。 依据链式法则,得到
∂ L ∂ W q h = ∑ t = 1 T prod ( ∂ L ∂ o t , ∂ o t ∂ W q h ) = ∑ t = 1 T ∂ L ∂ o t h t ⊤ , \frac{\partial L}{\partial \mathbf{W}_{qh}} = \sum_{t=1}^T \text{prod}\left(\frac{\partial L}{\partial \mathbf{o}_t}, \frac{\partial \mathbf{o}_t}{\partial \mathbf{W}_{qh}}\right) = \sum_{t=1}^T \frac{\partial L}{\partial \mathbf{o}_t} \mathbf{h}_t^\top, WqhL=t=1Tprod(otL,Wqhot)=t=1TotLht,
接下来,如图所示, 在最后的时间步 T T T,目标函数 L L L仅通过 o T \mathbf{o}_T oT依赖于隐状态 h T \mathbf{h}_T hT。 因此,我们通过使用链式法可以很容易地得到梯度 ∂ L / ∂ h T ∈ R h \partial L/\partial \mathbf{h}_T \in \mathbb{R}^h L/hTRh
∂ L ∂ h T = prod ( ∂ L ∂ o T , ∂ o T ∂ h T ) = W q h ⊤ ∂ L ∂ o T . \frac{\partial L}{\partial \mathbf{h}_T} = \text{prod}\left(\frac{\partial L}{\partial \mathbf{o}_T}, \frac{\partial \mathbf{o}_T}{\partial \mathbf{h}_T} \right) = \mathbf{W}_{qh}^\top \frac{\partial L}{\partial \mathbf{o}_T}. hTL=prod(oTL,hToT)=WqhoTL.
当目标函数 L L L通过 h t + 1 \mathbf{h}_{t+1} ht+1 o t \mathbf{o}_t ot依赖 h t \mathbf{h}_t ht时, 对任意时间步 t < T t < T t<T来说都变得更加棘手。 根据链式法则,隐状态的梯度 ∂ L / ∂ h t ∈ R h \partial L/\partial \mathbf{h}_t \in \mathbb{R}^h L/htRh在任何时间步骤 t < T t\lt T t<T时都可以递归地计算为:
∂ L ∂ h t = prod ( ∂ L ∂ h t + 1 , ∂ h t + 1 ∂ h t ) + prod ( ∂ L ∂ o t , ∂ o t ∂ h t ) = W h h ⊤ ∂ L ∂ h t + 1 + W q h ⊤ ∂ L ∂ o t . \frac{\partial L}{\partial \mathbf{h}_t} = \text{prod}\left(\frac{\partial L}{\partial \mathbf{h}_{t+1}}, \frac{\partial \mathbf{h}_{t+1}}{\partial \mathbf{h}_t} \right) + \text{prod}\left(\frac{\partial L}{\partial \mathbf{o}_t}, \frac{\partial \mathbf{o}_t}{\partial \mathbf{h}_t} \right) = \mathbf{W}_{hh}^\top \frac{\partial L}{\partial \mathbf{h}_{t+1}} + \mathbf{W}_{qh}^\top \frac{\partial L}{\partial \mathbf{o}_t}. htL=prod(ht+1L,htht+1)+prod(otL,htot)=Whhht+1L+WqhotL.

为了进行分析,对于任何时间步 1 ≤ t ≤ T 1 \leq t \leq T 1tT展开递归计算得
∂ L ∂ h t = ∑ i = t T ( W h h ⊤ ) T − i W q h ⊤ ∂ L ∂ o T + t − i . \frac{\partial L}{\partial \mathbf{h}_t}= \sum_{i=t}^T {\left(\mathbf{W}_{hh}^\top\right)}^{T-i} \mathbf{W}_{qh}^\top \frac{\partial L}{\partial \mathbf{o}_{T+t-i}}. htL=i=tT(Whh)TiWqhoT+tiL.

我们可以从上式中看到, 这个简单的线性例子已经展现了长序列模型的一些关键问题: 它陷入到 W h h ⊤ \mathbf{W}_{hh}^\top Whh的潜在的非常大的幂。 在这个幂中,小于1的特征值将会消失,大于1的特征值将会发散。 这在数值上是不稳定的,表现形式为梯度消失或梯度爆炸。 解决此问题的一种方法是按照计算方便的需要截断时间步长的尺寸(如第一部分所说)。 实际上,这种截断是通过在给定数量的时间步之后分离梯度来实现的。 稍后,我们将学习更复杂的序列模型(如长短期记忆模型) 是如何进一步缓解这一问题的。

最后, 上图表明:目标函数 L L L通过隐状态 h 1 , … , h T \mathbf{h}_1, \ldots, \mathbf{h}_T h1,,hT依赖于隐藏层中的模型参数 W h x \mathbf{W}_{hx} Whx W h h \mathbf{W}_{hh} Whh。 为了计算有关这些参数的梯度 ∂ L / ∂ W h x ∈ R h × d \partial L / \partial \mathbf{W}_{hx} \in \mathbb{R}^{h \times d} L/WhxRh×d ∂ L / ∂ W h h ∈ R h × h \partial L / \partial \mathbf{W}_{hh} \in \mathbb{R}^{h \times h} L/WhhRh×h, 我们应用链式规则得:
∂ L ∂ W h x = ∑ t = 1 T prod ( ∂ L ∂ h t , ∂ h t ∂ W h x ) = ∑ t = 1 T ∂ L ∂ h t x t ⊤ , ∂ L ∂ W h h = ∑ t = 1 T prod ( ∂ L ∂ h t , ∂ h t ∂ W h h ) = ∑ t = 1 T ∂ L ∂ h t h t − 1 ⊤ , \begin{aligned}\begin{aligned} \frac{\partial L}{\partial \mathbf{W}_{hx}} &= \sum_{t=1}^T \text{prod}\left(\frac{\partial L}{\partial \mathbf{h}_t}, \frac{\partial \mathbf{h}_t}{\partial \mathbf{W}_{hx}}\right) = \sum_{t=1}^T \frac{\partial L}{\partial \mathbf{h}_t} \mathbf{x}_t^\top,\\ \frac{\partial L}{\partial \mathbf{W}_{hh}} &= \sum_{t=1}^T \text{prod}\left(\frac{\partial L}{\partial \mathbf{h}_t}, \frac{\partial \mathbf{h}_t}{\partial \mathbf{W}_{hh}}\right) = \sum_{t=1}^T \frac{\partial L}{\partial \mathbf{h}_t} \mathbf{h}_{t-1}^\top, \end{aligned}\end{aligned} WhxLWhhL=t=1Tprod(htL,Whxht)=t=1ThtLxt,=t=1Tprod(htL,Whhht)=t=1ThtLht1,

其中 ∂ L / ∂ h t \partial L/\partial \mathbf{h}_t L/ht是由 ∂ L ∂ h T = prod ( ∂ L ∂ o T , ∂ o T ∂ h T ) = W q h ⊤ ∂ L ∂ o T . \frac{\partial L}{\partial \mathbf{h}_T} = \text{prod}\left(\frac{\partial L}{\partial \mathbf{o}_T}, \frac{\partial \mathbf{o}_T}{\partial \mathbf{h}_T} \right) = \mathbf{W}_{qh}^\top \frac{\partial L}{\partial \mathbf{o}_T}. hTL=prod(oTL,hToT)=WqhoTL. ∂ L ∂ h t = prod ( ∂ L ∂ h t + 1 , ∂ h t + 1 ∂ h t ) + prod ( ∂ L ∂ o t , ∂ o t ∂ h t ) = W h h ⊤ ∂ L ∂ h t + 1 + W q h ⊤ ∂ L ∂ o t . \frac{\partial L}{\partial \mathbf{h}_t} = \text{prod}\left(\frac{\partial L}{\partial \mathbf{h}_{t+1}}, \frac{\partial \mathbf{h}_{t+1}}{\partial \mathbf{h}_t} \right) + \text{prod}\left(\frac{\partial L}{\partial \mathbf{o}_t}, \frac{\partial \mathbf{o}_t}{\partial \mathbf{h}_t} \right) = \mathbf{W}_{hh}^\top \frac{\partial L}{\partial \mathbf{h}_{t+1}} + \mathbf{W}_{qh}^\top \frac{\partial L}{\partial \mathbf{o}_t}. htL=prod(ht+1L,htht+1)+prod(otL,htot)=Whhht+1L+WqhotL.递归计算得到的, 是影响数值稳定性的关键量。

正如我们在之前中所解释的那样, 由于通过时间反向传播是反向传播在循环神经网络中的应用方式, 所以训练循环神经网络交替使用前向传播和通过时间反向传播。 通过时间反向传播依次计算并存储上述梯度。 具体而言,存储的中间值会被重复使用,以避免重复计算, 例如存储 ∂ L / ∂ h t \partial L/\partial \mathbf{h}_t L/ht, 以便在计算 ∂ L / ∂ W h x \partial L / \partial \mathbf{W}_{hx} L/Whx ∂ L / ∂ W h h \partial L / \partial \mathbf{W}_{hh} L/Whh时使用。

3 小结

  • “通过时间反向传播”仅仅适用于反向传播在具有隐状态的序列模型。

  • 截断是计算方便性和数值稳定性的需要。截断包括:规则截断和随机截断。

  • 矩阵的高次幂可能导致神经网络特征值的发散或消失,将以梯度爆炸或梯度消失的形式表现。

  • 为了计算的效率,“通过时间反向传播”在计算期间会缓存中间值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/80691.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于java+springboot+vue+mysql的甜品蛋糕销售商城网站

项目介绍 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。人们生活水平的不断提高&#xff0c;日常生活中用户对网上蛋糕商城方面的要求也在不断提高&#xff0c;网上蛋糕商城得到广大用户的青睐&#xff0c;使得网上蛋糕商城的开发成为必需而且紧迫的事情。本系…

Docker笔记--使用数据卷实现容器与宿主机的数据交互

1--数据卷的介绍和作用 在 Docker 架构中&#xff0c;宿主机系统和容器之间不能直接传递数据&#xff0c;同时当容器被删除时&#xff0c;容器所有的数据都会被清除&#xff1b; 数据卷能够在宿主机与容器、容器与容器之间搭建数据传输和共享的通道&#xff0c;当容器内的目录与…

C++ 快速复习-数据类型

内置数据类型 int、unsigned int 、long、unsigned long 、short、char、signed char、bool、 long long float、double、long double 等 无符号的数据类型 主要在于 不在区分 -&#xff0c;数据波动范围变大。另外&#xff0c;值得注意的是 unsigned 类型的数据 不建议在输出…

玩以太坊链上项目的必备技能(变量作用域-Solidity之旅五)

在前文我们讲过 Solidity 是一种静态类型的语言&#xff0c;这就意味着在声明变量前需先指定类型。 而 Solidity 对变量划分了以下三种作用域范围&#xff1a; 状态变量&#xff08;State Variable&#xff09;&#xff1a; ​ 该变量的值被永久地存放在合约存储中&#xff…

JS新年倒计时

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;前端案例分…

Java---线程详解

目录 一、线程的介绍 二、线程的使用 &#xff08;1&#xff09;多线程的实现 1&#xff1a;继承Thread类 2&#xff1a;实现Runnable接口 &#xff08;2&#xff09;设置和获取线程名称 1:继承Thread类 2&#xff1a;实现Runnable接口 &#xff08;3&#xff09;线程…

Java学习—多线程Thread

多线程1. 线程简介1.1 普通方法和多线程1.2 程序、进程、线程2. 线程创建2.1 Thread类案例&#xff1a;下载图片2.2 Runnable接口案例&#xff1a;龟兔赛跑2.3 Callable接口3. 静态代理4. Lamda表达式5. 线程状态5.1 线程方法5.2 停止线程5.3 线程休眠5.4 线程礼让-yield5.5 Jo…

揭秘SpringMVC-DispatcherServlet之九大组件(二)

前言 上回聊到了HandlerAdapter&#xff0c;今天继续聊后面的组件。今天的主角是HandlerMapping&#xff0c;这篇文章全为他服务了。 HandlerMapping 上回说的Handler&#xff0c;我们说是处理特定请求的。也就是说&#xff0c;不是所有的请求都能处理。那么问题来了&#x…

gateway初始化与配置

1、排除依赖 spring-boot-starter-webflux 2、添加依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency><groupId>org.springf…

基于GDAL的JAVA生成GDB文件实战

前言 在之前博客中&#xff0c;陆续的介绍了关于gdb文件的读取&#xff0c;gis利器之Gdal&#xff08;三&#xff09;gdb数据读取&#xff0c;玩转GDAL一文带你深入Windows下FileGDB驱动支持&#xff0c;这些文章主要都是介绍gdal的读取gdb以及简单的gdb文件读写。在实际工作中…

VJ个人周赛

A:模拟 题意&#xff1a;给定了N个任务&#xff0c;每个任务都有一个优先级&#xff08;1~9&#xff09;&#xff0c;数字越大&#xff0c;优先级越高。将这些任务放入队列中&#xff0c;如果出队的元素&#xff08;x&#xff09;&#xff0c;x的优先级不是最高的&#xff0c;那…

从高级测试到测试开发有什么感悟

最近加入了新的团队&#xff0c;角色发生较大的转变&#xff0c;在这里分享一下自己的感受。 测试的划分 如果我们把产品的生产看成一个流水线的话&#xff0c;那么测试就是流水线上的一个重要岗位&#xff0c;把控着产品的质量。 当然&#xff0c;产品类型的不同&#xff0…

信息系统安全管理

信息系统安全是一个绕不开的话题。从事IT行业&#xff0c;不论何种角色&#xff0c;哪个工种&#xff0c;都需要有所了解。 一、信息系统安全策略 1、概述 信息系统安全策略是指对&#xff08;本单位&#xff09;信息系统的安全风险&#xff08;安全威胁&#xff09;进行有效…

小白学编程(js):通过按钮变换背景颜色

《JavaScript从入门到精通》【例9.1】 代码演示&#xff1a; <body><form class"form1" action"" name"form1" method"psot"><p><input type"button" name"Submit" value"变换背景&qu…

[附源码]计算机毕业设计基于Java的图书购物商城Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Linux常用环境配置及软件安装(持续更新)

1、jdk 1、下载jdk Linux安装包 把安装包放到自己定义的目录下 安装包网盘 提取码&#xff1a;n5hj 2、解压 解压安装包&#xff0c;输入命令&#xff1a; tar -xvf jdk-8u221-linux-x64.tar.gz 解压完成后会生成一个新文件 3、配置环境变量 编辑profile文件 vim /etc/p…

基于java+springboot+mybatis+vue+mysql的高校党务系统

项目介绍 本党务管理系统主要包括五大功能模块&#xff0c;即管理员模块、学生模块、积极分子模块、党员、党建组织。 &#xff08;1&#xff09;管理员模块&#xff1a;主要功能有&#xff1a;首页、个人中心、学生管理、学院管理、专业管理、班级管理、积极分子管理、党员管…

LeetCode HOT 100 —— 208. 实现 Trie (前缀树)

题目 Trie&#xff08;发音类似 “try”&#xff09;或者说 前缀树 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&#xff0c;例如自动补完和拼写检查。 请你实现 Trie类&#xff1a; Trie() 初始化前缀树对象。 vo…

postgresql_internals学习笔记(二)常规vacuum

一、 作用与原理 page pruning执行速度很快&#xff0c;但它们的作用范围毕竟只有单页、且不包含索引&#xff0c;因此&#xff0c;我们还需要更有效的清理机制。 常规vacuum是最常用的一种&#xff0c;作用范围可以是整张表&#xff0c;清理过期元组及索引项&#xff0c;并且不…

PS图层+移动工具(1)图层概念-拖动操作-移动工具基础

先打开ps软件 然后点击进入工作区 选择右上角文件 点击打开 随便选一个要操作的图片 然后看一下自己工作区右侧的 这个图层工具开了没有 如果没开 点击上方 窗口 将图层选项勾选上 这里可以看到 我们打开一个完整图片 他就只有一个图层 触发你打开的是PSD格式的图片 psd是ps…