在正式介绍完整的算法之前,让我们先看看如何为一个非常简单的网络手动计算单个梯度。这将帮助我们理解为什么链式法则如此重要。
对于本节内容,如果您暂时无法理解也请不必担心。
单个梯度计算
让我们以一个具有输入 x、权重 w、偏置 b 和激活函数 σ 的单个神经元为例。损失为 L。计算过程是:
1. 预激活:z=wx+b
2. 激活:a=σ(z)
3. 损失:L=Loss(a,y)
为了找到损失相对于权重 ∂w∂L 的梯度,我们需要看 w 的微小变化如何影响损失 L。链式法则告诉我们可以通过将每一步的变化率相乘来找到:
∂w∂L=∂a∂L×∂z∂a×∂w∂z
让我们分解每一项:
- ∂a∂L:这是神经元输出激活 a 变化时,损失如何变化。这是我们第一个需要计算的东西。
- ∂z∂a:这是激活函数的导数,σ′(z)。它告诉我们激活值如何根据预激活值变化。
- ∂w∂z:这是 wx+b 相对于 w 的导数,它就是 x。
因此,为了找到权重 w 的梯度,我们需要计算所有这些部分并将它们相乘。对于一个多层网络,这个导数链会更长,将网络深处的参数一直连接到最终的损失。反向传播算法只是一种结构化且高效的方法,可以同时为所有参数执行这个长链式法则计算。
链式法则的威力
本质上,神经网络是一系列嵌套函数。一层的输出成为下一层的输入。为了找出网络内部深处的参数的变化如何影响最终损失,我们需要重复应用链式法则。
考虑一个非常简单的网络计算:
1. 输入 x
2. 隐藏层预激活:z(1)=w(1)x+b(1)
3. 隐藏层激活:a(1)=σ(z(1)) (其中 σ 是激活函数)
4. 输出层预激活:z(2)=w(2)a(1)+b(2)
5. 输出层激活(预测):a(2)=σ(z(2))
6. 损失:L=Loss(a(2),y) (其中 y 是真实标签)
如果我们想找到损失 L 相对于第一层中的一个权重(例如 w(1))的梯度,我们需要追溯其对损失的影响路径:w(1) 影响 z(1),进而影响 a(1),再影响 z(2),接着影响 a(2),最终影响 L。链式法则允许我们分解这个计算:
∂w(1)∂L=∂a(2)∂L×∂z(2)∂a(2)×∂a(1)∂z(2)×∂z(1)∂a(1)×∂w(1)∂z(1)
反向传播有效地组织了这一计算。它首先计算像 ∂a(2)∂L 和 ∂z(2)∂L 这样的项,然后复用它们来计算前几层的梯度。
反向传播过程解释
该算法分两个主要阶段工作:
1. 前向传播: 输入数据逐层输入网络,每一步计算预激活值 (z(l)) 和激活值 (a(l)),最终得到最终输出预测 a(L)。在此过程中,我们存储中间值(所有层 l 的 z(l) 和 a(l)),因为反向传播过程将需要它们。最终损失 L 使用预测 a(L) 和真实目标 y 计算。
2. 反向传播: 该过程计算梯度。
* 输出层: 计算损失相对于输出层激活 ∂a(L)∂L 的梯度。然后,使用链式法则,计算损失相对于输出层预激活 z(L) 的梯度:
δ(L)=∂z(L)∂L=∂a(L)∂L∂z(L)∂a(L)=∂a(L)∂Lσ′(z(L))
其中,σ′(z(L)) 是输出层使用的激活函数在 z(L) 处的导数。这一项 δ(L) 表示输出层预激活处的“误差信号”。
现在,计算输出层权重 W(L) 和偏置 b(L) 的梯度:
∂W(L)∂L=∂z(L)∂L∂W(L)∂z(L)=δ(L)(a(L−1))T ∂b(L)∂L=∂z(L)∂L∂b(L)∂z(L)=δ(L)
(注意:具体形式取决于我们是否使用向量/矩阵记号。a(L−1) 表示传入输出层的上一层激活。转置是为了确保矩阵乘法的维度匹配)。
* 隐藏层(从 l=L−1 逆向到 l=1): 对于每个隐藏层 l,根据 下一层(更靠近输出层的那一层)的误差信号 δ(l+1) 来计算其误差信号 δ(l):
δ(l)=∂z(l)∂L=((W(l+1))Tδ(l+1))⊙σ′(z(l))
其中,(W(l+1))T 是连接层 l 和层 l+1 的权重。这一步有效地将误差梯度通过网络权重反向传播。项 σ′(z(l)) 是当前隐藏层 l 的激活函数的导数。符号 ⊙ 表示逐元素乘法(哈达玛积)。
一旦 δ(l) 已知,就可以像输出层一样计算层 l 的权重 W(l) 和偏置 b(l) 的梯度:
∂W(l)∂L=δ(l)(a(l−1))T ∂b(l)∂L=δ(l)
其中 a(l−1) 是传入层 l 的那一层的激活(对于第一个隐藏层,这将是输入数据 x)。
这个过程继续逆向进行,直到所有参数的梯度都已计算完毕。
流程可视化
我们可以将计算看作是向前流动以得到损失,然后向后流动以得到梯度。
前向(蓝色箭头)和反向(红色箭头)传播过程的简化视图。前向传播计算激活值和损失。反向传播计算梯度,从损失开始并逆向传播误差信号(如 δ(l)=∂z(l)∂L),复用前向传播过程中计算的值(a(l)、z(l))和网络权重(W(l))。参数(W,b)的梯度则从这些误差信号中得出。
为何高效?
反向传播的效率主要来自两个方面:
1. 计算复用: 在前向传播过程中计算的中间值(z(l)、a(l))会被存储并在反向传播过程中复用。更重要的是,为层 l+1 计算的误差信号(δ(l+1))直接用于计算层 l 的误差信号(δ(l))。这避免了冗余计算。
2. 动态规划: 它本质上使用了动态规划。通过从后向前逐层计算梯度,它构建出整个网络梯度的解,而无需独立地重新计算每个参数的影响路径。
与数值估计梯度相比(数值估计梯度对于 每个参数 至少需要一次额外的前向传播),反向传播以大致相当于单次前向传播的计算时间,计算出 所有 梯度。对于拥有数百万参数的网络来说,这种差异非常巨大,使得训练深度网络变得可行。
通过反向传播计算出梯度后,我们现在有了更新权重和偏置所需的方向,这将在以下部分详细说明。