随机梯度下降(SGD)基础:从数学原理到PyTorch实战

1次阅读
没有评论

共计 1466 个字符,预计需要花费 4 分钟才能阅读完成。

image.webp

背景痛点

在深度学习的模型训练中,随机梯度下降(Stochastic Gradient Descent, SGD)是最基础的优化算法之一。然而,由于深度学习模型的损失函数通常是非凸的,SGD 在实际应用中面临着诸多挑战。

随机梯度下降 (SGD) 基础:从数学原理到 PyTorch 实战

  • 非凸函数优化:非凸函数的优化问题通常存在多个局部最优解,SGD 可能会陷入这些局部最优而无法找到全局最优解。
  • 学习率衰减策略:学习率(learning rate)的选择对 SGD 的收敛速度和最终性能至关重要,但如何动态调整学习率(如学习率衰减策略)是一个常见难题。

技术对比

SGD 与其他梯度下降变体的比较:

  • 批量梯度下降(BGD):每次迭代使用全部训练数据计算梯度,计算复杂度高,但梯度方向稳定。
  • Mini-batch 梯度下降:折中方案,每次迭代使用一小批数据计算梯度,平衡了计算效率和稳定性。

以下是不同优化器在 CV/NLP 任务中的表现差异:

优化器 CV 任务准确率 NLP 任务 BLEU 分数
SGD 92.1% 28.5
Adam 93.5% 30.2
RMSProp 93.2% 29.8

核心实现

以下是一个带 momentum 的 SGD 实现,包含学习率 warmup 和余弦退火的代码片段:

import torch
import torch.optim as optim

# 定义模型和损失函数
model = ...
criterion = ...

# 带 momentum 的 SGD 优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

# 学习率 warmup
for epoch in range(num_epochs):
    # 线性 warmup
    lr = 0.01 * min(epoch / warmup_epochs, 1.0)
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

    # 余弦退火
    lr = 0.01 * 0.5 * (1 + math.cos(math.pi * epoch / num_epochs))
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

梯度裁剪 的阈值计算方法:

# 梯度裁剪
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

实验验证

在 MNIST 数据集上,我们可视化了不同 batch size 下的 loss 曲面:

  • 小 batch size(32):loss 曲面波动较大,但更容易跳出局部最优。
  • 大 batch size(1024):loss 曲面平滑,但容易陷入局部最优。

学习率与批量大小的协同影响:

  1. 学习率过大时,模型可能无法收敛。
  2. 学习率过小时,收敛速度过慢。
  3. 批量大小与学习率通常需要成比例调整。

生产建议

在分布式训练中,梯度聚合的通信优化技巧:

  • 使用梯度压缩技术减少通信量。
  • 异步更新梯度以减少等待时间。

如何根据 GPU 显存动态调整批量大小:

  1. 监控 GPU 显存使用情况。
  2. 动态调整 batch size 以避免显存溢出。

延伸思考

关于 SGD 二阶优化的开放性问题:

  1. 如何利用 Hessian 矩阵信息加速 SGD 收敛?
  2. 能否设计自适应学习率策略以更好地处理非凸函数?
  3. 如何结合 SGD 与其他优化器的优势?

推荐阅读:《Optimization for Deep Learning》第 3 章。

总结

SGD 作为深度学习中最基础的优化算法,虽然简单,但在实际应用中需要仔细调参。通过合理设置学习率、批量大小和使用技巧如梯度裁剪、学习率 warmup 等,可以显著提升模型性能。希望本文能帮助读者更好地理解和应用 SGD。

正文完
 0
评论(没有评论)