1. 优化器的前世今生:为什么我们需要这么多算法?
第一次接触深度学习优化器时,你可能和我当年一样困惑:为什么要有这么多算法?SGD、Adam、RMSprop...它们到底有什么区别?这个问题要从深度学习的本质说起。想象你在一个伸手不见五指的山谷里,目标是要找到最低点。优化器就是你手里的那盏灯,决定了你下山的速度和路径。
最原始的SGD(随机梯度下降)就像拿着一盏忽明忽暗的煤油灯,虽然简单直接,但遇到复杂地形就很容易卡在半山腰。2011年出现的AdaGrad给这盏灯加了个自动调光功能,但调得太狠可能导致灯光过早变暗。随后出现的RMSprop和Adam则像升级成了智能手电筒,不仅能自动调节亮度,还能预判地形变化。
我在训练图像分类模型时就深有体会:用普通SGD可能要调几十次学习率才能收敛,而切换到Adam后,模型在三五次尝试内就能找到不错的结果。但这不意味着Adam就是万能钥匙——在自然语言处理任务中,AdamW往往表现更好,因为它解决了权重衰减(weight decay)与自适应学习率之间的冲突问题。
2. 基础优化器详解:从SGD到Momentum
2.1 随机梯度下降(SGD):最朴实的起点
# PyTorch中的SGD实现示例 optimizer = torch.optim.SGD(model.parameters(), lr=0.01)SGD的核心思想简单到令人发指:沿着梯度方向一小步一小步往下走。我在MNIST手写数字识别项目里测试过,当学习率设为0.1时,SGD在前几轮就能快速降低损失,但很快就会在最小值附近"跳舞",始终无法稳定下来。这时常见的处理是加入学习率衰减:
# 带学习率衰减的SGD scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)实际使用时有个小技巧:批量大小(batch size)增大N倍时,学习率也可以相应增大N倍。这个经验来自我参与的一个电商推荐系统项目,当batch size从256调到1024时,学习率从0.01调到0.04效果最佳。
2.2 Momentum:给优化加上"惯性"
Momentum优化器给我的第一印象就像给SGD装了个雪橇——不仅考虑当前梯度,还会保留之前下降方向的"记忆"。公式看起来很简单:
v = β*v + (1-β)*∇J(θ) θ = θ - η*v但实际效果惊人。在训练ResNet时,普通SGD需要120轮才能收敛,而加入momentum(β=0.9)后,80轮就能达到相同精度。不过要注意,β值太大会导致"刹不住车",我在一次实验中设β=0.99,结果损失函数直接飞出了合理范围。
3. 自适应学习率优化器:从AdaGrad到Adam
3.1 AdaGrad与RMSprop:解决稀疏特征问题
2011年提出的AdaGrad特别适合处理稀疏特征,比如NLP中的词向量。它的核心思想是对频繁出现的参数进行小幅度更新,对罕见参数进行大幅度更新。但实际使用时我发现一个致命问题:随着训练进行,学习率会越来越小,最终导致模型提前停止学习。
RMSprop通过引入衰减因子解决了这个问题。我在Kaggle比赛中的经验是:对于视觉任务,rho参数设为0.9效果不错;而对于文本任务,0.99更合适。下面是一个典型配置:
optimizer = torch.optim.RMSprop(model.parameters(), lr=0.001, alpha=0.99, eps=1e-08)3.2 Adam:当前的主流选择
Adam结合了Momentum和RMSprop的优点,成为目前最流行的优化器。但很多人不知道的是,Adam对超参数其实相当敏感。经过多次实验,我总结出这些经验值:
- 计算机视觉:lr=3e-4, β1=0.9, β2=0.999
- 自然语言处理:lr=1e-4, β1=0.9, β2=0.98
- 强化学习:lr=1e-3, β1=0.95, β2=0.999
在Transformer模型中,Adam的表现尤其出色。我曾对比过不同优化器在机器翻译任务中的表现,Adam比SGD快了近3倍达到相同BLEU分数。
4. 进阶优化技术与实战选型指南
4.1 AdamW:修正权重衰减的真正Adam
AdamW可能是最被低估的优化器。它解决了原始Adam中权重衰减(L2正则化)与自适应学习率不兼容的问题。在训练BERT时,使用AdamW比Adam最终准确率能提升1-2个百分点。关键配置如下:
optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5, betas=(0.9, 0.999), weight_decay=0.01)4.2 优化器选型决策树
根据我的项目经验,可以总结出以下选型原则:
小数据集(<1万样本):
- 首选LBFGS(如果内存足够)
- 次选SGD with Momentum
计算机视觉任务:
- 初始尝试:Adam (lr=3e-4)
- 精细调优:SGD with Momentum (lr=0.1, momentum=0.9)
- 最终选择:根据验证集表现决定
自然语言处理:
- Transformer架构:AdamW (lr=5e-5)
- RNN架构:RMSprop (lr=1e-3, alpha=0.99)
强化学习:
- 离散动作空间:Adam (lr=1e-3)
- 连续动作空间:SGD with Momentum (lr=0.01, momentum=0.95)
4.3 实际训练中的调试技巧
在最近的一个图像分割项目中,我发现优化器的表现会随着训练阶段变化:
- 初期(0-50轮):Adam效果最好,快速下降
- 中期(50-150轮):SGD with Momentum开始反超
- 后期(150轮后):切换到SGD fine-tuning
于是采用了这样的混合策略:
# 阶段1:使用Adam快速收敛 optimizer1 = torch.optim.Adam(model.parameters(), lr=3e-4) train(epochs=50, optimizer=optimizer1) # 阶段2:切换到SGD精细调整 optimizer2 = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9) train(epochs=100, optimizer=optimizer2) # 阶段3:降低学习率微调 for param_group in optimizer2.param_groups: param_group['lr'] = 0.001 train(epochs=50, optimizer=optimizer2)这种分阶段优化策略在多个计算机视觉项目中都取得了比单一优化器更好的效果。不过要注意,当模型非常大(如GPT-3级别)时,通常从头到尾使用AdamW会更稳定。