优化器综述:从 SGD 到 Adam 的演进与选型
训练一个神经网络,本质上是在求解一个高维、非凸、带有大量噪声的优化问题。我们手里的「旋钮」有两个:模型结构与损失函数决定了目标地形,而**优化器(optimizer)**决定了我们如何沿着这个地形下降。选对优化器,往往意味着更快的收敛、更稳的训练,以及在相同算力下拿到更好的最终精度。
本文按时间演进顺序,依次拆解 SGD、Momentum、AdaGrad、RMSprop 与 Adam 的核心思想、更新公式与适用场景,并在最后给出一张对比表和一份可直接照做的实践选型清单。
为什么需要优化器
监督学习的训练,就是最小化经验风险:
theta* = argmin_theta (1/N) * sum_i L(f(x_i; theta), y_i)
其中 theta 是全部可学习参数,L 是损失函数。由于样本量 N 巨大、损失不可解析求导,我们通常采用**随机梯度下降(SGD)**的思路:每步只用一个 mini-batch 估计梯度,再沿负梯度方向小幅更新。
朴素的 SGD 有两个绕不开的痛点:
- 学习率难调。学习率太大,更新在山谷两侧来回震荡甚至发散;太小,则训练缓慢、容易困在平坦区。
- 各参数一视同仁。深层网络中不同层的梯度量级可能相差几个数量级,固定统一的学习率对所有人都不公平。
后续所有优化器,几乎都是在这两个痛点上做文章:Momentum 解决「震荡与慢」,自适应方法(AdaGrad/RMSprop/Adam)解决「各参数不同步」,二者结合则催生了 Adam。
SGD 与学习率
最基础的更新规则是:
g_t = grad_theta J(theta_{t-1}) # 当前 mini-batch 梯度
theta_t = theta_{t-1} - lr * g_t # 沿负梯度走一步
lr(learning rate)是全局学习率。SGD 的优点是简单、内存占用极小、在凸问题上有清晰的理论收敛保证;在图像分类等任务上,配合良好调参的衰减策略,最终泛化精度常常优于自适应方法。
但 SGD 的缺点也同样明显:
- 在「狭长峡谷」地形里会沿壁剧烈震荡,有效前进方向很慢。
- 对学习率极其敏感,且对所有参数使用同一学习率。
- 遇到鞍点(深度学习中极其常见)时,梯度接近零,容易停滞。
实践上我们几乎从不直接用「纯 SGD」,而是给它加上动量、学习率衰减(如 step decay、cosine annealing)等配套手段。
Momentum:利用指数滑动平均累积方向
动量法借鉴物理学中的惯性思想:不仅看当前梯度,还记住之前几次更新的「速度」,从而抑制正交方向上的震荡、加速一致方向上的前进。
标准写法(PyTorch 风格)为:
v_t = beta * v_{t-1} + g_t
theta_t = theta_{t-1} - lr * v_t
其中 beta 常取 0.9,表示历史速度的保留比例。v_t 实际上是梯度的指数滑动平均:距离越久的梯度权重按 beta^k 衰减。
另一种等价表述把学习率提到前面:v_t = beta * v_{t-1} + lr * g_t,再令 theta_t = theta_{t-1} - v_t。两种形式本质一致,区别只在系数摆放位置。
Momentum 带来的直观收益:
- 在峡谷壁上的横向震荡被历史速度「抹平」,纵向前进被加速。
- 能更可靠地越过浅小的局部洼地与鞍点附近的高原。
- 仍是单一全局学习率,未解决不同参数梯度量级不一致的问题。
AdaGrad 与 RMSprop:自适应学习率
AdaGrad
AdaGrad 的核心想法是:对出现频次高、更新频繁的参数使用更小的学习率,对稀疏特征使用更大的学习率。它累积历史所有梯度平方:
G_t = G_{t-1} + g_t ⊙ g_t
theta_t = theta_{t-1} - (lr / (sqrt(G_t) + eps)) ⊙ g_t
符号 ⊙ 表示逐元素相乘。问题也很明显:G_t 单调只增不减,训练越久分母越大,学习率被压到接近零,后期几乎不再更新。这在非凸深度训练里往往过早「熄火」。
RMSprop
RMSprop 由 Geoffrey Hinton 在 Coursera 课程讲义中首次提出,用来修正 AdaGrad 学习率单调递减的问题。它不再累积全部历史,而是对梯度平方做指数滑动平均:
E[g^2]_t = gamma * E[g^2]_{t-1} + (1 - gamma) * g_t^2
theta_t = theta_{t-1} - (lr / sqrt(E[g^2]_t + eps)) * g_t
gamma 通常取 0.9。分母对每个参数自适应缩放:梯度长期偏大的参数,分母被「撑大」,等效学习率自动变小;梯度长期偏小的参数,则获得更大步长。这样每个参数都有了「各扫门前雪」的独立学习率,且不会随时间归零,能稳定处理非平稳目标与稀疏梯度。
Adam:动量加自适应,并做偏差校正
Adam(Adaptive Moment Estimation)可以看成「Momentum 的一阶矩」与「RMSprop 的二阶矩」的结合体,并在此基础上补了一个关键细节——偏差校正(bias correction)。
由于 m 和 v 都初始化为 0,在训练初期它们的指数滑动平均会系统性地偏小(被 (1 - beta) 拉向 0)。Adam 用除以 (1 - beta^t) 来校正这一偏差:
m_t = beta1 * m_{t-1} + (1 - beta1) * g_t
v_t = beta2 * v_{t-1} + (1 - beta2) * (g_t ⊙ g_t)
m_hat = m_t / (1 - beta1^t)
v_hat = v_t / (1 - beta2^t)
theta_t = theta_{t-1} - lr * m_hat / (sqrt(v_hat) + eps)
默认超参为 beta1 = 0.9、beta2 = 0.999、eps = 1e-8、lr = 1e-3。Adam 兼具动量的加速能力与自适应方法的稳健步长,几乎「开箱即用」,对超参不敏感,因此在 Transformer、GAN、强化学习等大量场景中成为默认选择。
需要注意:原生 Adam 的权重衰减是以 L2 正则形式耦合进梯度的,而 L2 与权重衰减在自适应方法里并不等价。这正是 AdamW 的由来。
各优化器对比
下表从几个工程关心的维度横向对比常见优化器:
| 优化器 | 是否需要调学习率 | 超参敏感度 | 收敛速度 | 最终泛化(典型) | 主要记忆占用 |
|---|---|---|---|---|---|
| SGD | 高(最敏感) | 高 | 慢,但可调优 | 常最优(CV) | 极低(仅梯度) |
| SGD + Momentum | 高 | 中 | 较快 | 常最优(CV) | 低(一阶动量) |
| AdaGrad | 中 | 低 | 易早期熄火 | 一般 | 中(累积平方) |
| RMSprop | 中 | 低 | 快且稳 | 良好 | 中(二阶滑动) |
| Adam | 低(开箱可用) | 低 | 快 | 良好,有时弱于 SGD | 中(一阶+二阶) |
| AdamW | 低 | 低 | 快 | 在大规模训练中更优 | 中 |
补充说明:
- 收敛速度指到达可用精度的步数;最终泛化指测试集上的最后精度,二者经常冲突——Adam 快但 SGD 家族常拿到更好终值。
- 自适应方法为每个参数维护滑动统计量,内存约为参数两倍数(一阶、二阶各一份),对超大模型需留意显存。
实践选型建议
没有「永远最好」的优化器,只有「对当前任务最合适」的优化器。一份可照做的清单:
- 计算机视觉(CNN 图像分类、检测、分割):优先
SGD + Momentum(如lr=0.1、momentum=0.9),配合 cosine 或 step 学习率衰减。若想省调参,可先用 AdamW 验证可行性,再回到 SGD 追求精度上限。 - Transformer / 大模型 / NLP / 多模态:优先
AdamW,它是这类架构的事实标准,配合解耦权重衰减与 warmup + 线性(或 cosine)衰减。 - 生成模型(GAN、扩散模型):常用
Adam或AdamW,学习率偏小(如2e-4)。 - 稀疏特征 / 大规模 embedding(如推荐、NLP 词表):自适应方法(Adam/RMSprop)对稀疏梯度更友好。
- 在线学习、非平稳目标:RMSprop 与 Adam 更稳健。
- 显存极度受限:退回到
SGD + Momentum,内存占用最低。
一个常被忽视的原则:优化器与学习率调度、权重衰减策略是一套组合拳。换优化器时,学习率、衰减曲线、warmup 步数往往需要一起重新调。
PyTorch 示例
下面用 torch.optim 演示如何为同一个模型创建文中提到的优化器。AdamW 的 weight_decay 走解耦路径,与普通 Adam 的 L2 行为不同。
import torch
import torch.nn as nn
from torch.optim import SGD, RMSprop, Adam, AdamW
model = nn.Sequential(
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10),
)
# 1) 纯 SGD(不推荐直接使用,这里仅作对照)
opt_sgd = SGD(model.parameters(), lr=0.1)
# 2) SGD + Momentum,CV 任务常用
opt_sgd_m = SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
# 3) RMSprop
opt_rms = RMSprop(model.parameters(), lr=0.01, alpha=0.9, eps=1e-8)
# 4) Adam,beta1/beta2/eps 即文中一阶、二阶矩系数
opt_adam = Adam(model.parameters(), lr=1e-3, betas=(0.9, 0.999), eps=1e-8)
# 5) AdamW,解耦权重衰减,大模型与 Transformer 首选
opt_adamw = AdamW(model.parameters(), lr=1e-3, betas=(0.9, 0.999),
eps=1e-8, weight_decay=0.01)
# 典型训练循环骨架
optimizer = opt_adamw
criterion = nn.CrossEntropyLoss()
for x, y in data_loader:
optimizer.zero_grad()
loss = criterion(model(x), y)
loss.backward()
optimizer.step()
RMSprop 中的 alpha 对应本文公式里的 gamma(衰减率),PyTorch 命名略有差异,含义一致。
小结
- 优化器的演进主线,是不断缓解 SGD 的两个痛点:方向震荡/慢(Momentum)与统一学习率不公平(AdaGrad、RMSprop、Adam)。
- Momentum 用一阶矩累积方向;RMSprop 用二阶矩的指数滑动平均为每参数自适应缩放学习率;Adam 把两者合并,并加入偏差校正以修正初期统计偏小。
- AdamW 进一步把权重衰减与梯度更新解耦,在大规模训练里泛化更稳,是 Transformer 时代的事实标准。
- 选型没有银弹:CV 重调参追求精度上限可选 SGD+Momentum;Transformer 与快速原型首选 AdamW;稀疏特征与在线场景自适应方法更友好。
- 优化器必须和学习率调度、权重衰减、warmup 作为一个整体来设计与调试。
参考与延伸阅读
- Kingma, D. P., & Ba, J. (2015). Adam: A Method for Stochastic Optimization. ICLR 2015. arXiv:1412.6980.
- Loshchilov, I., & Hutter, F. (2019). Decoupled Weight Decay Regularization. ICLR 2019. arXiv:1711.05101.
- Tieleman, T., & Hinton, G. (2012). Lecture 6.5 — rmsprop: Divide the gradient by a running average of its recent magnitude. COURSERA: Neural Networks for Machine Learning, 4(2), 26-31.
- Duchi, J., Hazan, E., & Singer, Y. (2011). Adaptive Subgradient Methods for Online Learning and Online Convex Optimization. Journal of Machine Learning Research, 12, 2121-2159.(AdaGrad 原始论文)
- Sutskever, I., Martens, J., Dahl, G., & Hinton, G. (2013). On the Importance of Initialization and Momentum in Deep Learning. ICML 2013.(动量法深度训练分析)
- PyTorch 官方文档
torch.optim:https://pytorch.org/docs/stable/optim.html