6.10 反向传播:怎么让模型变好
前向传播算出预测,损失函数给出分数——接下来,怎么让分数变小?答案就是反向传播(Backpropagation),它是让神经网络”学会”的核心算法。
6.10.1 核心思想:责任追究
反向传播的本质是一个责任追究过程。
前向传播结束后,你得到了一个损失值——这个数字告诉你”模型整体有多差”。但问题是:这个”差”该怪谁?是第一层的权重?第三层的偏置?还是激活函数的选择?
反向传播的回答是:把损失的责任,沿着网络从后往前,逐一分配给每个参数。具体做法是计算”损失对这个参数的梯度”——梯度越大,说明调这个参数对降低损失越有效。1
可以类比为一场足球赛输了之后复盘:不是全队一起挨骂,而是逐个分析——前锋射门偏了负 30% 责任,后卫漏人负 40% 责任,门将失误负 30% 责任。反向传播做的是同样的事,只不过它精确到每一个参数。
前向:输入 -> 层1 -> 层2 -> ... -> 输出 -> Loss(计算分数)
反向:Loss -> 梯度 -> 更新层N参数 -> 更新层N-1参数 -> ...(追究责任)
graph LR
A[前向传播<br/>计算预测] --> B[计算损失<br/>预测vs真实]
B --> C[反向传播<br/>计算梯度]
C --> D[更新权重<br/>梯度下降]
D --> A6.10.2 数学本质:链式法则
反向传播不是什么神秘的魔法——它只是链式法则在多层网络上的高效应用。
链式法则是微积分中的一条规则:如果 A 影响 B,B 影响 C,那么 A 对 C 的影响 = (A 对 B 的影响) x (B 对 C 的影响)。就像多米诺骨牌——推倒第一块的力度,经过链条中的每一块传递,最终决定了最后一块倒下的速度。
在神经网络中,损失 L 是最后一层输出的函数,最后一层输出是倒数第二层输出的函数…依此类推。要算”损失对第一层权重的梯度”,就需要沿着这个链条一层层往回乘:
dL/dW1 = dL/d输出 × d输出/d第N层 × ... × d第2层/d第1层 × d第1层/dW1
反向传播的聪明之处在于:它从后往前计算,每算完一层就缓存结果,让深层网络的梯度计算变得可行。如果用”从前往后”的暴力方式,复杂度会爆炸。这种从后往前的顺序,正如它的名字——反向传播。
做一次前向 + 一次反向 = 一个训练步(step)。几十亿步之后,模型就学会了。
6.10.3 反向传播的三步操作
对每一层(从输出层往回走):
- 计算损失对该层输出的梯度:这一层的输出变化 1,损失会变化多少?
- 穿过激活函数:把梯度乘以激活函数的导数——例如 ReLU 的导数:正数区域导数为 1,负数区域导数为 0
- 计算损失对该层权重和偏置的梯度:这个梯度就是参数更新的方向和幅度
最后一步:用梯度更新参数。更新公式是 新参数 = 旧参数 - 学习率 × 梯度。梯度指向损失增长最快的方向,减去它(往反方向走)就是损失下降最快的方向。这就是梯度下降 (Gradient Descent)的核心。2
6.10.4 深度带来的挑战:梯度消失与梯度爆炸
反向传播在深层网络中面临两个经典问题:
梯度消失:链式法则中,如果每一层的梯度都小于 1(例如 Sigmoid 的导数最大才 0.25),那么 100 层乘下来,第一层的梯度就接近于零——最底层的参数几乎不更新。这就像一个传话游戏:消息经过 100 个人传递后,到最后一个人听到的已经完全失真了。
梯度爆炸:反之,如果梯度大于 1,100 层乘下来梯度变成天文数字,参数一步跨出十万八千里,训练直接崩溃。
解决方案:
- ReLU 与激活函数 (Activation Functions):正数区域导数恒为 1,不衰减,从根本上缓解梯度消失
- 6.7 权重初始化:He 初始化和 Xavier 初始化让初始梯度保持在合理范围
- 6.6 归一化层:BatchNorm 与 LayerNorm:在每一层后重新标准化数据分布,让梯度流动更稳定
- 残差连接(ResNet 的核心创新):给梯度开辟一条”高速公路”,让它能跳过中间层直接传到底层
概念文件夹中的梯度消失与梯度爆炸 (Vanishing/Exploding Gradient)、反向传播 (Backpropagation)和梯度下降 (Gradient Descent)有更完整的数学推导和代码演示。
← 上一节:6.9 损失函数:衡量模型多差 | 下一节:6.11 学习率调度的艺术 →