反向传播:梯度如何传回来
沿计算图应用链式法则,高效算出梯度;更新参数则留给优化器。
算梯度要多少钱?
上一课已经把预测与标签的差距变成了损失。现在的问题是:损失对每个权重的梯度,怎样高效算出来?第 07~08 课的函数复合与链式法则,在这里成为计算图上的系统算法。下一课再使用这些梯度更新参数。
最笨的方法是数值微分:对每个参数 ,把它微微增大 ,看损失怎么变:
是第 i 个分量为 1、其余为 0 的单位向量。 算一个参数的梯度,需要一次额外的前向传播。
GPT-3 有 1750 亿个参数。算一次完整梯度,需要 1750 亿次额外前向传播。 每次前向传播本身就要处理整个网络——这需要的时间和能源是天文数字。
能否只用一次前向保存中间量,再做一次反向扫描,就算出所有参数梯度?
链式法则:梯度怎么流回去
反向传播的精神,可以用一个词概括:追责。输出层算出来错了一截,这份「错」该怎么 摊派给前面每一层、每一个权重?谁的影响越大,谁就该多背一点责任、被调整得多一点。 而链式法则,正是这套追责的精确账本。
微积分里的链式法则:如果 ,那么:
翻译一下:「L 怎么随 x 变化」= 「L 怎么随 g 变化」× 「g 怎么随 x 变化」。 如果 g 是一层网络,x 是上一层的输出,那么这个公式就告诉我们:只要知道「损失对这层输出的梯度」,就能算出「损失对这层输入的梯度」, 进而继续往前一层传。
每个节点在前向传播时记录自己的输入值; 反向传播时,用记录的输入值计算本地导数,再乘以「右边传来的梯度」, 结果继续往左传。这就是计算图(computational graph)的工作方式。
第 07 课的函数复合、第 08 课的链式法则预告,现在汇合成计算图上的反向传播。单一路径把局部导数相乘,同一个中间量影响多条路径时要累加各条贡献。对于向量运算,框架计算的是相应的向量—雅可比乘积,不必显式展开巨大矩阵。
跟着数字走一遍
最简单的网络:输入 x=2,一个权重 w=1.5,网络: z = w·x,a = z²,L = (a−6)²。目标输出 y=6。
前向保存中间量,反向复用它们计算梯度。成本与前向通常是同一量级,不是严格固定为两倍;具体取决于算子和实现。
把同样的链式法则用到我们那台猜水果的机器上(神经元 + Sigmoid + 交叉熵),会冒出一个特别漂亮的结果。 下面这台演示就把梯度从损失一路传回 和 ——改颜色或真实答案,看每个梯度实时重算:
完整案例:一步不省,教网络认出西瓜
上面那台单神经元太简单,梯度只穿过一层就到了权重。真实网络真正的难点,是梯度要穿过隐藏层、一层层往回传。 下面这个完整案例就把这件事彻底摊开:一个最小的「真」网络——2 个输入 → 1 个隐藏神经元(Sigmoid)→ 2 个输出(Softmax), 任务是判断一个水果是不是西瓜(颜色深、个头大就更像)。从前向、Softmax、损失,到反向传播每一步的链式法则、再到权重更新与训练收敛,所有数字一个不省、全程可交互。
建议照标签页顺序走一遍:① 看清网络结构 → ② 前向算出预测(拖动权重滑块感受变化)→③ Softmax 把得分变概率、交叉熵量出损失 → ④ 反向传播,A→E 五步把梯度从输出一路传回每个权重 →⑤ 按梯度更新一步、看损失是降是升 → ⑥ 连点训练,看损失曲线一路滑到底、网络真的学会认西瓜。
x₂ 尺寸大小(0=极小, 1=极大),本例 x₂ = 0.8
w₁, w₂ 输入→隐藏层权重
z 隐藏层线性值:z = w₁·x₁ + w₂·x₂
h 隐藏层输出:h = sigmoid(z) ∈ (0,1)
v₁, v₂ 隐藏→输出层权重
o₁, o₂ 输出层线性值:o₁ = v₁·h,o₂ = v₂·h
ŷ₁, ŷ₂ Softmax 后的概率(ŷ₁=西瓜, ŷ₂=不是)
L 交叉熵损失 y = 0(真实类别:西瓜)
特别盯住第 ④ 页那条反向的链子:(预测 − 真实)→ 乘 、两路相加得 → 乘 Sigmoid 的导数 得 → 再乘输入 得 。 每一环都只是「上一环传来的梯度 × 本环的局部导数」,一路相乘传回去——这就是反向传播的全部秘密。 唯一要小心的是:隐藏层 同时连着两个输出,它的梯度得把两条路相加。
完整案例里的更新,是下一课的预告
保留上面的六个页签,是为了把局部求导放回完整流程。第五、六页先用简单更新观察训练,本课重点仍是第四页的链式法则。学习率、batch 和优化器的选择,留给第 17 课。反向传播产生梯度,并不会单独替你选择参数更新策略。
梯度消失——链式法则的副作用
反向传播的梯度是一串相乘: ∂L/∂w₁ = ∂L/∂aₙ × ∂aₙ/∂aₙ₋₁ × … × ∂a₂/∂a₁ × ∂a₁/∂w₁
如果每一层的「本地导数」都小于 1(比如 Sigmoid 的最大导数是 0.25), 经过 100 层相乘:0.25¹⁰⁰ ≈ 10⁻⁶⁰——梯度消失为零。 靠近输入的层接收到几乎为零的梯度信号,完全学不到任何东西。
ReLU 正区间导数为 1,但权重矩阵仍影响梯度尺度。初始化、残差连接与归一化可以帮助深层训练;范数裁剪限制爆炸梯度,不恢复消失的梯度。第 18 课观察训练稳定性,第 30 课详细解释残差与层归一化。
好消息:你几乎永远不需要手写反向传播。 PyTorch、TensorFlow 等框架内置自动微分(autograd): 用框架的运算构建网络,调用 loss.backward(), 所有参数的 .grad 属性就自动填好了。 反向传播对用户完全透明。
梯度算好了,下一步才是更新参数
到这里,预测、输出概率、损失与梯度已经接上。下一课用优化器更新参数,随后两课检查训练稳定性与泛化;卷二还没有结束。
- 神经元:z = w·x + b,σ(z) 输出(第 11 课)
- 激活函数引入非线性;ReLU 缓解一类饱和问题,但不保证梯度尺度稳定。
- 损失函数:MSE 用于回归,交叉熵用于分类(第 15 课)
- Softmax:把分数变成概率,temperature 参数的来源(第 14 课)
- Mini-batch / Adam:高效更新参数(第 17 课)
- 反向传播:一次反向扫描算出所有梯度(第 16 课)
反向传播在计算图上应用链式法则,复用前向中间量计算所有梯度。反向与前向通常具有相近量级的计算成本,而不是固定的两倍定律。它负责算梯度,参数更新由优化器完成。
💡 用大白话梳理:这一课的核心直觉
- 数值微分的问题:n 个参数需要 n 次额外前向传播,代价无法承受。
- 链式法则:dL/dx = dL/dg × dg/dx,梯度可以从外向内逐层传递。
- 反向传播:一次前向(保存中间值)+ 一次反向(传递梯度),搞定所有参数。
- 梯度消失:小数连乘趋向零;ReLU + 残差连接是主要解法。
- 自动微分:PyTorch autograd 帮你做了全部,只需 loss.backward()。
学习小测验
动动脑筋:核心直觉小测验(选出你的答案后点击「提交」,即可查看生动通俗的详细解析)
17 梯度下降与优化器
用已经算出的梯度更新参数:学习率、Mini-batch、动量、Adam 与 AdamW。