为什么损失函数可以下降
从 Bit 到 AGI · 第二章:数学(Math) · 为什么损失函数可以下降
链式法则能算梯度,但凭什么反复做 ,loss 就会降?本篇从泰勒一阶近似和凸优化直觉出发,说明下降成立的数学条件;同时诚实讨论非凸深度学习里为何「通常也能 work」,并给出学习率、batch size 的量化建议——调参时心里有数,不靠玄学。
直觉:沿最陡下坡走一小步
loss 曲面 在 70 亿维空间里极其复杂,但在当前点附近,一阶近似成立:
只要 且梯度非零,右边第二项为负——loss 近似下降。步长 太大则近似失效,可能 overshoot 甚至发散。
定义
梯度下降(Gradient Descent):
下降保证(充分小 ):若 在 可微且 ,存在 使 。
L-smooth 条件(常用理论假设):,则取 可保证单调下降(凸函数下收敛到全局最优)。
随机梯度下降(SGD):用 mini-batch 估计梯度 ,。有噪声但期望方向仍指向下降。
例子
例 1:一维二次函数(凸)
,。更新 。
- :,指数收敛到 0。
- :,振荡不收敛。
- :,发散。
例 2:训练 log
典型预训练曲线(7B 模型,cosine lr):
| 阶段 | loss(cross-entropy) | 说明 |
|---|---|---|
| 0–1B tokens | 3.0 → 2.5 | 快速下降 |
| 1B–100B | 2.5 → 1.8 | 缓慢下降 |
| 过拟合 | 训练 ↓ 验证 ↑ | 需 early stop |
def gd_quadratic(w0: float, eta: float, steps: int) -> list[float]:
w = w0
traj = [w ** 2]
for _ in range(steps):
w = w - eta * (2 * w)
traj.append(w ** 2)
return traj
for eta in [0.1, 0.5, 1.1]:
final = gd_quadratic(1.0, eta, 20)[-1]
print(f"eta={eta:.1f} → final loss={final:.4f}")量化
| 超参 | 典型范围 | 影响 |
|---|---|---|
| 学习率 | – | 太大发散,太小慢 |
| batch size | 256–4096+ | 大 batch 梯度稳、需更大 (linear scaling rule) |
| warmup steps | 1k–10k | 初期防大梯度破坏 |
| cosine decay | 总步数内 | 后期精细收敛 |
| Adam | 0.9, 0.95 | 自适应各维步长 |
每步下降量(近似):。
若 、,则 。
非凸现实:深度网络 loss 曲面有无数局部极小、鞍点。实践发现:宽网络 + SGD 噪声 + 大 batch 预训练,往往能到足够好的 basin;完全全局最优不可达也不必追求。
工程视角:loss 曲线与调度
W&B / TensorBoard 里 loss 曲线从 3.x 缓降到 1.x 是 healthy pretrain。loss spike(突然跳到 NaN)常见原因:lr 过大、bf16 溢出、坏数据 batch、梯度爆炸。recovery:降 lr、clip grad、skip batch、从 checkpoint 重载。
Linear scaling rule:batch 从 增到 ,lr 从 增到 (至上限),保持梯度噪声尺度。大模型用 batch 3M+ tokens/step,lr 可达 量级,配合 warmup。
Plateau 不是失败:后期 loss 每降 0.01 可能要多跑数 B tokens——边际收益递减。评估改用 downstream benchmark(MMLU、HumanEval),不只看 train loss。
凸优化理论:强凸 + L-smooth 时 GD 线性收敛,速率 。深度网络非凸,但宽网络文献有「多数局部极小接近全局」的渐近结果——工程上不必等理论完美再训练。
| 现象 | 可能原因 | 对策 |
|---|---|---|
| loss NaN | 溢出、除零 | fp32 loss scale、clip |
| loss 不降 | lr 太小、冻结层 | 查 lr、requires_grad |
| train↓ val↑ | 过拟合 | dropout、早停、更多数据 |
二阶方法(牛顿法、L-BFGS):用 Hessian 曲率信息,每步更准但 或 存储不可用于 7B。Adam 是实用的一阶自适应折中。
常见误区
- 「loss 必须每步都降」:SGD 有噪声,允许小幅反弹;看 moving average。
- 「收敛 = loss = 0」:分类 cross-entropy 理论下界 > 0(标签噪声、模型容量限制)。
- 学习率越大越好:warmup 后过大 lr 导致 loss spike,甚至 NaN(bf16 下尤其常见)。
动手试一试
import math
def cosine_lr(base: float, step: int, total: int, warmup: int) -> float:
if step < warmup:
return base * step / warmup
progress = (step - warmup) / (total - warmup)
return base * 0.5 * (1 + math.cos(math.pi * progress))
for step in [0, 500, 2000, 10000, 50000]:
print(f"step={step:5d} lr={cosine_lr(3e-4, step, 50000, 2000):.2e}")深入一层:非凸与宽网络
Barzilai-Borwein 步长:,无超参自适应——研究用,LLM 仍 cosine + warmup。
Sharp vs flat minima:小 batch 噪声倾向 flat minima(泛化好);大 batch 倾向 sharp(需 lr warmup、label smoothing 补救)。loss 曲面几何是 active research。
Continue pretrain vs finetune:finetune lr 通常小 10×,因已在 good basin 内,只需小步调整;从头 pretrain 可大 lr + long warmup。
Zero redundancy optimizer(ZeRO):分片 optimizer state,不改变 loss 下降数学,只改谁能装下 7B 的 Adam 状态——工程使下降可执行。
下降不是 guarantee 全局最优;是 empirical contract:足够数据 + 足够算力 + 合理 hyperparam → loss 曲线向下、下游任务向上。数学给局部理由;规模给全局效果。
学习率数量级参考
| 场景 | lr 量级 |
|---|---|
| 7B 预训练(AdamW) | – |
| 全参 SFT | – |
| LoRA | – |
| 头层分类(小数据) | 可试 |
warmup 通常 1%–5% 总步数。cosine 末段 lr → 0,利于收敛 flat 区域。linear scaling:batch ×2 → lr ×2(有上限)。
读者备忘
小步负梯度 ≈ 局部降 loss。 关注 lr、warmup、cosine decay、grad clip。loss spike → 先查 lr 与 overflow,再查数据。train loss 单指标不够,配 validation benchmark。非凸曲面无全局保证,但 billion-scale 预训练反复验证「能降就能用」。
本章内容面向程序员:公式可手推,数字可心算,代码可运行。遇到符号不熟时,先查本篇定义表,再查总结篇速查表,不必一次背熟全部细节。
复习建议:先通读直觉与定义,再跑代码块验证数字,最后看读者备忘与小结。与第一章的 float 数组、SIMD、GPU 并行对照阅读,印象更深。后续章节会在 Transformer、训练、推理中反复调用本章符号,值得在笔记里自建一张 shape/FLOPs 速查表。
动手练习:把本篇公式抄进 Jupyter,换三组数字复算;与 PyTorch 张量运算对照 shape 与数值。本章目标是建立可计算的数学直觉,而非完成证明。每篇至少两个数值例子,建议你都亲自算一遍或跑一遍代码。
小结
梯度下降靠泰勒一阶近似:小步沿负梯度方向,loss 局部下降。凸函数有收敛保证;深度网络非凸但实践有效。学习率、batch、schedule 决定能否稳定下降。下一篇转向概率论——分类、采样、loss 的语言基础。
→ 下一篇:概率是什么