当前位置: 首页 > news >正文

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

序言

反向传播(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}


总结

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

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

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

相关文章:

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

序言 反向传播&#xff08;Backpropagation&#xff0c;简称backprop&#xff09;是神经网络训练过程中最关键的技术之一&#xff0c;尤其在多层神经网络中广泛应用。它是一种与优化方法&#xff08;如梯度下降法&#xff09;结合使用的算法&#xff0c;用于计算网络中各参数的…...

自动化设备上位机设计 四

目录 一 设计原型 二 后台代码 一 设计原型 二 后台代码 using SimpleTCP; using SqlSugar; using System.Text;namespace 自动化上位机设计 {public partial class Form1 : Form{SqlHelper sqlHelper new SqlHelper();SqlSugarClient dbContent null;bool IsRun false;i…...

[leetcode hot 150]第二十三题,合并K个升序链表

题目&#xff1a; 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例 1&#xff1a; 输入&#xff1a;lists [[1,4,5],[1,3,4],[2,6]] 输出&#xff1a;[1,1,2,3,4,4,5,6] 解释&#xff1a…...

MybatisPlus实现插入/修改数据自动设置时间

引言 插入数据时自动设置当前时间&#xff0c;更新数据时自动修改日期为修改时的日期。 使用MybatisPlus的扩展接口MetaObjectHandler 步骤 实现接口 实体类加注解 实现接口 package com.example.vueelementson.common;import com.baomidou.mybatisplus.core.handlers.M…...

Java语言程序设计篇一

Java语言概述 Java语言起源编程语言最新排名名字起源Java语言发展历程Java语言的特点Java虚拟机垃圾回收Java语言规范Java技术简介Java程序的结构Java程序注意事项&#xff1a;注释编程风格练习 Java语言起源 1990年Sun公司提出一项绿色计划。1992年语言开发成功最初取名为Oak…...

Calicoctl工具学习 —— 筑梦之路

官方文档&#xff1a; Calico Documentation | Calico Documentation 插件方式安装 calicoctl 工具 curl -o kubectl-calico -O -L "https://github.com/projectcalico/calicoctl/releases/download/v3.20.0/calicoctl"cp kubectl-calico /usr/bin/kubectl-calic…...

Wormhole Filters: Caching Your Hash on Persistent Memory——泛读笔记

EuroSys 2024 Paper 论文阅读笔记整理 问题 近似成员关系查询&#xff08;AMQ&#xff09;数据结构可以高效地近似确定元素是否在集合中&#xff0c;例如Bloom滤波器[10]、cuckoo滤波器[23]、quotient滤波器[8]及其变体。但AMQ数据结构的内存消耗随着数据规模的增长而快速增长…...

PyTorch学习之torch.transpose函数

PyTorch学习之torch.transpose函数 一、简介 torch.transpose 函数我们用于交换张量的维度。 二、语法 torch.transpose 函数用于交换给定张量的两个维度&#xff0c;其语法如下&#xff1a; torch.transpose(input, dim0, dim1)三、参数 input&#xff1a;待交换维度的张…...

Git仓库介绍

1. Github GitHub 本身是一个基于云端的代码托管平台&#xff0c;它提供的是远程服务&#xff0c;而不是一个可以安装在本地局域网的应用程序。因此&#xff0c;GitHub 不可以直接在本地局域网进行安装。 简介&#xff1a;GitHub是最流行的代码托管平台&#xff0c;提供了大量…...

人工智能笔记分享

文章目录 人工智能图灵测试分类分类与聚类的区别&#xff08;重点&#xff09;分类 (Classification)聚类 (Clustering) 特征提取 分类器&#xff08;重点&#xff09;特征提取为什么要进行特征提取&#xff1f;&#xff08;重点&#xff09;分类器 训练集、测试集大小&#x…...

秋招提前批面试经验分享(上)

⭐️感谢点开文章&#x1f44b;&#xff0c;欢迎来到我的微信公众号&#xff01;我是恒心&#x1f60a; 一位热爱技术分享的博主。如果觉得本文能帮到您&#xff0c;劳烦点个赞、在看支持一下哈&#x1f44d;&#xff01; ⭐️我叫恒心&#xff0c;一名喜欢书写博客的研究生在读…...

[AIGC] ClickHouse的表引擎介绍

ClickHouse是一种高性能的列式数据库管理系统&#xff0c;支持各种不同的表引擎。表引擎是数据库系统中的核心组件&#xff0c;它定义了数据的存储方式和访问方式。本文将介绍ClickHouse中常见的表引擎及其特点。 文章目录 一、MergeTree引擎二、ReplacingMergeTree引擎三、Sum…...

关于新装Centos7无法使用yum下载的解决办法

起因 之前也写了一篇类似的文章&#xff0c;但感觉有漏洞&#xff0c;这次想直接把漏洞补齐。 问题描述 在我们新装的Centos7中&#xff0c;如果想要用C编程&#xff0c;那就必须要用到yum下载&#xff0c;但是&#xff0c;很多新手&#xff0c;包括我使用yum下载就会遇到一…...

OpenEarthMap:全球高分辨率土地覆盖制图的基准数据集(开源来下载!!!)

OpenEarthMap由220万段5000张航拍和卫星图像组成&#xff0c;覆盖6大洲44个国家97个地区&#xff0c;在0.25-0.5m的地面采样距离上人工标注8类土地覆盖标签。我们提供8类标注:裸地、牧场、已开发空间、道路、树木、水、农业用地和建筑。类选择与现有的具有亚米GSD的产品和基准数…...

工作助手VB开发笔记(1)

1.思路 1.1 样式 样式为常驻前台的一个小窗口&#xff0c;小窗口上有三到四个按钮&#xff0c;为一级功能&#xff0c;是当前工作内容的常用功能窗口&#xff0c;有十个二级窗口&#xff0c;为选中窗口时的扩展选项&#xff0c;有若干后台功能&#xff0c;可选中至前台 可最…...

WAWA鱼曲折的大学四年回忆录

声明&#xff1a;本文内容纯属个人主观臆断&#xff0c;如与事实不符&#xff0c;请参考事实 前言&#xff1a; 早想写一下大学四年的总结了&#xff0c;但总是感觉无从下手&#xff0c;不知道从哪里开始写&#xff0c;通过这篇文章主要想做一个记录&#xff0c;并从现在的认…...

Go 依赖注入设计模式

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...

使用React复刻ThreeJS官网示例——keyframes动画

最近在看three.js相关的东西&#xff0c;想着学习一下threejs给的examples。源码是用html结合js写的&#xff0c;恰好最近也在学习react&#xff0c;就用react框架学习一下。 本文参考的是threeJs给的第一个示例 three.js examples (threejs.org) 一、下载threeJS源码 通常我们…...

嵌入式linux面试1

1. linux 1.1. Window系统和Linux系统的区别 linux区分大小写windows在dos&#xff08;磁盘操作系统&#xff09;界面命令下不区分大小写&#xff1b; 1.2. 文件格式区分 windows用扩展名区分文件&#xff1b;如.exe代表执行文件&#xff0c;.txt代表文本文件&#xff0c;.…...

智能交通(3)——Learning Phase Competition for Traffic Signal Control

论文分享 https://dl.acm.org/doi/pdf/10.1145/3357384.3357900https://dl.acm.org/doi/pdf/10.1145/3357384.3357900 论文代码 https://github.com/gjzheng93/frap-pubhttps://github.com/gjzheng93/frap-pub 摘要 越来越多可用的城市数据和先进的学习技术使人们能够提…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...