深度网络现代实践 - 深度前馈网络之反向传播和其他的微分算法篇

序言

反向传播(Backpropagation,简称backprop)是神经网络训练过程中最关键的技术之一,尤其在多层神经网络中广泛应用。它是一种与优化方法(如梯度下降法)结合使用的算法,用于计算网络中各参数的梯度,进而通过调整这些参数来最小化损失函数,从而提高模型的预测准确性和泛化能力。微分算法在机器学习中占据核心地位,主要用于计算复杂函数的梯度。反向传播作为其中的一种,特别适用于神经网络中的梯度计算。其基本原理是利用链式法则,通过计算图中每个节点的梯度来逐步反向传播误差信号,从而实现对网络参数的优化。

反向传播和其他的微分算法

  • 当我们使用前馈神经网络接收输入 x \boldsymbol{x} x并产生输出 y ^ \hat{\boldsymbol{y}} y^时,信息通过网络向前流动。
  • 前向传播(forward propagation)
    • 输入 x \boldsymbol{x} x提供初始信息,然后传播到每一层的隐藏单元,最终产生输出 y ^ \hat{\boldsymbol{y}} y^
  • 反向传播(back propagation)
    • 在训练过程中,前向传播可以持续向前直到它产生一个标量代价函数 J ( θ ) J(\boldsymbol{\theta}) J(θ)反向传播(back propagation),经常简称为backprop,允许来自代价函数的信息通过网络向后流动,以便计算梯度。
    • 计算梯度的解析表达式是很直观的,但是数值化地求解这样的表达式在计算上可能是昂贵的。反向传播算法使用简单和廉价的程序来实现这个目标。
    • 反向传播这个术语经常被误解为用于多层神经网络的整个学习算法。实际上,反向传播仅指用于计算梯度的方法,而另一种算法,例如随机梯度下降,使用该梯度来进行学习。
    • 此外,反向传播仅适用于多层神经网络,但原则上它可以计算任何函数的导数(对于一些函数,正确的响应是报告函数的导数是未定义的)。
    • 特别地,我们会描述如何计算一个任意函数 f f f的梯度 ∇ x f ( x , y ) \nabla_x f(\boldsymbol{x,y}) xf(x,y)
      • 其中 x \boldsymbol{x} x是一组变量,我们需要它们的导数
      • y \boldsymbol{y} y是另外一组函数的输入变量,但我们并不需要它们的导数。
    • 在学习算法中,我们最常需要的梯度是成本函数关于参数的梯度,即 ∇ θ J ( θ ) \nablaθJ(θ) θJ(θ)。许多机器学习任务涉及计算其他导数,作为学习过程的一部分,或者用来分析学习的模型。反向传播算法也适用于这些任务,并且不限于计算成本函数关于参数的梯度。通过网络传播信息来计算导数的想法是非常通用的,并且可以用于计算诸如具有多个输出的函数 f f f Jacobi \text{Jacobi} Jacobi矩阵的值。我们这里描述的是最常用的情况, f f f只有单个输出。

计算图(computational graphs)

  • 到目前为止我们已经用相对非正式的图形语言讨论了神经网络。为了更精确地描述反向传播算法,使用更精确的计算图(computational graphs)语言是很有帮助的。

  • 将计算形式化为图形的方法有很多。这里,我们使用图中的每一个节点来表示一个变量。变量可以是标量、向量、矩阵、张量、或者甚至是另一类型的变量。

  • 为了形式化我们的图形,我们还需要引入操作 (operation)。操作是一个或多个变量的简单函数。我们的图形语言伴随着一组被允许的操作。可以通过将多个操作组合在一起来描述比该组中的操作更复杂的函数。

  • 不失一般性,我们定义一个操作仅返回单个输出变量。这并没有失去一般性,因为输出变量可以有多个条目,例如向量。反向传播的软件实现通常支持具有多个输出的操作,但是我们在描述中避免这种情况,因为它引入了对概念理解不重要的许多额外细节。

  • 如果变量 y y y是变量 x x x通过一个操作计算得到的,那么我们画一条从 x x x y y y的有向边。我们有时用操作的名称来注释输出的节点,当上下文很明确时有时也会省略这个标注。

  • 例如,计算图的示例
    在这里插入图片描述

  • 说明

    • 图(a):使用乘法符x操作计算 z = x y z=xy z=xy的计算图。
    • 图(b):用于逻辑回顾预测 y ^ = σ ( x ⊤ w + b ) \hat{y}=\sigma(\boldsymbol{x}^\top\boldsymbol{w}+b) y^=σ(xw+b)的计算图。注:一些中间表达式在代数表达式中没有名称,但在图形中却需要。
    • 图©:表达式 H = max ⁡ { 0 , X W + b } H=\max\{0, \boldsymbol{XW}+b\} H=max{0,XW+b}的计算图。在给定包含小批量输入数据的设计矩阵 X \boldsymbol{X} X时,它计算整流线性单元激活的设计矩阵 H \boldsymbol{H} H
    • 图(d):示例a-c对每个变量最多只实施一个操作,但是对变量实施多个操作也是可能的。这里我们展示一个计算图,它对线性回归模型的权重 w \boldsymbol{w} w实施多个操作。这个权重不仅用于预测 y ^ \hat{y} y^,也用于权重衰减惩罚项 λ ∑ i w i 2 \lambda\sum_i w_i^2 λiwi2

微积分中的链式法则(chain rule of calculus)

  • 微积分中的链式法则(为了不与概率中的链式法则相混淆)用于计算复合函数的导数反向传播是一种计算链式法则的算法,使用高效的特定运算顺序。
  • 反向传播算法应用标量情况
    • x x x是实数, f f f g g g是从实数映射到实施的函数。
      • 假设 y = g ( x ) y=g(x) y=g(x)并且 z = f ( g ( x ) ) = f ( y ) z=f(g(x))=f(y) z=f(g(x))=f(y)
      • 那么,链式法则,即 d z d x = d z d y d y d x \displaystyle\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx} dxdz=dydzdxdy,给出了复合函数 z = f ( g ( x ) ) z=f(g(x)) z=f(g(x))关于 x x x的导数。
  • 我们可以将这种标量情况进行扩展,即应用于向量情况
    • 假设 x ∈ R m \boldsymbol{x}\in\mathbb{R}^m xRm y ∈ R n \boldsymbol{y}\in\mathbb{R}^n yRn g g g R m \mathbb{R}^m Rm R n \mathbb{R}^n Rn的映射, f f f R n \mathbb{R}^n Rn R \mathbb{R} R的映射。
    • 如果 y = g ( x ) \boldsymbol{y}=g(\boldsymbol{x}) y=g(x)并且 z = f ( y ) z=f(\boldsymbol{y}) z=f(y),那么链式法则,即 ∂ z ∂ x i = ∑ j ∂ z ∂ y i ∂ y i ∂ x i \displaystyle\frac{\partial z}{\partial \boldsymbol{x}_i}=\sum\limits_j\frac{\partial z}{\partial y_i}\frac{\partial y_i}{\partial x_i} xiz=jyizxiyi,给出了复合函数 z = f ( g ( x ) ) z=f(g(\boldsymbol{x})) z=f(g(x))关于 x \boldsymbol{x} x的导数。
    • 使用向量记法,可以等价地写成: ∇ x z = ( ∂ y ∂ x ) ⊤ ∇ y z \nabla_{\boldsymbol{x}}z=\left(\frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}}\right)^\top\nabla_{\boldsymbol{y}}z xz=(xy)yz。其中 ∂ y ∂ x \displaystyle\frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}} xy g g g n × m n\times m n×mJacobi矩阵
    • 从这里我们看到变量 x \boldsymbol{x} x的梯度可以通过将 Jacobi \text{Jacobi} Jacobi矩阵 ∂ y ∂ x \displaystyle\frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}} xy g g g n × m n\times m n×m乘以梯度 ∇ y z \nabla_{\boldsymbol{y}}z yz来得到。反向传播算法由图中每一个这样的 Jacobi \text{Jacobi} Jacobi矩阵的乘积操作所组成的。
  • 反向传播算法应用于张量的情况
    • 通常我们不将反向传播算法仅用于向量,而是应用于任意维度的张量
    • 从概念上讲,这与使用向量的反向传播完全相同。
    • 唯一的区别是如何将数字排列成网格以形成张量。
    • 我们可以想象,在我们运行反向传播之前,将每个张量变平为一个向量,计算一个向量值梯度,然后将该梯度重新构造成一个张量。
    • 从这种重新排列的观点上看,反向传播仍然只是将 Jacobi \text{Jacobi} Jacobi矩阵乘以梯度。
    • 为了表示值 z z z对张量 X \bold{X} X的梯度,我们记为: ∇ X z \nabla_{\bold{X}}z Xz,就像 X \bold{X} X是向量一样。 X \bold{X} X的索引现在有多个坐标。
      • 例如,一个3维的张量由三个坐标索引。我们可以通过使用单个变量 i i i来表示完整的索引元组,从而完全抽象出来。
      • 对所有可能的元组 i i i ( ∇ X z ) i \left(\nabla_{\bold{X}}z\right)_i (Xz)i给出 ∂ z ∂ X i \displaystyle\frac{\partial z}{\partial X_{i}} Xiz
      • 这与向量中索引的方式完全一致, ( ∇ x z ) i \left(\nabla_{\boldsymbol{x}}z\right)_i (xz)i给出 ∂ z ∂ x i \displaystyle\frac{\partial z}{\partial x_{i}} xiz
      • 使用这种记法,我们可以写出适用于张量的链式法则。
      • 如果 Y = g ( X ) \bold{Y}=g(\bold{X}) Y=g(X)并且 z = f ( Y ) z=f(\bold{Y}) z=f(Y),那么张量的链式法则,即 ∇ X z = ∑ j ( ∇ X Y j ) ∂ z ∂ Y j \nabla_{\bold{X}}z=\sum\limits_j(\nabla_{\bold{X}}\bold{Y}_j)\frac{\partial z}{\partial \bold{Y}_j} Xz=j(XYj)Yjz

递归地使用链式法则来实现反向传播算法

  • 使用链式法则,可以直接写出某个标量对于计算图中任何产生该标量的节点的梯度的代数表达式。然而,实际在计算机中计算该表达式时会引入一些额外的考虑。

  • 具体来说,许多子表达式可能在梯度的整个表达式中重复若干次。任何计算梯度的程序都需要选择是存储这些子表达式还是重新计算它们几次。

    • 例如,计算梯度时导致重复子表达式的计算图
      在这里插入图片描述

    • 说明

      • w ∈ R w\in\mathbb{R} wR为图的输入。
      • 我们对链中的每一步使用相同的操作函数: f : R → R f: \mathbb{R} \rightarrow \mathbb{R} f:RR,这样 x = f ( w ) , y = f ( x ) , z = f ( y ) x=f(w),y=f(x),z=f(y) x=f(w),y=f(x),z=f(y)
      • 为了计算 ∂ z ∂ w \frac{\partial z}{\partial w} wz,我们应用公式: d z d x = d z d y d y d x \displaystyle\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx} dxdz=dydzdxdy得到:
        { ∂ z ∂ w = ∂ z ∂ y ∂ y ∂ x ∂ x ∂ w = f ′ ( y ) f ′ ( x ) f ′ ( w ) 公式1 = f ′ ( f ( f ( w ) ) ) f ′ ( f ( w ) ) f ′ ( w ) 公式2 \begin{cases}\begin{aligned} \frac{\partial z}{\partial w} &= \frac{\partial z}{\partial y} \frac{\partial y}{\partial x} \frac{\partial x}{\partial w}\\ &= f'(y) f'(x) f'(w) \quad \text{公式1}\\ &= f'(f(f(w))) f'(f(w)) f'(w)\quad \text{公式2}\end{aligned} \end{cases} wz=yzxywx=f(y)f(x)f(w)公式1=f(f(f(w)))f(f(w))f(w)公式2
      • 公式1:
        • 建议我们采用的实现方式是,仅计算 f ( w ) f(w) f(w)的值一次并将它存储在变量 x x x中。
        • 这是反向传播算法所采用的方法。
      • 公式2:
        • 提供了一种替代方法,其中子表达式 f ( w ) f(w) f(w)出现了不止一次。
        • 在替代方法中,每次只在需要时重新计算$f(w)。
        • 当存储这些表达式的值所需的存储较少时,公式2的反向传播方法显然是较优的,因为它减少了运行时间。
        • 然而,公式2也是链式法则的有效实现,并且当存储受限时它是有用的。
  • 上图给出了一个例子来说明这些重复的子表达式是如何出现的。在某些情况下,计算两次相同的子表达式纯粹是浪费。在复杂图中,可能存在指数多的这种计算上的浪费,使得简单的链式法则不可实现。在其他情况下,计算两次相同的子表达式可能是以较高的运行时间为代价来减少内存开销的有效手段。

  • 我们首先给出一个版本的反向传播算法,它指明了梯度的直接计算方式(算法2以及相关的正向计算的算法1,按照它实际完成的顺序并且递归地使用链式法则。可以直接执行这些计算或者将算法的描述视为用于计算反向传播的计算图的符号表示。然而,这些公式并没有明确地操作和构造用于计算梯度的符号图。这些公式在后面的内容中给出,其中我们还推广到了包含任意张量的节点。

  • 首先考虑描述如何计算单个标量 u ( n ) u^{(n)} u(n)(例如训练样例上的损失函数)的计算图。

    • 我们想要计算这个标量对 n i n_i ni个输入节点 u ( 1 ) u^{(1)} u(1) u ( n i ) u^{(n_i)} u(ni)的梯度。
    • 换句话说,我们希望对所有的 i ∈ { 1 , 2 , … , n i } i\in\{1,2,\dots,n_i\} i{1,2,,ni},计算 ∂ u ( n ) ∂ u ( i ) \displaystyle\frac{\partial u^{(n)}}{\partial u^{(i)}} u(i)u(n)
    • 在用反向传播计算梯度来实现参数的梯度下降时, u ( n ) u^{(n)} u(n)将对应单个或者小批量实例的代价函数,而 u ( 1 ) u^{(1)} u(1) u ( n i ) u^{(n_i)} u(ni)则对应于模型的参数。
  • 我们将假设图的节点已经以一种特殊的方式被排序,使得我们可以一个接一个地计算他们的输出,从 u ( n i + 1 ) u^{(n_i+1)} u(ni+1)开始,一直上升到 u ( n ) u^{(n)} u(n)。如算法1中所定义的,每个节点 u ( i ) u^{(i)} u(i)与操作 f ( i ) f^{(i)} f(i)相关联,并且通过对该函数求值得到: u ( i ) = f ( A ( i ) ) u^{(i)}=f(\mathbb{A}^{(i)}) u(i)=f(A(i)),其中 A ( i ) \mathbb{A}^{(i)} A(i) u ( i ) u^{(i)} u(i)所有双亲节点的集合。

  • 算法1


    计算将 n i n_i ni个输入 u ( 1 ) u^{(1)} u(1) u ( n i ) u^{(n_i)} u(ni)映射到一个输出 u ( n ) u^{(n)} u(n)的程序。
    这定义了一个计算图,其中每个节点通过将函数 f ( i ) f^{(i)} f(i)应用到变量集合 A ( i ) \mathbb{A}^{(i)} A(i)上来计算 u ( i ) u^{(i)} u(i)的值, A ( i ) \mathbb{A}^{(i)} A(i)包含先前节点 u ( j ) u^{(j)} u(j)的值满足 j < i j<i j<i j ∈ P a ( u ( i ) ) j\in Pa(u^{(i)}) jPa(u(i))
    计算图的输入是向量 x \boldsymbol{x} x,并且被分配给前 n i n_i ni个节点 u ( 1 ) u^{(1)} u(1) u ( n i ) u^{(n_i)} u(ni)
    计算图的输出可以从最后一个节点 u ( n ) u^{(n)} u(n)读出。


    伪代码
    f o r i = 1 , … , n i d o u ( i ) ← x i e n d f o r f o r i = n i + 1 , … , n d o A ( i ) ← { u ( j ) ∣ j ∈ P a ( u ( i ) ) } u ( i ) ← f ( i ) ( A ( i ) ) e n d f o r r e t u r n u ( n ) \bold{for}\quad i=1,\dots,n_i \quad \bold{do}\\ \qquad u^{(i)} \gets x_i\\ \bold{end}\quad\bold{for}\\ \bold{for}\quad i=n_i+1,\dots,n \quad \bold{do}\\ \qquad \mathbb{A}^{(i)} \gets \{u^{(j)} \mid j\in Pa(u^{(i)})\}\\ \qquad u^{(i)} \gets f^{(i)}(\mathbb{A}^{(i)})\\ \bold{end}\quad\bold{for}\\ \bold{return}\quad u^{(n)} fori=1,,nidou(i)xiendforfori=ni+1,,ndoA(i){u(j)jPa(u(i))}u(i)f(i)(A(i))endforreturnu(n)


  • 算法1说明:

    • 算法1详细说明了前向传播的计算,我们可以将其放入图 G \mathcal{G} G中。
    • 为了执行反向传播,我们可以构造一个依赖于 G \mathcal{G} G并添加额外一组节点的计算图。这形成了一个子图 B \mathcal{B} B,它的每个节点都是 G \mathcal{G} G的节点。
    • B \mathcal{B} B中的计算顺序完全相反,而且 B \mathcal{B} B的每个节点计算导数 ∂ u ( n ) ∂ u ( i ) \displaystyle\frac{\partial u^{(n)}}{\partial u^{(i)}} u(i)u(n)与前向图中的节点 u ( i ) u^{(i)} u(i)相关联。
    • 这通过对标量输出 u ( n ) u^{(n)} u(n)使用链式法则来完成: ∂ u ( n ) ∂ u ( j ) = ∑ i : j ∈ P a ( u ( i ) ) ∂ u ( n ) ∂ u ( i ) ∂ u ( i ) ∂ u ( j ) \displaystyle\frac{\partial u^{(n)}}{\partial u^{(j)}}=\sum\limits_{i:j\in Pa(u^{(i)})}\frac{\partial u^{(n)}}{\partial u^{(i)}} \frac{\partial u^{(i)}}{\partial u^{(j)}} u(j)u(n)=i:jPa(u(i))u(i)u(n)u(j)u(i)。注:在算法2中详细说明
  • 子图 B \mathcal{B} B恰好包含每一条对应着 G \mathcal{G} G中从节点 u ( j ) u^{(j)} u(j)到节点 u ( i ) u^{(i)} u(i)的边。从节点 u ( j ) u^{(j)} u(j)到节点 u ( i ) u^{(i)} u(i)的边对应着计算 ∂ u ( i ) ∂ u ( j ) \displaystyle\frac{\partial u^{(i)}}{\partial u^{(j)}} u(j)u(i)

  • 另外,对于每个节点都要执行一个内积,内积的一个因子是对于 u ( j ) u^{(j)} u(j)孩子节点 u ( i ) u^{(i)} u(i)的已经计算的梯度,另一个因子是对于相同孩子节点 u ( i ) u^{(i)} u(i)的偏导数 ∂ u ( i ) ∂ u ( j ) \displaystyle\frac{\partial u^{(i)}}{\partial u^{(j)}} u(j)u(i)组成的向量。

  • 总而言之,执行反向传播所需的计算量与 G \mathcal{G} G中的边的数量成比例,其中每条边的计算包括计算偏导数(节点关于它的一个双亲节点的偏导数)以及执行一次乘法和一次加法。下面,我们将此分析推广到张量值节点,这只是在同一节点中对多个标量值进行分组并能够更有效的实现。

  • 反向传播算法被设计为减少公共子表达式的数量而不考虑存储的开销。

    • 具体来说,它执行了图中每个节点一个 Jacobi \text{Jacobi} Jacobi乘积的数量的计算。
    • 这可以从算法2中看出,反向传播算法访问了图中的节点 u ( j ) u^{(j)} u(j)到节点 u ( i ) u^{(i)} u(i) 的每条边一次,以获得相关的偏导数 ∂ u ( i ) ∂ u ( j ) \displaystyle\frac{\partial u^{(i)}}{\partial u^{(j)}} u(j)u(i)
    • 反向传播因此避免了重复子表达式的指数爆炸。然而,其他算法可能通过对计算图进行简化来避免更多的子表达式,或者也可能通过重新计算而不是存储这些子表达式来节省内存。
    • 我们将在描述完反向传播算法本身后再重新审视这些想法。

全连接MLP中反向传播算法的计算

  • 为了阐明反向传播的上述定义,让我们考虑一个与全连接的多层MLP相关联的特定图。
  • 算法3首先给出了前向传播,它将参数映射到与单个训练样例(输入,目标)( x , y \boldsymbol{x},\boldsymbol{y} x,y)相关联的有监督损失函数 L ( y ^ , y ) L(\boldsymbol{\hat{y}},\boldsymbol{y}) L(y^,y),其中 y ^ \boldsymbol{\hat{y}} y^是当 x \boldsymbol{x} x提供输入时神经网络的输出。
  • 算法4随后说明了将反向传播应用于改图所需的相关计算。
  • 算法3和算法4是简单而直观的演示。然而,它们专门针对特定的问题。
  • 现在的软件实现基于之后符号到符号的导数中描述的一般形式的反向传播,它可以通过明确地操作用于表示符号计算的数据结构,来适应任何计算图。

符号到符号的导数

  • 代数表达式和计算图都对符号 (symbol) 或不具有特定值的变量进行操作。这些代数或者基于图的表达式被称为符号表示 (symbolic representation)。当我们实际使用或者训练神经网络时,我们必须给这些符号赋值。我们用一个特定的数值 (numeric value) 来替代网络的符号输入 x \boldsymbol{x} x,例如 [ 1.2 , 3 , 765 , − 1.8 ] ⊤ [1.2,3,765,-1.8]^\top [1.2,3,765,1.8]

  • 一些反向传播的方法采用计算图和一组用于图的输入的数值,然后返回在这些输入值处梯度的一组数值。我们将这种方法称为“符号到数值”的微分。这种方法用在诸如 Torch(Collobert et al., 2011b) 和 Caffe(Jia, 2013) 之类的库中。

  • 另一种方法是采用计算图以及添加一些额外的节点到计算图中,这些额外的节点提供了我们所需导数的符号描述。这是 Theano(Bergstra et al., 2010b; Bastien et al., 2012b) 和 TensorFlow(Abadi et al., 2015) 采用的方法。

  • 例如,使用符号到符号的方法计算导数的示例
    在这里插入图片描述

  • 说明:

    • 使用符号到符号的方法计算导数的示例。在这种方法中,反向传播算法不需要访问任何实际的特定数值。相反,它将节点添加到计算图中来描述如何计算这些导数。
    • 通用图形求值引擎可以在随后计算任何特定数值的导数。
    • 左图:在这个例子中,我们从表示 z = f ( f ( f ( w ) ) ) z=f(f(f(w))) z=f(f(f(w)))的图开始。
    • 右图:我们运行反向传播算法,指导它构造表达式 ∂ z ∂ w \frac{\partial z}{\partial w} wz对应的图。在这个例子中,我们不解释反向传播算法如何工作。我们目的只是说明想要的结构是什么:具有导数的符号描述的计算图
  • 上图给出了该方法如何工作的一个例子。这种方法的主要优点是导数可以使用与原始表达式相同的语言来描述。因为导数只是另外一张计算图,可以再次运行反向传播,对导数再进行求导以得到更高阶的导数。高阶导数的计算在高阶微分中描述。

  • 我们将使用后一种方法,并且使用构造导数的计算图的方法来描述反向传播算法。图的任意子集后来都可以使用特定的数值来求值。这允许我们避免完全指明每个操作应该在何时计算。相反,通用的图计算引擎只要当一个节点的父节点的值都可用时就可以进行求值。

  • 基于符号到符号的方法的描述包含了符号到数值的方法。符号到数值的方法可以理解为执行了与符号到符号的方法中构建图的过程中完全相同的计算。关键的区别是符号到数值的方法不会显示出图形

一般化的反向传播

  • 反向传播算法非常简单。

  • 为了计算某个标量 z z z对图中它的一个祖先 x \boldsymbol{x} x的梯度,我们首先观察到对 z z z的梯度由 ∂ z ∂ z = 1 \displaystyle\frac{\partial z}{\partial z}=1 zz=1给出。我们然后可以计算对图中 z z z的操作的 Jacobi \text{Jacobi} Jacobi矩阵。我们继续乘以 Jacobi \text{Jacobi} Jacobi矩阵,以这种方式向后穿过图,直到我们到达 x \boldsymbol{x} x。对于从 z z z触发可以经过两个或更多路径向后行进而到达的任意节点,我们简单的对该节点来自不同路径上的梯度进行求和。

  • 算法2


    反向传播算法的简化版本,用于计算 u ( n ) u^{(n)} u(n)对图中变量的导数。
    这个示例旨在通过演示所有变量都是标量的简化情况来进一步理解反向传播算法,这里我们 希望计算关于 u ( 1 ) , … , u ( n ) u^{(1)},\dots,u^{(n)} u(1),,u(n)的导数。这个简化版本计算了关于图中所有节点的导数。
    假定与每条边相关联的偏导数计算需要恒定的时间的话,该算法的计算成本与图中边的数量成比例。
    这与前向传播的计算次数具有相同的阶。每个 ∂ u ( i ) ∂ u ( j ) \displaystyle\frac{\partial u^{(i)}}{\partial u^{(j)}} u(j)u(i)的父节点 u ( j ) u^{(j)} u(j)的函数,从而将前向图的节点链接到反向传播图中添加的节点。


    伪代码
    运行前向传播(算法1)以获得网络激活
    初始化grad_table,是一种存储计算过的导数的数据结构
    grad_table [ u ( n ) ] \text{grad\_table}[u^{(n)}] grad_table[u(n)]是存储 ∂ u ( n ) ∂ u ( i ) \displaystyle\frac{\partial u^{(n)}}{\partial u^{(i)}} u(i)u(n)的计算值
    grad_table [ u ( n ) ] ← 1 f o r j = n − 1 down to 1 d o The next line computes ∂ u ( n ) ∂ u ( j ) = ∑ i : j ∈ P a ( u ( i ) ) ∂ u ( n ) ∂ u ( i ) ∂ u ( i ) ∂ u ( j ) using stored values: grad_table [ u ( j ) ] ← ∑ i : j ∈ P a ( u ( i ) ) grad_table [ u ( i ) ] ⋅ ∂ u ( i ) ∂ u ( j ) e n d f o r r e t u r n { grad_table [ u ( i ) ] ∣ i = 1 , … , n i } \text{grad\_table}[u^{(n)}] \gets 1\\ \bold{for}\quad j=n-1 \quad\text{down to}\quad 1 \quad \bold{do}\\ \qquad \text{The next line computes}\quad \displaystyle\frac{\partial u^{(n)}}{\partial u^{(j)}}=\sum_{i:j\in Pa(u^{(i)})} \frac{\partial u^{(n)}}{\partial u^{(i)}} \frac{\partial u^{(i)}}{\partial u^{(j)}} \quad\text{using stored values:} \\ \qquad \text{grad\_table}[u^{(j)}] \gets \sum_{i:j\in Pa(u^{(i)})} \text{grad\_table}[u^{(i)}] \cdot \frac{\partial u^{(i)}}{\partial u^{(j)}}\\ \bold{end}\quad\bold{for} \\ \bold{return}\quad \{\text{grad\_table}[u^{(i)}]\mid i=1,\dots,n_i\} grad_table[u(n)]1forj=n1down to1doThe next line computesu(j)u(n)=i:jPa(u(i))u(i)u(n)u(j)u(i)using stored values:grad_table[u(j)]i:jPa(u(i))grad_table[u(i)]u(j)u(i)endforreturn{grad_table[u(i)]i=1,,ni}


总结

反向传播算法和自动微分技术是神经网络训练过程中不可或缺的组成部分。它们通过高效地计算梯度,使得神经网络的参数优化成为可能。反向传播算法利用链式法则,通过反向传播误差信号来逐层调整网络参数,而自动微分技术则通过构建计算图来自动完成这一复杂的计算过程。这些技术的结合,极大地简化了神经网络的训练过程,提高了模型的训练效率和性能。

本章涉及知识点参考往期内容

应用数学与机器学习基础 - 线性代数篇
深度网络现代实践 - 深度前馈网络之基于梯度的学习篇

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

香橙派AIpro开发板评测:部署yolov5模型实现图像和视频中物体的识别

OrangePi AIpro 作为业界首款基于昇腾深度研发的AI开发板&#xff0c;自发布以来就引起了我的极大关注。其配备的8/20TOPS澎湃算力&#xff0c;堪称目前开发板市场中的顶尖性能&#xff0c;实在令人垂涎三尺。如此强大的板子&#xff0c;当然要亲自体验一番。今天非常荣幸地拿到…

Pseudo-Label : The Simple and Efficient Semi-Supervised Learning Method--论文笔记

论文笔记 资料 1.代码地址 https://github.com/iBelieveCJM/pseudo_label-pytorch 2.论文地址 3.数据集地址 论文摘要的翻译 本文提出了一种简单有效的深度神经网络半监督学习方法。基本上&#xff0c;所提出的网络是以有监督的方式同时使用标记数据和未标记数据来训练的…

ASCII码对照表(Matplotlib颜色对照表)

文章目录 1、简介1.1 颜色代码 2、Matplotlib库简介2.1 简介2.2 安装2.3 后端2.4 入门例子 3、Matplotlib库颜色3.1 概述3.2 颜色图的分类3.3 颜色格式表示3.4 内置颜色映射3.5 xkcd 颜色映射3.6 颜色命名表 4、Colorcet库5、颜色对照表结语 1、简介 1.1 颜色代码 颜色代码是…

2024亚太杯数学建模竞赛(B题)的全面解析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024亚太杯数学建模竞赛&#xff08;B题&#xff09;的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有详尽的建模过程和解…

数据库-MySQL 实战项目——书店图书进销存管理系统数据库设计与实现(附源码)

一、前言 该项目非常适合MySQL入门学习的小伙伴&#xff0c;博主提供了源码、数据和一些查询语句&#xff0c;供大家学习和参考&#xff0c;代码和表设计有什么不恰当还请各位大佬多多指点。 所需环境 MySQL可视化工具&#xff1a;navicat&#xff1b; 数据库&#xff1a;MySq…

MySQL:如何在已经使用的数据表中增加一个自动递增的字段

目录 一、需求 二、实现步骤 &#xff08;一&#xff09;数据表students &#xff08;二&#xff09;添加整型字段 &#xff08;三&#xff09;更新SID字段的值 1、使用用户定义的变量和JOIN操作 2、用SET语句和rownum变量 &#xff08;1&#xff09;操作方法 &#x…

使用antd的<Form/>组件获取富文本编辑器输入的数据

前端开发中&#xff0c;嵌入富文本编辑器时&#xff0c;可以通过富文本编辑器自身的事件处理函数将数据传输给后端。有时候&#xff0c;场景稍微复杂点&#xff0c;比如一个输入页面除了要保存富文本编辑器的内容到后端&#xff0c;可能还有一些其他输入组件获取到的数据也一并…

MySQL篇三:数据类型

文章目录 前言1. 数值类型1.1 tinyint类型1.2 bit类型1.3 小数类型1.3.1 float1.3.2 decimal 2. 字符串类型2.1 char2.2 varchar2.3 char和varchar比较 3. 日期类型4. enum和set 前言 数据类型分类&#xff1a; 1. 数值类型 1.1 tinyint类型 在MySQL中&#xff0c;整型可以指…

如何第一次从零上传项目到GitLab

嗨&#xff0c;我是兰若&#xff0c;今天想给大家说下&#xff0c;如何上传一个完整的项目到与LDAP集成的GitLab&#xff0c;也就是说这个项目之前是不在git上面的&#xff0c;这是第一次上传&#xff0c;这样上传上去之后&#xff0c;其他小伙伴就可以根据你这个项目的git地址…

自动批量将阿里云盘文件发布成WordPress文章脚本源码(以RiPro主题为例含付费信息下载地址SEO等自动设置)源码

背景 很多资源下载站&#xff0c;付费资源下载站&#xff0c;付费内容查看等都可以用WordPress站点发布内容&#xff0c;这些站点一般会基于一个主题&#xff0c;付费信息作为文章附属的信息发布&#xff0c;底层存储在WP表里&#xff0c;比如日主题&#xff0c;子比主题等。 …

2-5 softmax 回归的简洁实现

我们发现通过深度学习框架的高级API能够使实现线性回归变得更加容易。 同样&#xff0c;通过深度学习框架的高级API也能更方便地实现softmax回归模型。 本节如在上节中一样&#xff0c; 继续使用Fashion-MNIST数据集&#xff0c;并保持批量大小为256。 import torch from torc…

【基础篇】第4章 Elasticsearch 查询与过滤

在Elasticsearch的世界里&#xff0c;高效地从海量数据中检索出所需信息是其核心价值所在。本章将深入解析查询与过滤的机制&#xff0c;从基础查询到复合查询&#xff0c;再到全文搜索与分析器的定制&#xff0c;为你揭开数据检索的神秘面纱。 4.1 基本查询 4.1.1 Match查询…

多语言版在线出租车预订完整源码+用户应用程序+管理员 Laravel 面板+ 司机应用程序最新版源码

源码带PHP后台客户端源码 Flutter 是 Google 开发的一款开源移动应用开发 SDK。它用于开发 Android 和 iOS 应用&#xff0c;也是为 Google Fuchsia 创建应用的主要方法。Flutter 小部件整合了所有关键的平台差异&#xff0c;例如滚动、导航、图标和字体&#xff0c;可在 iOS 和…

如何在前端网页实现live2d的动态效果

React如何在前端网页实现live2d的动态效果 业务需求&#xff1a; 因为公司需要做机器人相关的业务&#xff0c;主要是聊天形式的内容&#xff0c;所以需要一个虚拟的卡通形象。而且为了更直观的展示用户和机器人对话的状态&#xff0c;该live2d动画的嘴型需要根据播放的内容来…

昇思25天学习打卡营第08天 | 模型训练

昇思25天学习打卡营第08天 | 模型训练 文章目录 昇思25天学习打卡营第08天 | 模型训练超参数损失函数优化器优化过程 训练与评估总结打卡 模型训练一般遵循四个步骤&#xff1a; 构建数据集定义神经网络模型定义超参数、损失函数和优化器输入数据集进行训练和评估 构建数据集和…

【Excel、RStudio计算T检测的具体操作步骤】

目录 一、基础知识1.1 显著性检验1.2 等方差T检验、异方差T检验1.3 单尾p、双尾p1.3.1 检验目的不同1.3.2 用法不同1.3.3 如何选择 二、Excel2.1 统计分析工具2.1.1 添加统计分析工具2.1.2 数据分析 2.2 公式 -> 插入函数 -> T.TEST 三、RStudio 一、基础知识 参考: 1.…

无人机运营合格证及无人机驾驶员合格证(AOPA)技术详解

无人机运营合格证及无人机驾驶员合格证&#xff08;AOPA&#xff09;技术详解如下&#xff1a; 一、无人机运营合格证 无人机运营合格证是无人机运营企业或个人必须获得的证书&#xff0c;以确保无人机在运营过程中符合相关法规和标准。对于无人机运营合格证的具体要求和申请…

【React】React18 Hooks之useState

目录 useState案例1&#xff08;直接修改状态&#xff09;案例2&#xff08;函数式更新&#xff09;案例3&#xff08;受控表单绑定&#xff09;注意事项1&#xff1a;set函数不会改变正在运行的代码的状态注意事项2&#xff1a;set函数自动批量处理注意事项3&#xff1a;在下次…

【反悔堆 优先队列 临项交换 决策包容性】630. 课程表 III

本文涉及知识点 贪心 反悔堆 优先队列 临项交换 Leetcode630. 课程表 III 这里有 n 门不同的在线课程&#xff0c;按从 1 到 n 编号。给你一个数组 courses &#xff0c;其中 courses[i] [durationi, lastDayi] 表示第 i 门课将会 持续 上 durationi 天课&#xff0c;并且必…

E4.【C语言】练习:while和getchar的理解

#include <stdio.h> int main() {int ch 0;while ((ch getchar()) ! EOF){if (ch < 0 || ch>9)continue;putchar(ch);}return 0; } 理解上述代码 0-->48 9-->57 if行判断是否为数字&#xff0c;打印数字&#xff0c;不打印非数字