为什么梯度下降在峡谷里要走两百多步?
本课一问:拿到梯度之后,沿着它走一步——这么简单的规则,为什么在一个「峡谷」形的 loss 面上要走两百多步?
这一课先不碰:让每个参数用不同的步长(第 2 课);让学习率随步数变化(第 4、5 课);batch 该取多大(岔路课)。
从已有出发
「小明把苹果给了小王」走完前五章搭好的网络,每个位置都输出一个下一 token 的概率分布。参数刚随机初始化时,模型对 248,320 个 token 几乎一视同仁,每个位置的 loss ≈ ln 248,320 = 12.42(C0 第 5 课)。反向传播再给 Qwen3.8-27B 的 27,781,427,952 个参数各算出一个梯度:往哪个方向改一点点,loss 降得最快。
前向的每一环都学过了。这一章看的是下面这个循环里「优化器」那一格——拿到梯度之后,参数到底怎么动:
这一章为什么换例子。「参数怎么动」在例句上看不见:27,781,427,952 维的 loss 面画不出来,也没法手算。所以本章换成两个替身,结论再回到大模型的真实配置上:① 一个画得出、能手算的二维 loss 面——下面的「峡谷」;② 一个能在浏览器里真训练的小模型(第 2 课起),所有 loss 曲线都是它现场训练出来的。
先自己设计:沿梯度走,每步看全部数据
最直接的规则就是梯度下降:θ ← θ − η·∇L(θ)。η 是学习率,决定这一步走多远。
朴素方案 ①:每一步都用全部训练数据算梯度。梯度最准,可代价是一步就要把全部数据前向、反向各算一遍。DeepSeek-V3 预训练用了 14.8T token:算一次全量梯度 = 把整个训练预算花完,只能走 1 步。
改进是小批量随机梯度下降(SGD):每步随机取一小批数据,用它的平均梯度代替全量梯度。随机一批的梯度是全量梯度的无偏估计 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条每个样本等概率被抽到时,小批量梯度的期望等于全量梯度;收敛性在凸或光滑等假设下可证 出处Robbins & Monro 1951 ↗需联网 ——方向平均来看是对的,只是每一步带点噪声。DeepSeek-V3 的满 batch 是 15,360 条 × 4,096 token = 62,914,560 token,同样 14.8T token 的数据就能走约 235,240 步(按满 batch 算;它前 469B token 内 batch 是渐增的,真实步数更多)。噪声有什么代价、batch 该多大,放到岔路课。
朴素方案 ②:全体参数共用一个 η,就这么一直走下去。先在一维上看清 η 能取多大。下面是峡谷的两个方向各自的一条抛物线,f = ½λe²,两个方向共用同一个 η:
一维上每一步是 e ← (1 − ηλ)·e,所以只看 ηλ 这一个数:在 0 到 1 之间单调靠近谷底;1 到 2 之间越过谷底、来回振荡但收敛;超过 2 就越跳越远 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条e_t = (1 − ηλ)^t·e_0,收敛当且仅当 |1 − ηλ| < 1,即 0 < ηλ < 2 出处待补 。两个方向共用一个 η 时,上限由最陡的方向决定:λ = 100 要求 η 小于 0.02,而 λ = 1 的缓方向在这个 η 下每步只能缩到 0.98 倍左右。
放回二维,两个方向合在一起就是一条狭长的峡谷:f = ½(x² + 100y²),起点 (−9, 1.5)。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
试三件事:① 在「朴素方案」里把 GD 的 η 拖到 0.021,看轨迹飞出峡谷、表格里「到 1% 以内」变成「进不去」;再拖回 0.019,右边分解图里实线(缓方向)几乎是一条缓坡,虚线(陡方向)一上一下地收敛——慢和抖同时出现。② 点「看它在哪失败」再点「换成改进方案」,只打开「动量」一条:同样 η = 0.019,步数从 241 降到 87。③ hover 动量轨迹上开头的几个点,读「动量缓冲 v」:x 分量一步步变大(同一方向在累积),y 分量正负交替(来回的方向在抵消)。
为什么会这样:两个方向的曲率差 100 倍
峡谷的两个方向曲率分别是 λ = 1 和 λ = 100,比值 κ = 100 叫条件数。梯度下降要稳,η < 2/λmax;于是缓方向每步最多缩到 1 − 2/κ 倍,要走到 1% 需要的步数和 κ 成正比。学习率不是「选大一点就快」——它被最陡的方向卡住了,而最慢的方向决定总步数。
这不是二维玩具才有的事。任何光滑的 loss 在一个点附近都可以用二次函数近似(二阶泰勒展开),不同方向的曲率一般不同 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条局部二次近似是分析优化器的标准工具;真实网络的曲率分布随位置和训练阶段变化,本课不给具体数字 出处待补 。真实大模型的曲率谱没法在页面上画出来;下一课改用一个能直接测的量——同一批数据里,各个参数的梯度差多少。
改进:动量
动量(重球法,Polyak 1964)不直接用这一步的梯度,而是维护一个「速度」v:把过去的梯度按 β 衰减着累加起来,再沿 v 走。
同一个峡谷上,不同的 (η, β) 各要多少步?下面这张热力图的每一格,都是一组 (η, β) 的收敛速度——不是跑出来的,而是把重球法的 2×2 迭代矩阵在两个方向上的特征值现算出来。点任意一格,右边就画出那组参数的真实轨迹。
试三件事:① 点最下面一行(β = 0,就是 GD)里颜色最深的位置,读「真实轨迹到 1% 以内」:两百多步。② 点白圈标出的最优点(β∗ ≈ 0.669、η∗ ≈ 0.0331):真实轨迹 45 步,渐近估计 22.9 步——渐近估计忽略了开头的过渡段。③ 沿红色虚线从左下往右上看:β 越大,能用的 η 越大;但 β 贴近 0.99 时颜色又变浅——动量太大会过冲,在谷底来回荡很久。
🔍 最优的 β 为什么是 ((√κ − 1)/(√κ + 1))²?
在二次函数上,重球法每个方向的误差满足一个两步递推,收敛因子是特征方程 z² − (1 + β − ηλ)z + β = 0 两根的最大模。当两根是一对共轭复数时,它们的模恰好是 √β,与 λ 无关;让两个极端方向(λmin、λmax)都刚好落在这个区间里,就得到 β∗ = ((√κ − 1)/(√κ + 1))²、η∗ = (2/(√λmin + √λmax))²,收敛因子 (√κ − 1)/(√κ + 1)。κ = 100 时是 9/11 ≈ 0.818,而最好的 GD 是 99/101 ≈ 0.980:步数从正比于 κ 降到正比于 √κ。这是动量在二次函数上可证明的加速;真实网络不是二次函数,所以 β 最后还是靠实验选(常用 0.9)。
纠正旧课的一句话
旧版 M3 的地形实验写过:「把 η 拖过 0.125,SGD 和动量当场发散」。那个地形是 f = 0.5x² + 8y²(条件数 16)。GD 的上限确实是 2/16 = 0.125,但重球动量(β = 0.9)的上限是 2 × 1.9 / 16 = 0.2375——η = 0.13、0.14 时动量照样收敛,只有 GD 发散。
试两件事:① 把 GD 和动量的 η 都拖到 0.130:GD 的表格一行显示「进不去」、第 400 步 f 变成天文数字,动量那一行照样收敛。② 再把动量的 η 慢慢拖过 0.2375,看它什么时候才开始发散。
⚠ 常见误解
「学习率越大,收敛越快。」只在 ηλ < 1 的范围里对。越过 1 开始振荡,越过 2 直接发散;而且判断用的是最陡的方向。一维抛物线上 η 从 0.019 调到 0.021 只多了约 10%,陡方向就从收敛变成每步放大 1.1 倍。
「动量只是让它走得更快。」动量同时改变了稳定性:上限从 2/λ 放宽到 2(1 + β)/λ,所以旧课「动量和 SGD 一起发散」的说法不成立;它也会过冲——β 太大时轨迹冲过谷底再折返,反而更慢(热力图右上角)。
在演进地图上的位置
- 全量梯度下降
- 小批量随机梯度下降 SGD
- 动量(重球法)
- Adam:每个参数一把尺子
- AdamW:解耦权重衰减
- 学习率 warmup
- 学习率衰减:cosine → WSD
- batch 大小:渐增,还是一开始就大
- 全局梯度范数裁剪
- Muon:按矩阵的奇异方向更新
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 小批量:全量梯度算不起;动量:单一 η 被最陡方向卡住,缓方向爬得慢、陡方向来回锯齿 |
| ② 数学上为什么可能有效? | 小批量梯度是全量梯度的无偏估计 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条随机逼近;收敛需要凸或光滑等假设 出处Robbins & Monro 1951 ↗需联网 ;二次函数上 GD 的稳定域和重球法的加速都能直接推出来,步数从正比于 κ 降到正比于 √κ 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条只对二次函数(或其局部近似)严格成立 出处Polyak 1964;Distill 的推导 ↗需联网 |
| ③ 实验上为什么最后选了它? | 现代优化器都保留了动量:GPT-3、DeepSeek-V3 的 Adam 取 β₁ = 0.9,DeepSeek-V4 的 Muon 取动量 0.95 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条这是「大家都在用」的证据,不是「动量最优」的证明 出处DeepSeek-V4 报告 §4.2.2;GPT-3 附录 B ↗ |
一句话
学习率被最陡的方向卡住;动量让一致的方向越走越快、来回的方向互相抵消。
先停在这里:记住「上限看最陡的方向、步数看最缓的方向」,进下一课。
再深一层:展开上面「最优 β」的 Dig,再去读 Distill 的全文。
下一个缺口
峡谷里只有两个方向,动量一个 β、一个 η 就够了。可真实模型有几百亿个参数,它们的梯度大小能差多少?一个 η 管得过来吗? → 第 2 课:一个学习率管得了所有参数吗?
你可能会问
这一课还没有收到真实提问;你的提问会记到 05-问答记录/C5-L1.md。下面是最常被问到的几个:
- 「batch 越大梯度越准,那是不是越大越好?」不是。梯度准到一定程度以后,再加大 batch 只是在重复同一个方向,浪费数据——见岔路课:batch 能无限加大吗?
🔍 Nesterov 动量是什么?
Nesterov 版本先按旧速度「往前看一步」,在那个位置算梯度再更新;常见写法等价于把这一步的更新改成 g 与 v 的一个组合。我们项目的 SGD 默认开着 nesterov(04-实践项目 minillm/optim.py),Muon 也默认用 Nesterov 形式——Keller Jordan 的博客写的理由是「在我们测过的每个设置里都略好一点」,这是实验结论,不是证明。
🔍 大模型的 loss 面真的长成峡谷吗?
没人能把几百亿维的 loss 面画出来。常见的「3D 地形图」都是沿两个随机方向切出来的二维截面(Li et al. 2017),形状取决于怎么选方向,不能当成真实地形。本课的峡谷只是局部二次近似下的一个最小例子:它说明「不同方向曲率不同」会让单一学习率失效。这件事在大模型里怎么表现,下一课用真实训练中的梯度尺度来看。