深度学习常用优化器有哪些?SGD、Momentum、Adam 有什么区别?
简化版
优化器决定「拿到梯度后怎么更新参数」。演进主线:SGD(随机梯度下降)——最基础,沿负梯度走一小步,简单但收敛慢、易在沟壑里震荡、对学习率敏感;Momentum(动量)——给更新加「惯性」,累积历史梯度方向,加速收敛、减少震荡(像小球滚下坡越滚越快);AdaGrad/RMSProp(自适应学习率)——给每个参数按其历史梯度大小自动调学习率(梯度大的参数步子小、梯度小的步子大);Adam——同时结合 Momentum(一阶动量)和 RMSProp(二阶自适应学习率),还带偏差校正,通常较快且易作为基线,但仍需调基础学习率、权重衰减和调度。精调追求最佳泛化时有人用 SGD+Momentum。
详细版
优化器演进:
| 优化器 | 核心思想 | 特点 |
|---|---|---|
| SGD | w ← w - η·g | 简单、慢、震荡、对 η 敏感 |
| Momentum | 累积历史梯度(一阶动量) | 加速、抗震荡、冲出局部沟壑 |
| AdaGrad | 按累积梯度平方缩放学习率 | 自适应,但学习率单调衰减到过小 |
| RMSProp | 用指数移动平均替代累积(修正 AdaGrad) | 避免 AdaGrad 分母永久累积;有效步长仍取决于近期梯度与 ε |
| Adam | Momentum + RMSProp + 偏差校正 | 常用基线,仍需调参 |
Adam 更新(核心):
m = β₁·m + (1-β₁)·g (一阶动量:梯度的移动平均 = Momentum)
v = β₂·v + (1-β₂)·g² (二阶动量:梯度平方的移动平均 = RMSProp)
m̂, v̂ = 偏差校正(m, v) (修正初期偏向 0)
w ← w - η · m̂ / (√v̂ + ε) (方向用 m̂、步长按 v̂ 自适应)
两条改进主线: ① 动量(利用历史方向加速);② 自适应学习率(每参数各自调步长)。Adam 把两条合一。
完整版教学
一、优化器解决什么:怎么用梯度更新参数
反向传播算出了梯度,但「梯度告诉你往哪个方向走」不等于「怎么走最好」。优化器就是决定更新策略的——走多大步、要不要利用历史信息、每个参数是否用不同步长。好的优化器能让训练更快收敛、更稳、更少陷入困境。从 SGD 到 Adam,是一条不断改进「怎么走」的演进线,抓住两条主线就能理清:① 加动量(利用历史梯度方向)② 自适应学习率(每个参数各调步长)。
二、SGD:最基础的一步一步走
随机梯度下降(SGD) 是最基本的优化器:
w ← w - η · g (η 是学习率,g 是当前梯度)
每次沿当前负梯度方向走一小步。实际用小批量(mini-batch) 算梯度——比全量快、比单样本稳。
问题:
- 收敛慢,尤其在损失面「又扁又长的沟壑」里会来回震荡(垂直于沟壑方向反复横跳,沿沟壑方向前进很慢)。
- 对学习率极敏感:太大发散、太小极慢。
- 容易卡在平坦区、鞍点。
三、Momentum:给更新加「惯性」
Momentum(动量) 借鉴物理里小球滚下坡的惯性:不只看当前梯度,还累积过去的梯度方向:
v ← β·v + g (速度 = 历史动量 + 当前梯度,β 常取 0.9)
w ← w - η·v
直觉:小球滚下坡时,一直往下的方向会越滚越快(累积加速),而来回摆动的方向会相互抵消(震荡被抑制)。
好处:
- 加速收敛:一致的下降方向被不断累积、越走越快。
- 减少震荡:沟壑里左右横跳的分量相互抵消,走得更直。
- 在一致方向上保留速度,可能穿过小范围平坦区,也可能造成过冲:靠惯性冲出平坦区和小坑。
这是第一条改进主线:利用历史梯度方向(一阶动量)。
四、AdaGrad / RMSProp:每个参数自适应学习率
另一条思路:不同参数应该用不同的学习率。频繁更新、梯度大的参数该走小步(别冲过头),稀疏、梯度小的参数该走大步(多学一点)。
- AdaGrad:累积每个参数历史梯度的平方和,用它的平方根去除学习率——梯度一直大的参数学习率被压小,梯度小的保持大。问题:平方和只增不减,学习率单调衰减到过小,后期几乎不动。
- RMSProp:修正 AdaGrad——用指数移动平均代替累积和(只看近期梯度),分母不会像 AdaGrad 那样因历史平方梯度永久累积而单调增大,但有效步长仍可能很小,适合非平稳目标和深层网络。
这是第二条改进主线:自适应学习率(按每个参数的梯度历史调步长,这里的“二阶矩”是梯度平方的指数平均,不是 Hessian 或二阶优化)。
五、Adam:两条主线合一,成为默认
Adam(Adaptive Moment Estimation) 把上面两条主线结合起来——既用 Momentum 的动量方向,又用 RMSProp 的自适应学习率:
m ← β₁·m + (1-β₁)·g ① 一阶动量:梯度的移动平均(= Momentum,决定方向)
v ← β₂·v + (1-β₂)·g² ② 二阶动量:梯度平方的移动平均(= RMSProp,决定步长)
m̂ = m/(1-β₁ᵗ), v̂ = v/(1-β₂ᵗ) ③ 偏差校正(修正初期 m、v 偏向 0)
w ← w - η · m̂ / (√v̂ + ε) ④ 更新:方向用 m̂、步长按 √v̂ 自适应缩放
- m(一阶矩) 提供动量、加速、抗震荡。
- v(二阶矩) 提供每参数自适应学习率。
- 偏差校正 修正训练初期 m、v 从 0 起步的低估。
优点:常能较快得到可用结果并适应稀疏尺度,但基础学习率、ε、β 和正则仍会显著影响训练——是深度学习中常用的基线优化器之一(β₁=0.9、β₂=0.999、η=0.001 是常用默认)。
六、Adam vs SGD:泛化之争
虽然 Adam 又快又省心,但实践中发现:在某些任务(尤其 CV 分类)上,精调过的 SGD + Momentum 泛化往往更好(Adam 有时收敛到泛化稍差的解)。所以:
- 需要快速建立基线、NLP/Transformer → Adam 或更常见的 AdamW(解耦权重衰减)。
- 追求最佳泛化、愿意调学习率和调度 → SGD + Momentum + 学习率调度。
- AdamW 修正了 Adam 里权重衰减的实现,是现在 Transformer 训练的标配。
七、算一次 Adam 更新,理解偏差校正与 AdamW
设第一步梯度 g=2,β₁=0.9,β₂=0.999,初始 m=v=0。则 m₁=0.2、v₁=0.004;偏差校正后 m̂₁=2、v̂₁=4,忽略 ε 时更新量约为 η×2/2=η。没有偏差校正,第一步会因 m、v 从零起步而尺度失真。
m1 = 0.9*0 + 0.1*2 = 0.2 -> m_hat=0.2/(1-0.9)=2
v1 = 0.999*0 + 0.001*4 = .004 -> v_hat=.004/(1-.999)=4
Δw = -η * 2/(sqrt(4)+ε) ≈ -η
| 方法 | 历史方向 | 每参数缩放 | 权重衰减建议 |
|---|---|---|---|
| SGD | 否 | 否 | 可配 L2 |
| Momentum | 是 | 否 | 可配 L2 |
| Adam | 是 | 是 | L2 与自适应缩放耦合 |
| AdamW | 是 | 是 | 解耦 weight decay |
记忆钩子:Adam 的 v 是梯度平方的移动平均,不是损失曲率;AdamW 的 W 强调解耦权重衰减。
八、常见误区与追问
- 误区:Adam 使用了真正的二阶导数。 它使用梯度平方的一阶统计,不计算 Hessian。
- 误区:Adam 默认参数在所有任务上都无需调整。 基础学习率和权重衰减常是决定性超参数。
- 追问:为什么 Adam 要偏差校正? 零初始化使早期移动平均偏向零,除以
1-β^t可校正期望。 - 追问:AdamW 与 Adam 加 L2 为什么不完全等价? 自适应预条件会改变 L2 梯度,AdamW 则把参数衰减从梯度更新中解耦。
- 追问:如何公平比较 SGD 与 AdamW? 统一数据、训练预算和评估协议,并分别调各自学习率与调度,不能只用同一 η。
九、加强记忆
优化器决定「拿到梯度怎么更新」,两条改进主线:① 动量(利用历史梯度方向,加速+抗震荡)② 自适应学习率(每参数按梯度历史调步长)。演进:SGD(w←w-ηg,简单但慢、沟壑震荡、对 η 敏感)→ Momentum(累积历史梯度=一阶动量,像滚下坡加速抗震荡、冲出局部沟壑)→ AdaGrad/RMSProp(按梯度平方缩放学习率,RMSProp 用移动平均修正 AdaGrad 学习率衰减到 0 的毛病)→ Adam(一阶动量 m(Momentum)+ 二阶动量 v(RMSProp)+ 偏差校正,w←w-η·m̂/√v̂,常用基线,仍需调参)。取舍:NLP 常从 AdamW 起步;视觉任务可分别调优 AdamW 与 SGD+Momentum 后比较。