从 SGD 到 Adam:优化器究竟替我们做了什么?
优化器不负责决定模型“学什么”,却决定模型沿着什么节奏、以多大步幅去学。Adam 的关键是同时利用梯度方向的历史和不同参数的尺度差异。
训练神经网络时,我们希望最小化损失函数 L(θ)。最朴素的更新规则是随机梯度下降(SGD):
θ ← θ - ηg
其中 g 是当前 mini-batch 的梯度,η 是学习率。这条公式非常重要,因为绝大多数优化器都可以看作是在“如何处理 g”和“如何设定步幅”上做改造。
SGD 的两个现实困难
第一,mini-batch 梯度带噪声。某一步的方向未必代表总体下降方向,参数容易在狭长的损失谷底左右摇摆。
第二,不同参数的梯度尺度差异很大。有些参数的梯度通常在 1e-1 量级,有些在 1e-5 量级。只用一个全局学习率,往往意味着一部分参数走得太快,另一部分几乎不动。
Momentum:不要只相信当前一步
动量方法维护梯度的指数滑动平均:
mₜ = β₁mₜ₋₁ + (1 - β₁)gₜ
更新时使用 mₜ 而非单次梯度。直觉上,它像给优化过程加了惯性:在长期一致的方向上加速,在正负来回波动的方向上减速。
这解释了为什么 Momentum 往往比裸 SGD 更稳定。但它依然只用一个全局学习率,并没有解决不同参数量级不同的问题。
RMSProp:关注梯度“通常有多大”
RMSProp 维护平方梯度的滑动平均:
vₜ = β₂vₜ₋₁ + (1 - β₂)gₜ²
再用 1 / (√vₜ + ε) 调整每个参数的有效步长。梯度长期较大的参数会自动减小步幅,梯度长期较小的参数可以获得相对更大的步幅。
Adam:把两种记忆放在一起
Adam 同时维护一阶矩 m 和二阶矩 v:
θₜ ← θₜ₋₁ - η · m̂ₜ / (√v̂ₜ + ε)
其中带帽子的量是偏差校正后的估计。训练刚开始时,滑动平均从零初始化,会系统性偏小;偏差校正正是为了避免前几步更新被无意压得过小。
可以这样记忆 Adam:
m回答“过去一段时间,应该往哪个方向走?”v回答“这个方向上的梯度通常有多大?”- 两者结合,形成平滑且按参数自适应的更新。
为什么 Adam 不等于“默认最优”
Adam 常常是强基线,尤其适合深网络和大规模预训练,但它不是不需要思考的默认答案。
1. **学习率仍然最重要。** 自适应并不会消除学习率选择,错误数量级的学习率依然会让训练发散或停滞。
2. **权重衰减要区分实现。** AdamW 将 weight decay 与自适应梯度更新解耦,是现代 Transformer 训练中更常见的选择。
3. **泛化不只由训练 loss 决定。** 有些任务中,SGD 配合动量可能获得不同的泛化表现;不能只根据训练曲线选择优化器。
4. **参数组应该有不同策略。** 新增头部、Embedding、Norm 层或 LoRA 参数,可能需要不同学习率和正则化设置。
大模型训练中的检查清单
当你设置 AdamW 时,至少明确这些问题:
- 学习率是如何 warmup 和衰减的?
β₁、β₂与ε是否匹配所用框架的默认实现?- 哪些参数不做 weight decay,例如 bias 和 Norm 参数?
- 是否需要对 LoRA 参数设置单独学习率?
- 梯度裁剪、混合精度与 loss scaling 是否改变了有效更新?
优化器不是一个孤立超参数,而是训练动态的一部分。只有把它和数据规模、batch size、学习率调度、正则化一起看,才会形成真正可复现的训练方案。
小结
SGD 提供了最基本的下降方向;Momentum 平滑方向;RMSProp 调整尺度;Adam 则把二者结合。理解这条演进路线,之后再看 AdamW、Adafactor 或各种面向大模型的优化器时,就不会只停留在背诵配置上。