2026年4月19日

优化器与训练技巧(Adam / SGD / LR Schedule / Warmup)

优化器的选择和学习率调度是训练深度网络最关键的两个工程决策:

知识库深度学习deep-learningoptimizersgdadamtraining

优化器与训练技巧(Adam / SGD / LR Schedule / Warmup)

先把结论放前面

优化器的选择和学习率调度是训练深度网络最关键的两个工程决策:

  • SGD + Momentum:泛化能力更强,调参直觉清晰,但收敛慢、需要仔细调学习率
  • Adam / AdamW:收敛快,对学习率不那么敏感,但泛化能力有时不如 SGD
  • 实际建议:Transformer 类模型用 AdamW(Adam 的权重衰减修正),CNN / 传统深度学习用 SGD+Momentum,大模型用 AdamW

学习率调度比学习率本身更重要:Warmup + Cosine Annealing 是当前最标准的配置。

SGD with Momentum

标准 SGD

θ ← θ - α · ∇L(θ)

问题是梯度方向震荡,收敛慢。

Momentum(动量)

v_t = β · v_{t-1} + ∇L(θ)    # 动量累积
θ ← θ - α · v_t               # 沿动量方向更新

Momentum 让更新方向保持惯性,减少震荡,加速收敛。β = 0.9 是标准值。

物理类比:一个小球在损失曲面上滚动,Momentum 让它有惯性。

Nesterov Momentum

标准 Momentum 先累积历史梯度再更新,Nesterov 先"前瞻"一步再修正:

v_t = β · v_{t-1} + ∇L(θ - α · β · v_{t-1})  # 先走一步
θ ← θ - α · v_t

Nesterov 通常比标准 Momentum 更快收敛,尤其在曲面弯曲处。

Adam(Adaptive Moment Estimation)

Adam 的更新规则

Adam 维护两个指数移动平均:

  • 动量(m_t):梯度的一阶矩估计(类似 Momentum)
  • 自适应学习率(v_t):梯度平方的指数移动平均(自动调节每个参数的学习率)
m_t = β₁ · m_{t-1} + (1-β₁) · g_t        # 动量
v_t = β₂ · v_{t-1} + (1-β₂) · g_t²       # 自适应学习率(二阶矩)
m̂_t = m_t / (1 - β₁^t)                     # 偏差修正
v̂_t = v_t / (1 - β₂^t)                     # 偏差修正

θ ← θ - α · m̂_t / (√v̂_t + ε)

Adam 的自适应学习率

  • 梯度大的参数 → v_t 大 → 学习率自动减小
  • 梯度小的参数 → v_t 小 → 学习率自动增大

结果是每个参数有独立的学习率,自动适应梯度的稀疏性。

AdamW(带权重衰减的 Adam)

标准 Adam 的 L2 正则化和权重衰减不是一回事——Adam 的自适应学习率让 L2 正则效果不稳定。

AdamW 修正了这个问题,直接在梯度上施加权重衰减:

θ ← θ - α · (m̂_t / √v̂_t + λ · θ)

Adam vs SGD+Momentum

维度 SGD + Momentum Adam / AdamW
泛化能力 更强 有时更差
收敛速度
学习率敏感性 高(需要精细调度) 低(自适应)
超参数调参 相对容易
理论支持 弱(收敛不稳定)
大数据训练 优(泛化好) 差(有时泛化差)

Transformer 训练为什么用 AdamW:因为 Transformer 的优化曲面(loss landscape)用 SGD 不容易找到好的泛化点,AdamW 在收敛速度和泛化之间找到了更好的平衡。

学习率调度(Learning Rate Schedule)

为什么需要学习率调度

固定学习率的两个问题:

  • 学习率太大 → 震荡不收敛
  • 学习率太小 → 收敛太慢

Warmup(学习率预热)

Transformer 训练初期(尤其是大模型)需要 Warmup:

t < T_warmup:  lr = t / T_warmup × lr_max
t ≥ T_warmup: lr = lr_max

为什么需要 Warmup:训练初期参数随机,梯度方向不可靠。如果一开始学习率太大,会把网络"踢"到一个不好的区域,后续很难恢复。Warmup 让参数在早期稳定后再大学习。

Warmup 的另一个解释:分布式训练时,各 Worker 的梯度在早期差异大,Warmup 让网络慢慢稳定。

Cosine Annealing(余弦退火)

lr(t) = lr_min + (lr_max - lr_min) × (1 + cos(π · t / T)) / 2

从 lr_max 缓慢退火到 lr_min,曲线是余弦形状。配合 Warmup 是 Transformer 训练的标准配置:

Warmup (线性) → Cosine Annealing (余弦)

Step Decay(阶梯衰减)

每 N 个 epoch 把学习率乘以 γ(γ = 0.1):

lr_new = lr_old × 0.1  (每 30 epochs)

简单有效,是 CNN 训练的传统方法。但需要手工选择衰减时机,不如 Cosine Annealing 平滑。

实际训练配置参考

Transformer(大模型,推荐)

optimizer = AdamW(model.parameters(), lr=3e-4, weight_decay=0.01)
scheduler = CosineAnnealingWarmupLR(
    optimizer,
    warmup_steps=2000,
    max_steps=num_training_steps,
    min_lr=3e-5
)

CNN(图像,推荐)

optimizer = SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
scheduler = MultiStepLR(optimizer, milestones=[30, 60, 90], gamma=0.1)

如果放到面试里怎么讲

"Adam 为什么有时泛化不如 SGD?"

Adam 的自适应学习率对每个参数自动调节,但这个自适应本身是"短期"的——只看过去几个 step 的梯度平方均值。这会导致它对某些方向的"惩罚"过大,让网络找到的解泛化不如 SGD。Momentum 的 SGD 因为有更"长期"的累积方向,梯度曲面更平滑,泛化能力通常更好。这在大规模训练(如 GPT/BERT)里有大量实验验证。

"Warmup 为什么对 Transformer 重要?"

Transformer 的参数是随机初始化的,早期梯度方向噪声很大。如果一开始学习率太大,会把参数"踢"到一个损失曲面的不稳定区域,难以恢复。另外大模型分布式训练时,早期各 Worker 梯度差异很大,Warmup 让参数在早期稳定下来再大学习,保证各 Worker 同步稳定。

最后记几个点

  1. SGD+Momentum 泛化能力强但收敛慢;Adam 收敛快但泛化有时更差
  2. AdamW = Adam + 正确的权重衰减,是 Transformer 训练的推荐优化器
  3. 学习率调度比学习率本身更重要,固定学习率几乎训不好大模型
  4. Warmup 解决训练初期梯度方向不稳定的问题,是 Transformer 的必备配置
  5. Cosine Annealing + Warmup 是当前最标准的训练配置
  6. 分布式训练(多 GPU)时,梯度同步通信成本高,正确的学习率调度更关键

跨库关联