反向传播是神经网络训练时用来「算出每个参数该怎么调」的核心算法。它把网络最终的预测误差,从输出层一层层往回传,告诉路上每一个参数:你对这个误差该负多少责任、下次该往哪个方向调。
流水线返工:一个贯穿全文的类比
想象一条流水线:原料先过加工站 A,半成品再到 B,再到 C,最后出成品。质检员发现成品不达标(误差),这份「不达标」的信息会从最后一站往回传——
- 先告诉 C 站「你的输出偏了多少」,C 据此知道自己该怎么调;
- 同时 C 算出「那 B 交给我的料子也有问题」,把这条消息往回递给 B;
- B 再照样追溯给 A……
每个站收到的「调整指令」,就是梯度(gradient,一个表示「该往哪个方向调、调多少」的数)。神经网络就是这条流水线,反向传播就是「误差从后往前、逐站分摊责任」的过程。
它在 AI 体系中的位置
反向传播属于深度学习训练的「中枢」环节。一次完整的训练由四步循环组成,反向传播负责其中关键的第三步:
- 前向传播(forward):数据从前往后走,得出网络的预测。
- 算损失(loss):拿预测值和真实答案比对,得出误差有多大——这正是损失函数干的事。
- 反向传播(backward):误差从后往前传,算出每个参数的梯度。
- 更新参数:用梯度下降,按梯度方向把每个参数调一点,让下一次更准。
四步不断循环,网络就一点点「学」会了任务。可以说,没有反向传播高效地算出梯度,训练多层网络几乎寸步难行。
核心数学:链式法则
反向传播的数学基础就是微积分里的链式法则(chain rule)。神经网络的本质是一个层层嵌套的复合函数:输入经过第一层得到中间结果,再喂进第二层,再喂进第三层……最后算出损失。链式法则告诉我们怎么对这种「函数套函数」的结构求导。
以最简单的一段为例——输入
符号逐项解读:
—— 偏导数符号,读作"partial", 整个读作" 对 的偏导数",表示 动一点时 跟着变多少,即梯度 —— 损失 对权重 的梯度,也就是「 该往哪调、调多少才能减小误差」。这是反向传播最终想算出来的东西。 —— 误差信号从输出端出发的初始值(损失对网络输出的敏感度)。 —— 激活函数的记号,本文里就是 sigmoid,把 压到 0~1 —— 上标撇号 是求导记号, 表示激活函数 对 的导数 —— 信号经过激活函数这一关时,被放大或缩小了多少。 —— 权重 对中间值 的影响(在这个例子里它就等于输入 )。
通俗理解:每个参数的「责任」= 输出端的误差 × 信号往回传时每一关的「传导系数」连乘。回到流水线类比——C 站的调整力度,等于「最终成品的偏差」乘上「B 到 C 之间信号衰减」再乘上「A 到 B 之间信号衰减」。这正是「反向传播」名字的由来:信号是反向流动的。
图 1:权重的梯度 = 输出端误差 × 激活函数传导 × 权重影响,三个因子从右往左连乘。
算一个小例子
设
(式中的
现在用链式法则往回算
| 步骤 | 计算 | 结果 |
|---|---|---|
| 输出端误差 | ||
| 激活函数传导 | ||
| 权重影响 | ||
| 三者相乘得 |
自检:梯度为负,说明稍微增大
符号解读:
—— 学习率,每次调权重的步伐大小 —— 更新后的新权重
图 2:把小例子的三个数 −0.269、0.197、2 连乘,得到权重梯度 −0.106。
为什么它这么重要
在反向传播被广泛使用之前,训练多层神经网络极其困难——人们不知道怎么高效地算出成千上万个参数各自的梯度。反向传播(本质上是反向模式的自动微分)把这个计算组织成一次从后往前的扫掠,效率极高:网络再深,算梯度也只需走一遍。
正是有了它,深度学习才从「理论可行」变成「实际可训」,今天的大模型才训练得动。
图 3:反向传播只需从输出往输入扫一遍,沿途顺手收集每一层权重的梯度。
完整代码
下面用 PyTorch 写一个能真学会任务的小网络。整体流程是「造大脑 → 备数据 → 反复练习(前向 → 算误差 → 反向 → 更新)→ 考试」——训练循环里每一步的顺序不能乱:先看预测准不准(前向 + 损失),再回头分摊责任(反向传播),最后才动参数(更新)。
import torch
import torch.nn as nn # nn = neural network,PyTorch 搭神经网络用的工具箱
# ===== 任务:教神经网络学会「复习时长 → 考试分数」=====
# 准备 4 组有真实含义的数据(小时数 → 分数),趋势是学得越久分越高
hours = torch.tensor([[1.0], [2.0], [3.0], [4.0]]) # torch.tensor:把数据变成 PyTorch 的多维数组(张量)
scores = torch.tensor([[52.0], [65.0], [78.0], [91.0]]) # 目标分数
# ===== 定义两层小网络:信号要穿过两层,「反向」才有链条可言 =====
class ScoreNet(nn.Module): # nn.Module:所有神经网络模块的基类,继承它 PyTorch 才能帮你管理参数
def __init__(self):
super().__init__()
self.layer1 = nn.Linear(1, 8) # 第一层:1 个输入 → 8 个中间值(nn.Linear = 全连接层)
self.act = nn.ReLU() # 激活函数:把负数压成 0,给网络「非线性」能力
self.layer2 = nn.Linear(8, 1) # 第二层:8 个中间值 → 1 个输出(预测分数)
def forward(self, x): # forward:定义数据「从前往后」怎么走,即前向传播
out = self.layer1(x) # 先过第一层
out = self.act(out) # 再过激活函数
out = self.layer2(out) # 再过第二层,得到预测分数
return out
torch.manual_seed(42) # 固定随机数种子,保证每次运行结果可复现
net = ScoreNet()
loss_fn = nn.MSELoss() # 均方误差:衡量预测分数和真实分数差多少(损失函数)
opt = torch.optim.Adam(net.parameters(), lr=0.1) # Adam 优化器:自适应学习率,比普通梯度下降收敛更快更稳,lr 是学习率(每次调整的步伐大小)
# ===== 训练循环:反复「前向 → 算误差 → 反向传播 → 更新参数」=====
for epoch in range(500): # 把 4 组数据反复看 500 遍
pred = net(hours) # ① 前向传播:输入复习时长,得到预测分数
loss = loss_fn(pred, scores) # ② 算损失:预测分数离真实分数有多远
opt.zero_grad() # ③ 清空上一轮残留的梯度(不清空会累加,方向就算错)
loss.backward() # ④ 反向传播!自动用链式法则,从损失往回算出每个参数的梯度
opt.step() # ⑤ 梯度下降:按梯度把每个参数往「让损失更小」的方向调一点
# ===== 考试:网络学会了吗?预测「复习 5 小时」能考多少分 =====
test_hour = torch.tensor([[5.0]])
print(f"复习 5 小时,网络预测能考:{net(test_hour).item():.1f} 分")
print(f"训练损失:{loss.item():.4f}(越小越准)")运行后会看到网络预测「复习 5 小时」能考约 104 分——它真的从 4 组数据里学到了「每小时约涨 13 分」的趋势(52 → 65 → 78 → 91 → 104,正好接上)。其中 loss.backward() 这一行,就是反向传播在代码里的化身:框架自动用链式法则,把穿过两层的梯度一口气算好,你完全不用手写求导。
小结
前向传播让数据从前往后走出一个预测,反向传播则让误差从后往前传回去,算清每个参数该怎么调。一个是「往前走」,一个是「往回传」,两者一去一回,神经网络才真正「学」起来。
参考资料
- Backpropagation calculus — 3Blue1Brown(深度学习系列第 4 章,最直观的反向传播可视化讲解) https://www.3blue1brown.com/lessons/backpropagation-calculus
- Neural Networks: Backpropagation — CS231n(斯坦福深度学习课程笔记,含计算图与梯度推导) https://cs231n.github.io/optimization-2/
- 反向传播算法 — 维基百科 https://zh.wikipedia.org/zh-cn/反向传播算法