Adam Optimizer
Adam 将动量与按近期梯度大小缩放的逐参数步长相结合。本文介绍更新规则、默认设置、AdamW,以及 Adam 与 SGD 的比较。
Adam 优化器是 Adaptive Moment Estimation(自适应矩估计)的缩写,是一种用于训练神经网络的优化算法,会为每个参数设置自适应步长。该算法由 Kingma 和 Ba 在论文 Adam: A Method for Stochastic Optimization 中提出,它通过过去梯度及其平方的滑动平均扩展了随机梯度下降(SGD)。由于前期进展快且默认设置宽容,Adam 成为深度学习中最常用的起步优化器,而其 AdamW 变体则是训练 Transformer和大型语言模型的标准选择。
Adam 的工作原理#
训练会通过反复沿着与梯度相反的方向更新每个权重,以最小化损失函数。普通 SGD 会用同一个学习率缩放每个梯度。Adam 为每个参数额外保留两个数值,并在每一步根据当前梯度 t 更新它们 g:
- 一阶矩(动量):
m = β1·m + (1 − β1)·g,即梯度的指数衰减平均值,可使更新持续朝一致的方向推进。 - 二阶矩:
v = β2·v + (1 − β2)·g²,即梯度平方的衰减平均值,用于追踪每个参数梯度的典型大小。 - 偏差校正:
m̂ = m / (1 − β1^t)和v̂ = v / (1 − β2^t),用于抵消两个平均值都从零开始的影响。 - 更新:
θ = θ − lr · m̂ / (√v̂ + ε)。
论文中的默认值,PyTorch 的 torch.optim.Adam也采用这些默认值,分别是 lr = 0.001、β1 = 0.9、β2 = 0.999 和 ε = 1e-8。除以 √v̂ 会根据参数的典型梯度大小对每一步进行归一化,因此无论梯度很小还是很大,步长都接近学习率;在 m̂ 内正负梯度相互抵消的嘈杂方向上,步长则会缩小。下面的代码片段比较了 SGD 和 Adam 在两个梯度相差 1,000 倍的参数上的第一步更新:
import torch
# Two parameters whose gradients differ in scale by 1,000x
scale = torch.tensor([1000.0, 1.0])
for name, optimizer_cls in [("SGD", torch.optim.SGD), ("Adam", torch.optim.Adam)]:
w = torch.zeros(2, requires_grad=True)
optimizer = optimizer_cls([w], lr=0.001)
loss = (scale * w).sum() # gradient is [1000, 1]
loss.backward()
optimizer.step()
print(f"{name} first step: {[round(v, 4) for v in w.tolist()]}")SGD 将第一个参数更新为 -1.0,第二个更新为 -0.001,两者相差 1,000 倍,符合梯度的大小。Adam 将两者的更新量都设为学习率 -0.001,因为其归一化步长取决于梯度的方向和一致性,而不是梯度的原始大小。
Adam 与 AdamW#
常见实现中的 Adam 会将权重衰减作为一种正则化方法,以 L2 惩罚项的形式加到梯度上;随后该惩罚项会与其他所有内容一起除以 √v̂,因此梯度较大的权重几乎不会受到正则化。Loshchilov 和 Hutter 提出的解耦权重衰减通过在每一步直接缩减权重,并将其与自适应更新分开,解决了这个问题。论文实验表明,由此得到的 AdamW 在图像分类任务上的泛化能力优于 Adam;你可以通过 torch.optim.AdamW使用 AdamW。
Adam 与 SGD#
带动量的 SGD 使用一个全局学习率,并为每个参数存储一个缓冲区;而 Adam 会存储两个缓冲区,在 32 位精度下每个参数占用 8 字节,因此一个拥有 70 亿参数的模型需要 56 GB 优化器状态。Adam 通常在前期进展更快,对学习率不那么敏感,而且比 SGD 更可靠地训练 Transformer。经过良好调优的 SGD 在卷积图像模型上通常能达到相同或更高的最终准确率,而 Wilson 等人发现,在他们测试的图像分类和语言任务中,自适应方法的泛化能力往往不如 SGD。
Ultralytics YOLO 训练体现了这种权衡:默认的 optimizer="auto" 会选择 AdamW,初始学习率根据类别数量调整,最多运行 10,000 次迭代;对于更长的训练计划,则会切换到 MuSGD,它是 SGD 与 Muon 的混合优化器。显式设置优化器时也需要设置学习率,因为默认的 lr0=0.01 适用于 SGD,是 Adam 常用学习率的十倍。
from ultralytics import YOLO
# 加载预训练的 YOLO26n 模型
model = YOLO("yolo26n.pt")
# 使用 AdamW 和适合 Adam 的初始学习率进行训练
results = model.train(data="coco8.yaml", epochs=5, optimizer="AdamW", lr0=0.001)当 YOLO26使用 Adam 系列优化器训练时,momentum 参数(默认值为 0.937)会设置 β1,而 β2 保持固定为 0.999。
Adam 与相关优化器#
- AdaGrad:每一步都除以过去所有梯度平方和的平方根,因此步长只会不断缩小。这适用于稀疏特征,但会拖慢较长的训练过程。
- RMSProp:将 AdaGrad 的累积和替换为梯度平方的指数衰减平均值。从本质上说,Adam 就是加入了动量和偏差校正的 RMSProp。
- Muon:用于隐藏层二维权重矩阵的优化器。它通过 Newton–Schulz 迭代对每次动量更新进行正交化,并为每个参数保留一个状态缓冲区,只有 Adam 优化器状态的一半。










