去年我在训练一个文本分类模型时遇到了奇怪的现象:模型在训练集上的准确率轻松突破95%,但验证集表现始终卡在82%左右。调整学习率、增加Dropout层、扩充数据量都收效甚微。直到把TensorBoard的权重分布可视化打开,才发现隐藏层参数正在以惊人的速度膨胀——这是典型的过拟合信号。
问题根源最终锁定在Adam优化器的权重衰减机制上。传统SGD中,权重衰减(L2正则化)是直接作用于参数更新的独立项。但在Adam的实现里,权重衰减被错误地耦合进了梯度计算过程。就像给汽车刹车时同时踩油门和刹车,虽然车速会下降,但发动机始终处于高负荷状态。
具体来说,当使用Adam时:
这个发现让我意识到,优化器的选择不仅影响收敛速度,更直接关系到模型能否学到真正有效的特征表示。
2017年ICLR论文《Decoupled Weight Decay Regularization》提出的AdamW,其核心创新可以用一个比喻理解:把原本绑在一起的"学习"和"减肥"两个过程分开管理。具体实现只需要修改一行代码,但带来的改变却是革命性的。
让我们对比下Adam和AdamW的更新公式差异:
Adam的参数更新:
python复制param -= lr * (m_hat / (sqrt(v_hat) + eps) + weight_decay * param)
AdamW的参数更新:
python复制param -= lr * (m_hat / (sqrt(v_hat) + eps))
param -= lr * weight_decay * param # 独立权重衰减
这个看似微小的调整,实际解决了三个关键问题:
在实际训练曲线中,这种解耦最直观的表现是:
在LLaMA-2的官方训练配置中,AdamW的三个关键参数设置为:
这个配置经过大量实验验证,特别适合Transformer架构。我在复现Alpaca模型时测试发现,当weight_decay从0.1调整为0.01时,模型在常识推理任务上的准确率下降了约3%。
对于不同规模的模型,建议的AdamW配置策略:
| 模型参数量 | 学习率 | 权重衰减 | Batch Size |
|---|---|---|---|
| <1B | 3e-4 | 0.1 | 256 |
| 1B-10B | 1e-4 | 0.1 | 1024 |
| >10B | 5e-5 | 0.05 | 2048 |
实际使用时还需要注意:
在CV领域,我们将AdamW应用在ViT模型训练时发现一个有趣现象:当图像分辨率从224提升到384时,最优weight_decay需要从0.1降低到0.03。这说明解耦后的权重衰减仍然需要根据任务特性调整。
一个实用的调参技巧是监控权重范数比(WNR):
python复制wnr = torch.norm(param) / torch.norm(param.grad)
当WNR持续大于100时,说明需要增大weight_decay;小于10时则应该减小。
对于需要快速原型开发的场景,我推荐使用分层衰减策略:
python复制optimizer = AdamW([
{'params': model.backbone.parameters(), 'weight_decay': 0.1},
{'params': model.head.parameters(), 'weight_decay': 0.01}
], lr=3e-4)
这种设置既保持了底层特征的稳定性,又给顶层分类器足够的灵活性。在NLP和CV的跨模态实验中,这种方法相比统一衰减带来了平均1.2%的性能提升。