第 4 章 · 反向传令:从标量到每个参数 本章要回答的三个问题:loss 是个标量,几万个参数各自的"更新方向"是怎么从这一个数里算出来的?训练为什么这么吃显存和算力,能不能又快又省?一张卡不够用时,反向传令怎么组织成多路并进?这一章回答的是"训练这条流水线的引擎舱"里发生的事。 为什么会有这一章 前半程的一切铺垫——1.2 节的"记账凭证"、3.2 节的前向站点——都是为本章服务的。反向传播听起来高深,直觉却朴素:loss 对每个参数的影响方向和力度(梯度),可以沿着前向的计算路径倒着逐层推算,每层只做局部计算,不用解全局方程。autograd 把这套倒推自动化了:你在前向只管写普通 Python 代码,它在背后记账;你喊一声 backward,它沿账本把梯度分发给每个登记过的参数。
本章要回答的三个问题:loss 是个标量,几万个参数各自的"更新方向"是怎么从这一个数里算出来的?训练为什么这么吃显存和算力,能不能又快又省?一张卡不够用时,反向传令怎么组织成多路并进?这一章回答的是"训练这条流水线的引擎舱"里发生的事。
前半程的一切铺垫——1.2 节的"记账凭证"、3.2 节的前向站点——都是为本章服务的。反向传播听起来高深,直觉却朴素:loss 对每个参数的影响方向和力度(梯度),可以沿着前向的计算路径倒着逐层推算,每层只做局部计算,不用解全局方程。autograd 把这套倒推自动化了:你在前向只管写普通 Python 代码,它在背后记账;你喊一声 backward,它沿账本把梯度分发给每个登记过的参数。
但"自动"不等于"不用懂"。训练里最著名的一批故障——梯度消失、梯度爆炸、loss 不降、显存溢出——全都藏在引擎舱里。不懂传令机制的人只能靠玄学调参;懂的人看一眼梯度范数就知道病在哪一层。本章还顺带讲两个工程加速件:混合精度(把传令时的记号写轻一点)与分布式(把一支队伍拆成多路纵队)——它们是大模型时代绕不开的两件装备。
本章知识点清单:
zero_grad() 存在的理由:梯度是累加的,不清零会发生什么、以及什么场合故意利用累加;torch.no_grad() 与 detach() 正确切断记账:知道各自该用在验证、推理、特征提取哪个场景;| 节 | 回答哪个问题 | 关键产出 |
|---|---|---|
| 4.1 自动求导 | 梯度从哪来、怎么管 | 计算图全景与梯度卫生守则 |
| 4.2 混合精度 | 传令怎么更快更省 | 半精度与损失缩放实务 |
| 4.3 分布式训练 | 一支队伍怎么变多路 | 数据并行的组织方式 |
三节的推进是"先懂机制,再提速度,再扩规模"——顺序不能反,跳过 4.1 直接上 4.3 的人,分布式调试时基本寸步难行。
问:backward 的报错里写着"图已被释放",这是什么事故? 计算图是消耗品——一次 backward 之后默认销毁,省下的显存正是训练能跑起来的原因。二次 backward 或在循环外保存了带图的张量再循环内反传,都会撞上这个报错。处置不是盲目 retain_graph,而是检查你的前向与反向是不是"一对一"的节拍(5.1 节)。
问:梯度爆炸和消失,怎么用一个指标区分? 逐层梯度范数(4.1 节的体检代码)。范数沿层指数级增大是爆炸,指数级衰减是消失。名字里带"病"不重要,重要的是拿到范数表你能指着某一层说"从这里开始不对"——定位到层,才有针对手段。
问:混合精度、分布式这些内容,小模型用得上吗? 机制部分(4.1)人人必须懂;提速部分(4.2)与规模部分(4.3)在小模型上确实用不上,但面试、读别人的大模型工程、以及未来某天你的任务突然变大时,这两节是现成的地图。学的时候可以快,但建议别跳。
本章结束时,每个参数的手里都攥着自己的梯度——"该往哪挪、挪多少"有了答案。但有了方向不等于迈步:学习率定多少、动量怎么加、Adam 凭什么自适应,这些"怎么执行更新"的决策是第 5 章优化器的主场。反向与更新一衔接,训练闭环就完整了:前向算预测,反向算方向,更新迈一步,周而复始。