优化算法三剑客:SGD、Adam、AdamW的深度对比

优化算法三剑客:SGD、Adam、AdamW的深度对比

1. 引言:模型训练的"导航系统"

想象一下,你正在一个复杂的地形中寻找最低点(最小损失),四周浓雾弥漫(高维空间不可视)。优化算法就是你的GPS导航系统,它决定着你如何一步步走向目的地。

今天我们要认识三位风格迥异的"导航员":稳重的老将SGD灵活的Adam精致的AdamW。让我们一起来看看它们各自的看家本领!

2. 随机梯度下降(SGD):大道至简

2.1 核心思想

SGD就像一位经验丰富的登山老人,他相信"欲速则不达",每一步都脚踏实地。

基本公式:

$$θ_{t+1} = θ_t - η · ∇J(θ_t)$$

其中:

  • θ_t​:第t步的模型参数
  • η​:学习率(步长)
  • ∇J(θ_t)​:损失函数在θ_t​处的梯度

2.2 代码示例

import torch
import torch.nn as nn

简单线性回归示例

model = nn.Linear(10, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

训练循环

for epoch in range(100):
# 前向传播
outputs = model(inputs)
loss = criterion(outputs, labels)

# 反向传播
optimizer.zero_grad()
loss.backward()

# SGD更新:简单直接的参数更新
optimizer.step()

2.3 优缺点分析

优点:

  • ✅ 简单易懂,理论成熟
  • ✅ 通常能找到更泛化的解
  • ✅ 对学习率调度友好

缺点:

  • ❌ 收敛速度较慢
  • ❌ 对学习率敏感
  • ❌ 容易陷入局部最优

3. Adam:自适应学习率的王者

3.1 核心思想

Adam就像一位聪明的年轻向导,他会根据地形自动调整步伐,陡坡小步走,平路大步跑。

Adam公式分解:

一阶矩估计(动量项):

$$m_t = β_1 · m_{t-1} + (1 - β_1) · g_t$$

二阶矩估计(自适应学习率):

$$v_t = β_2 · v_{t-1} + (1 - β_2) · g_t²$$

偏差校正:

$$m̂_t = m_t / (1 - β_1^t) \\ v̂_t = v_t / (1 - β_2^t)$$

参数更新:

$$θ_t = θ_{t-1} - η · m̂_t / (\sqrt(v̂_t) + ε)$$

3.2 形象比喻

想象你在下山:

  • m_t:考虑了你之前的方向,避免"之字形"走法
  • v_t:根据坡度调整步长,陡的地方小步走

3.3 代码示例

# 同样的模型,使用Adam优化器
model = nn.Linear(10, 1)
optimizer = torch.optim.Adam(
    model.parameters(), 
    lr=0.001,           # 通常更小的学习率
    betas=(0.9, 0.999), # 一阶和二阶矩的衰减率
    eps=1e-8            # 数值稳定性项
)

训练流程相同,但内部更新机制更智能

3.4 优缺点分析

优点:

  • ✅ 收敛速度快
  • ✅ 对学习率不敏感
  • ✅ 适合稀疏梯度场景

缺点:

  • ❌ 可能泛化性能不如SGD
  • ❌ 内存占用稍大
  • ❌ 超参数更多

4. AdamW:权重衰减的正确打开方式

4.1 核心问题:L2正则化 ≠ 权重衰减

这是一个很多人的认知误区!在Adam中,传统的L2正则化与自适应学习率机制会产生不良相互作用

Adam vs AdamW的区别:

# Adam (错误的方式)
gradient = gradient + weight_decay * parameter
parameter = parameter - learning_rate * adapted_gradient

AdamW (正确的方式)

parameter = parameter - learning_rate * (adapted_gradient + weight_decay * parameter)

数学表达:

Adam with L2 regularization:

$$θ_t = θ_{t-1} - η · m̂_t / (√v̂_t + ε) - ηλθ_{t-1}$$

AdamW with decoupled weight decay:

$$θ_t = θ_{t-1} - η · (m̂_t / (√v̂_t + ε) + λθ_{t-1})$$

4.2 核心思想

AdamW就像一位注重细节的工程师,他发现Adam的"小毛病"并进行了精准修复。

4.3 代码示例

# 使用AdamW
model = nn.Linear(10, 1)
optimizer = torch.optim.AdamW(
    model.parameters(),
    lr=0.001,
    weight_decay=0.01,  # 现在这是真正的权重衰减!
    betas=(0.9, 0.999)
)

4.4 为什么重要?

在计算机视觉和Transformer模型中,AdamW通常比Adam表现更好,因为它实现了真正的权重衰减,有助于模型更好地泛化。

5. 三剑客对比:各显神通

5.1 性能对比表格

特性 SGD Adam AdamW
收敛速度
超参数敏感度
内存占用
泛化性能
使用难度
适用场景 简单模型、调优好的场景 默认选择、复杂模型 计算机视觉、Transformer

5.2 选择指南

选择SGD当:

  • 你有时间和计算资源进行充分调优
  • 追求最好的泛化性能
  • 配合优秀的学习率调度器

选择Adam当:

  • 你需要快速原型开发
  • 处理稀疏梯度问题
  • 不想花太多时间调参

选择AdamW当:

  • 训练Transformer模型(BERT、GPT等)
  • 计算机视觉任务
  • 想要Adam的便利+更好的泛化

6. 实战建议

6.1 学习率设置经验

# 典型的学习率设置
SGD_lr = 0.01      # 相对较大
Adam_lr = 0.001    # 相对较小  
AdamW_lr = 0.001   # 与Adam类似

权重衰减设置

Adam_weight_decay = 0 # 通常不用
AdamW_weight_decay = 0.01 # 常用值

6.2 实际应用场景

# 场景1:简单的全连接网络
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

场景2:训练ResNet

optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)

场景3:BERT微调

optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5, weight_decay=0.01)

7. 总结:没有银弹,只有合适

通过我们的对比,可以看到:

  • SGD 像老匠人,需要经验但能出精品
  • Adam 像现代工具,开箱即用效率高
  • AdamW 像精密仪器,在特定场景表现卓越

实践建议:

  • 初学者从Adam开始
  • 追求极致性能考虑SGD+精心调参
  • Transformer和CV任务优先尝试AdamW

记住,优化算法的选择不是绝对的,最好的方法是在你的具体任务上进行实验验证


希望这篇博客能帮助你更好地理解这三种优化算法。Happy training!

posted @ 2025-11-04 19:42  黑冰5  阅读(247)  评论(0)    收藏  举报
runAll: function() { this.resetPreCode(); hljs.initHighlightingOnLoad(); // 重新渲染,添加语法高亮 hljs.initLineNumbersOnLoad(); // 为代码加上行号 }