资讯动态

深度学习优化器全解析:从SGD到AdamW的选型与调参指南

发布时间:2026/10/12 22:59:27 来源:尧图企业网站定制
1. 为什么优化器值得单独拎出来聊但凡动手训过模型的人迟早都会在某个深夜盯着loss曲线发呆明明网络结构没动、数据也没换换个优化器或者调一下它的参数收敛速度和最终精度就能差出一大截。优化器optimizer这个词听起来像是框架里一个不起眼的配置项实际上它是整个训练过程的方向盘——它决定了参数沿着梯度的反方向到底走多远、走多快、要不要带点惯性、遇到震荡要不要刹车。我见过太多新手把注意力全砸在模型结构上觉得网络设计得够花哨就能出效果结果训练半天不收敛回头一看优化器还是默认配置学习率从头到尾没动过。也见过有人盲目照搬别人的超参别人用0.001自己就用0.001完全不考虑batch size、数据规模、任务类型的差异。这篇文章就是想把优化器这件事从头到尾讲透它是什么、为什么这么设计、不同优化器之间到底差在哪、实际训练时该怎么选怎么调、踩过哪些坑。内容会覆盖从最朴素的SGD到Adam、AdamW这一整条演进脉络重点不是背公式而是理解每个设计决策背后的动机。适合刚入门想搞明白训练细节的同学也适合已经能跑通模型但总感觉收敛不对劲、想系统梳理一遍的从业者。看完你至少能做到拿到一个新任务知道该从哪个优化器起步学习率大概给多少什么时候该换、什么时候该调。2. 优化器的本质它到底在解决什么问题2.1 从梯度下降到参数更新训练神经网络说白了就是找一组参数让损失函数的值尽可能小。数学上这是个高维非凸优化问题没有解析解只能靠迭代逼近。最基础的做法是梯度下降算出当前参数下损失对每个参数的偏导也就是梯度然后让参数沿着梯度的反方向挪一小步。这一步的大小就是学习率方向就是梯度的反方向。用生活化的类比你被蒙着眼放在一座山上要走到山谷最低点。你能感知到的只有脚下这一小块地面的倾斜方向于是你朝着下坡方向迈一步再重新感知、再迈一步。学习率就是你每一步迈多大——迈太小走得慢迈太大可能直接跨过谷底甚至摔下悬崖。这个朴素逻辑就是SGD随机梯度下降的核心。但真实训练里纯粹的SGD有几个绕不开的麻烦梯度噪声大导致更新方向抖动、不同参数方向的曲率差异巨大导致学习率很难统一、容易卡在鞍点或局部极小值附近。后面所有的优化器改进本质上都是在解决这几个问题。2.2 一阶方法与二阶方法的取舍理论上如果我们能算出损失函数的二阶导数Hessian矩阵就能知道每个方向的曲率从而给出更精准的步长这就是牛顿法这类二阶方法的思路。但神经网络的参数量动辄百万千万Hessian矩阵是参数量的平方级别存储和求逆都不现实。所以深度学习里几乎清一色用的是一阶方法只用梯度信息通过一些巧妙的近似和累积来模拟二阶信息的效果。Adam里的二阶矩估计、AdaGrad里的梯度平方累积本质上都是在用一阶信息去近似每个参数方向应该走多大步这件事。理解了这一点你就能明白为什么这些优化器在稀疏梯度、不同尺度参数共存的场景下表现更好——它们在做某种程度上的自适应。2.3 优化器、学习率、batch size的三角关系这里必须先厘清一个常见误区优化器不是孤立起作用的它和学习率调度、batch size强耦合。batch size越大梯度的方差越小、方向越准理论上可以用更大的学习率反过来小batch噪声大学习率就得保守些。有个经验规律是学习率和batch size的平方根大致成正比虽然不绝对但可以作为调参的起点。优化器本身很多时候只是决定了如何利用梯度而学习率决定了利用的强度。所以你会看到同一个优化器在不同学习率下表现天差地别也会看到有人换了优化器但没调学习率然后得出这个优化器不行的结论——这其实是不公平的对比。3. 主流优化器逐个拆解设计动机与适用场景3.1 SGD与Momentum最朴素也最稳的基线纯SGD的更新公式很干净参数减去学习率乘以梯度。它的优点是泛化性能往往不错很多图像分类的经典结果都是用调好学习率的SGD加动量跑出来的。缺点是收敛慢、对学习率敏感、在峡谷型损失面上来回震荡。Momentum的引入就是为了解决震荡问题。它引入一个速度变量把历史梯度累积起来相当于给下山的小球加了惯性。这样在梯度方向一致的维度上速度越来越快在反复震荡的维度上正负抵消从而加速收敛、抑制抖动。动量系数一般取0.9意思是保留90%的历史速度、加入10%的当前梯度。还有一个变种叫Nesterov动量它的思路是先按当前速度往前探一步在那个预判位置算梯度再修正。直觉上像是提前看了一眼前面的路收敛通常比标准动量略好。实际用起来两者差距不大Nesterov在理论上有更好的收敛保证。实操心得如果你在做图像分类、追求最终精度而不是训练速度SGDMomentum配上余弦退火学习率往往能比Adam高出零点几个百分点。代价是你得花时间调学习率和调度策略。3.2 AdaGrad、RMSProp自适应学习率的开端SGD对所有参数用同一个学习率但实际中不同参数的梯度尺度可能差好几个数量级。稀疏特征对应的参数更新次数少应该给大一点的学习率频繁更新的参数则应该收敛得稳一些。AdaGrad的思路就是累积每个参数历史梯度的平方用它来缩放学习率——更新频繁的参数累积值大学习率被压小更新稀疏的参数累积值小学习率保持较大。这个设计在稀疏数据场景比如推荐系统里的稀疏特征非常有效。但问题也很明显累积值只增不减训练到后期学习率会被压到几乎为零模型提前学不动了。RMSProp就是来修这个bug的它把累积改成指数移动平均只关注近期梯度的量级让学习率不会无限衰减。RMSProp在非平稳目标比如RNN训练上表现不错也是后来Adam的直接前身。3.3 Adam集大成者与它的隐忧Adam把动量和自适应学习率结合到了一起一阶矩估计负责方向上的惯性二阶矩估计负责每个参数的步长缩放还加了偏差修正来处理初期估计不准的问题。它的默认超参学习率0.001、beta10.9、beta20.999在绝大多数任务上开箱即用收敛快、对学习率不那么敏感这也是它成为默认选择的原因。但Adam不是没有代价。实践中发现Adam训练出来的模型在某些任务上泛化性能不如调好的SGD尤其是在图像分类这类任务上。一个被广泛讨论的原因是自适应学习率会让模型倾向于收敛到尖锐的极小值而尖锐极小值对数据扰动更敏感泛化就差。另一个原因是L2正则和Adam的自适应缩放会打架导致正则效果被削弱。3.4 AdamW把权重衰减从梯度里拿出来刚才提到的L2正则问题AdamW给出了干净的解法。传统做法是把L2正则项加到损失里等价于在梯度上加一个正比于参数的项。但在Adam里这个项会被二阶矩估计缩放导致大梯度的参数正则力度被削弱、小梯度的参数正则力度被放大效果就乱了。AdamW的做法是把权重衰减从梯度更新里剥离出来直接在参数上做衰减不参与自适应缩放。这样正则的力度就和梯度尺度解耦了行为更可预测。现在很多Transformer类模型的训练默认就用AdamW效果确实比原版Adam稳。3.5 一张表看清各优化器的差异优化器核心机制优点缺点典型场景SGD纯梯度更新泛化好、简单慢、对学习率敏感图像分类基线SGDMomentum加惯性收敛快、抑制震荡仍需调学习率经典CV任务AdaGrad累积梯度平方适合稀疏特征学习率单调衰减推荐、NLP稀疏场景RMSProp梯度平方的移动平均非平稳目标表现好仍需调参RNN、序列任务Adam动量自适应偏差修正开箱即用、收敛快泛化可能略差通用默认选择AdamWAdam解耦权重衰减正则行为清晰需注意衰减系数Transformer类模型4. 实操怎么选、怎么调、怎么排坑4.1 选型决策从任务特征出发选优化器不是选最好的而是选最匹配当前任务的。我的经验顺序是这样的如果是Transformer类模型或者NLP任务直接上AdamW学习率从1e-4到3e-4之间试如果是CNN图像分类且追求精度用SGDMomentum学习率从0.1起步配余弦退火如果是RNN或序列建模RMSProp或Adam都行如果数据特别稀疏先考虑AdaGrad系。还有一个容易被忽略的点微调预训练模型时优化器选择和新任务的数据量有关。数据少的时候AdamW更稳因为自适应学习率能防止某些参数被过度更新数据充足时SGD系可能泛化更好。这个没有铁律得靠实验。4.2 学习率比优化器本身更重要的参数我个人的排序是学习率 优化器 其他超参。学习率没调好换什么优化器都白搭。几个实操建议用学习率扫描找量级从1e-1到1e-6按10倍间隔各跑几百步看哪个量级loss下降最快然后在这个量级附近细化。配合warmup训练初期参数随机梯度可能很大直接上大学习率容易炸。前几百到几千步线性升温到目标学习率能显著提升稳定性Transformer训练几乎必用。配合衰减调度余弦退火、阶梯衰减、线性衰减都行目的是后期让学习率降下来精细收敛。余弦退火因为平滑、无需手动设衰减点用得最多。4.3 权重衰减与正则的配合用Adam时如果你要做L2正则建议直接换AdamW把weight_decay参数设成1e-2到1e-4之间试。用SGD时L2正则加在损失里是没问题的因为SGD没有自适应缩放正则行为是线性的。这个细节很多人不注意结果用Adam加L2发现正则几乎没效果还以为是系数设小了。4.4 梯度裁剪防止训练炸掉的保险丝不管用什么优化器梯度裁剪都建议加上尤其是RNN和深层网络。做法是算完梯度后如果梯度的范数超过某个阈值就按比例缩放回去。阈值一般设1.0或5.0。这不是优化器的一部分但和优化器配合使用能极大提升训练稳定性。我踩过的坑就是有次训练loss突然变成NaN排查半天发现是某一步梯度爆炸加了裁剪后再没出现过。5. 常见问题与排查速查5.1 loss不下降或下降极慢先看学习率是不是太小其次看优化器选得对不对。如果用的是SGD且学习率只有1e-4那基本等于没在学。另外检查梯度是不是被某种操作截断了比如用了sigmoid激活导致梯度消失。还有一种情况是数据没归一化特征尺度差异大导致损失面极度扭曲这时候自适应优化器能缓解但治标不治本。5.2 loss震荡剧烈或发散学习率太大是最常见原因先降一个数量级试试。如果加了动量检查动量系数是不是过高。梯度爆炸的话加梯度裁剪。还有一种隐蔽情况是batch size太小导致梯度噪声过大适当增大batch或做梯度累积。5.3 训练集loss降但验证集不降这是过拟合不是优化器的问题但优化器选择会影响过拟合程度。Adam系有时会更快过拟合因为它收敛快。可以试试换SGD、增大权重衰减、加dropout。另外AdamW的解耦权重衰减在这种场景下通常比Adam表现好。5.4 换了优化器结果反而变差大概率是学习率没跟着调。不同优化器对学习率的敏感度完全不同Adam的0.001和SGD的0.001根本不是一个概念。换优化器时一定要重新扫学习率否则对比是不公平的。现象可能原因排查方向loss不降学习率过小、梯度消失调大学习率、检查激活函数loss震荡学习率过大、动量过高降学习率、减动量loss变NaN梯度爆炸加梯度裁剪、降学习率验证集不降过拟合加正则、换优化器、加数据换优化器变差学习率未重调重新扫描学习率6. 几个容易被忽略的进阶细节6.1 优化器状态的内存开销Adam要为每个参数存一阶矩和二阶矩也就是两份额外状态显存占用是参数量的两倍。大模型训练时这个开销很可观。如果显存吃紧可以考虑AdaFactor这类省内存的优化器它用矩阵分解的方式近似二阶矩把状态从O(n)降到O(sqrt(n))。或者用8-bit Adam这类量化方案把状态压到低精度。6.2 学习率预热与重启warmup前面提过了这里说下余弦退火重启训练到一定步数后把学习率重新拉高相当于让模型跳出当前极小值再找更好的。这个技巧在集成和某些竞赛场景有用但会增加训练时间日常训练不一定需要。6.3 不同层用不同学习率微调预训练模型时底层特征通常比较通用不需要大改顶层任务相关需要更大更新。所以常见做法是底层用小学习率、顶层用大学习率这叫分层学习率。实现上就是给不同参数组设置不同的lr优化器本身支持参数组配置。6.4 优化器与混合精度的配合用混合精度训练时梯度会做缩放防止下溢。这时候优化器看到的是缩放后的梯度更新前要记得把缩放还原。主流框架的自动混合精度工具会帮你处理但如果你手动实现一定要在优化器step之前unscale梯度否则更新量会错得离谱。这个坑我在早期手写训练循环时踩过loss直接不收敛排查了很久。7. 我个人的调参习惯说了这么多最后分享下我自己实际训练时的固定流程。拿到新任务先固定一个AdamW、学习率3e-4、weight_decay 1e-2、warmup 500步、余弦退火跑一遍看能不能收敛、大概什么水平。这一步的目的是快速验证数据和模型没问题。然后如果追求精度再切到SGDMomentum学习率从0.1开始扫配余弦退火通常能再涨一点。如果显存紧张或者模型特别大考虑AdaFactor或8-bit优化器。调参这件事没有银弹优化器只是其中一环。但把优化器的原理和脾气摸清楚至少能让你在loss不对劲的时候知道往哪个方向查而不是盲目地改网络结构或者加数据。我见过太多人把优化器当黑盒结果在错误的方向上浪费了大量时间。希望这篇能把这块讲明白让你下次调参时心里有底。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑