资讯动态

深度学习优化器全解析:从SGD到Adam的原理与选型指南

发布时间:2026/10/17 20:10:13 来源:尧图企业网站定制
先说个可能很多人踩过的坑模型结构写得再漂亮数据集处理得再干净一跑训练发现loss就是降不下去或者降到某一个数值就开始原地打转。这时候大部分人会去调学习率、调批大小、改网络层数折腾一整天也没找到病根。但真正的问题往往出在优化器上——你用的到底是SGD、Momentum、AdaGrad还是Adam这四种优化器表面上都是“梯度下降的变体”但它们的内部机制差异非常大选错了、参数配错了训练结果能差出一大截。这篇文章我不打算只贴公式了事而是想顺着这四类优化器的发展脉络把它们的原理、适用场景、参数经验和踩坑记录一次讲透。适合正在学深度学习的新手也适合那些已经能跑通模型、但总觉得loss曲线不对劲的进阶玩家。1. 一张损失地形图引发的思考为什么“最陡”方向走不快梯度下降的思路很简单沿着损失函数的负梯度方向更新参数就能让loss逐渐变小。很多教程用小球滚下山坡来比喻但真实训练场景远比“光滑斜坡”复杂得多。1.1 梯度方向是局部信息不是全局答案我在一个模拟项目X里做过一次对照实验同一个网络结构同一个batch只改优化器SGD训练200个epoch之后loss还是3.8换Adam之后只用了40个epoch就降到了1.2。差距就是这么大。问题就出在“梯度方向只是当前位置的局部信息”这句话上。真实任务的损失面往往是高维非凸的有峡谷地带、有鞍点、有平缓的高原。传统SGD在峡谷区域的表现尤其糟糕——垂直于最优方向的那个维度梯度很大会来回震荡而真正需要前进的那个维度梯度很小走得极慢。这就像一个在窄巷子里跑步的人每一步都撞墙反弹实际往前走不了多少。1.2 学习率困境太小走不动太大直接炸SGD的更新公式就一行[ \theta_{t1} \theta_t - \eta \cdot g_t ]这里的(\eta)就是学习率(g_t)是当前梯度。很多人在这一步就犯难了学习率设0.01loss下降特别慢设0.1loss反而爆成NaN。原因在于梯度的大小本身不固定有的参数梯度大有的梯度小同一个学习率不可能同时照顾到两者。你要是为了照顾大梯度把学习率调小那本来梯度就小的参数几乎就冻结了反过来为了照顾小梯度把学习率调大大梯度那个维度直接发散。我在另一个跨平台项目上做过一个极端案例某个参数在训练初期梯度突然达到正常值的20倍全局学习率没变一步更新就把参数推出合理范围整个模型从此再也回不来。这种“病”不是网络结构的问题而是固定学习率机制的天然缺陷。1.3 四类优化器的本质都在解决“步长怎么给”搞清楚了上面的困境再看SGD、Momentum、AdaGrad和Adam就清晰多了。它们本质上是同一问题的四个递进方案SGD步长完全由学习率和当前梯度决定没有任何记忆。Momentum用历史梯度的指数平均来修正当前方向解决震荡问题。AdaGrad用每个参数的历史梯度平方和来调整各自的步长解决稀疏参数更新难的问题。Adam上面两者的融合既有惯性又有自适应步长成为当前默认选择。这个演进过程非常有逻辑值得慢慢拆开来理解。2. 从SGD到Momentum让“裸奔”的梯度带起惯性SGD的问题前面提到了峡谷地形中震荡严重、前进缓慢。Momentum就是冲着这个来的。2.1 物理类比里的“速度变量”想象一个小球从山顶滚下来如果地面是光滑的它会越滚越快不会因为某个方向坡度变缓就立刻停下。Momentum就是给参数更新引入了“速度”的概念[ v_t \beta \cdot v_{t-1} \eta \cdot g_t ][ \theta_{t1} \theta_t - v_t ]这里的(\beta)通常取0.9叫作动量系数。(v_t)一方面记住了历史梯度的方向另一方面给当前梯度留了权重。这个“记忆”的效果是如果在峡谷里垂直方向来回震荡的梯度会被相互抵消而最优方向上前几步积累的速度会保留下来让小球冲过去。2.2 动量为什么能“压住”震荡与噪声梯度本身是有噪声的尤其是小batch训练时每个batch的梯度都只是全样本梯度的估计方向抖动很大。动量相当于对梯度做了时间维度的低通滤波短时间的抖动被平均掉长期稳定的趋势被保留。这里有一个关键点动量不是平均原始梯度而是平均历史速度方向。这听上去区别不大实际效果差别很大。如果直接平均原始梯度一个突然的异常大梯度仍然会瞬间扰乱方向而平均速度时当前梯度要先改变速度再通过速度间接影响参数相当于多了一层缓冲。实际调参中你会发现加了Momentum之后loss曲线的毛刺明显变少了就是低通滤波的功劳。2.3 动量系数的边界取0.99的代价很多入门教程说(\beta)取0.9但这只是经验起点。(\beta)越接近1历史速度的惯性越持久但也意味着对最近梯度的响应越迟钝。我试过把这套方案里的(\beta)调到0.99结果在某个数据集上loss降得奇快但到训练后期会绕着一个停滞点反复打转明显是惯性太大冲过头了、刹不住车。Momentum适合的场景是loss面存在较多狭长沟壑、batch噪声较大。如果数据集本身很干净、梯度方向稳定Momentum带来的收益就有限反而可能因为惯性错过特别窄的极小值点。现在不少框架里的SGD其实都默认内置了Momentum所以“纯SGD”反而少见。3. AdaGrad给每个参数单独配学习率如果说Momentum解决的是“方向不一致”的问题AdaGrad解决的则是“参数尺度不一致”的问题。这个问题的严重性往往被低估。3.1 稀疏特征场景里的更新不公现实任务里特征稀疏的情况太常见了。某用户画像系统里大部分特征在多数样本里都是0只有少数样本出现。按标准SGD的规则那些频繁出现、梯度大的特征会获得大量更新而那些稀缺但重要的特征由于梯度小、更新少几乎学不动。AdaGrad的回应非常直接每个参数都有自己的学习率。更新频繁的参数学习率自动变小更新少的参数学习率自动变大。做法是维护一个梯度平方的累积项[ G_{t,i} \sum_{s1}^{t} g_{s,i}^2 ][ \theta_{t1,i} \theta_{t,i} - \frac{\eta}{\sqrt{G_{t,i} \epsilon}} g_{t,i} ]分子上每个参数除以自己历史梯度平方和的根号。梯度大的参数累积值大有效学习率自动变小梯度小的参数累积值小反而获得更大的更新。3.2 效果明显但有一个要命的缺陷AdaGrad在稀疏数据上的优势是实打实的。我在某自然语言处理Demo里用AdaGrad训练词向量低频词的学习速度肉眼可见地快了起来高频词的参数则更加稳定没有出现反复横跳。但用着用着就会发现另一个问题随着训练进行(G_{t,i})只增不减分母越变越大有效学习率趋于0。训练到后期所有参数几乎都停止更新了。这在凸问题上可能是好事会收敛但在非凸的深度网络里模型还没有达到理想位置就被迫“冻结”损失往往停留在一个偏高的水平。3.3 为什么AdaGrad仍然值得理解AdaGrad现在已经很少作为主力优化器使用但它的核心思想——逐参数自适应学习率——是整个自适应优化器家族的基石。后面出现的RMSProp把“累积全部平方梯度”改成“指数衰减的移动平均”就是为了解决AdaGrad后期学习率归零的问题。而Adam又是对RMSProp加上了动量。你要是不先把AdaGrad搞明白后面的Adam会越看越糊涂。所以别嫌AdaGrad过时。理解它是理解Adam的必经之路。4. Adam把动量与自适应学习率焊到一起Adam是目前实践中最常用的优化器没有之一。它名字里的“自适应矩估计”听起来很玄其实拆开来看并不复杂。4.1 一阶矩和二阶矩的双重记忆Adam维护两个量一阶动量(m_t)对梯度的指数移动平均作用等同于上面说的Momentum记住前进方向。二阶动量(v_t)对梯度平方的指数移动平均作用等同于RMSProp的自适应步长给每个参数配动态学习率。[ m_t \beta_1 m_{t-1} (1 - \beta_1) g_t ][ v_t \beta_2 v_{t-1} (1 - \beta_2) g_t^2 ][ \hat{m}_t \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t \frac{v_t}{1 - \beta_2^t} ][ \theta_{t1} \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} \epsilon} \hat{m}_t ]前两项都好理解。关键在第三个式子里的偏差修正——(\hat{m}_t)和(\hat{v}_t)。因为(m_0)和(v_0)初始为0训练早期的指数移动平均会被往0的方向严重拉低导致前几步更新特别小。Adam通过除以(1 - \beta^t)来补偿这个偏差让训练前期的更新幅度恢复正常。4.2 偏差修正的实际影响去掉它前期直接废我在某图像处理Demo里专门做过对比实验一个用标准Adam一个手工去掉偏差修正项。两种设置在最初20个batch里表现差异巨大。没修正的那边前几步的effective迈步非常小模型参数基本在原地蠕动而标准Adam因为修正项的存在第一个epoch内就能正常进入学习状态。这个细节很多人会忽略因为直接用框架的Adam接口时偏差修正是默认内置的。只有你什么时候自己动手实现优化器或者要魔改Adam才会遇到这种隐蔽问题。4.3 Adam的长处与三个实际坑Adam的优势是组合拳有惯性所以收敛快有自适应步长所以对学习率不敏感。实际项目里Adam甚至可以在不调参的情况下跑出还能看的结果。但用久了你会发现它也有自己的问题。第一个坑训练后期参数可能在最优解附近来回震荡无法像SGD那样收敛到更精确的极小值。实验里用Adam训练到后期loss会稳定在一个区间内但不会再往下探。这是因为二阶动量v的存在让步长控制在很稳定的水平缺乏SGD后期那种“精准打磨”的效果。第二个坑二阶动量对梯度平方的指数平均可能让训练早期的大梯度阴影持续很久。如果一个参数在前几个batch碰到特别大的梯度v_t会被推高之后较长一段时间内该参数的学习率都会被压低哪怕后续梯度早就恢复正常了。第三个坑Adam对学习率的初始值不如SGD那么敏感但并不是完全不用调。默认的0.001在小任务上很好使但某些需要长训练的大模型场景里0.001反而过大了会出现前期收敛快、后期震荡明显的情况。很多大模型训练用的是0.0001甚至更小的学习率配合warmup策略慢慢加上去。5. 现代选型与参数调优用一张表选好起点做个简单的横向总结方便你对号入座。优化器核心思想擅长场景主要缺陷常用默认值SGD直接沿负梯度更新收敛后期精细调优震荡剧烈、对学习率敏感lr0.01momentum0.9Momentum历史速度修正方向峡谷地形、batch噪声大惯性过大会错过局部极小点lr0.01beta0.9AdaGrad逐参数累计平方梯度稀疏特征、低频参数学习率单调衰减到0lr0.01eps1e-8Adam一阶动量二阶自适应大多数任务优先基线泛化性可能略逊于SGDlr0.001beta10.9beta20.999这是一份起点配置不是终点配置。真实项目里很少一上来就定死优化器一般都要做两三次切换实验。5.1 我的项目选型路径建议第一条通用路线先用Adam以0.001的学习率快速跑通整个pipeline确认数据和模型都没问题。Adam对参数的容忍度高能帮你把网络结构、数据增强、loss函数这些更重要的环节先稳定下来。等到模型整体工作正常了再考虑换成SGD加Momentum继续训练往往能在Adam的基础上再挤压出一点精度。第二条路线如果你的任务场景是广告点击率预估、推荐系统特征交互特征极其稀疏那AdaGrad的思路仍然有很强的启发性。即便现代框架里更多用Adam或AdamW但理解AdaGrad能帮助你理解为什么稀疏特征需要单独的学习率策略以及为什么这类任务里Embedding层的优化器设置要格外小心。第三条路线关注训练稳定性的话可以看一下Adam的变种AdamW把权重衰减从损失函数项里拆出来直接作用在参数更新上对泛化性有实际提升。现在不少人直接用AdamW代替Adam尤其在Transformer类结构里。5.2 参数设置心得别全指望默认值框架默认的Adam参数是(\beta_10.9)、(\beta_20.999)、(\epsilon10^{-8})这是论文里的标准配置但不该无脑照搬。如果你的batch很小梯度噪声大可以考虑把(\beta_1)调到0.95甚至0.99增加惯性来平滑噪声。我做过实验batch16时(\beta_1)从0.9改成0.95后loss曲线明显平滑。如果你的数据分布变化较快比如强化学习场景过大的(\beta_2)会让二阶动量反应迟钝跟不上梯度变化。这种情况下把(\beta_2)从0.999降到0.99可以让学习率调整更灵敏。(\epsilon)不是越小越好。太小会让分母接近0数值上容易不稳定太大又会稀释自适应效果。一般别低于(10^{-8})但也不要为了“更精确”把它设成(10^{-12})反而可能导致数值问题。5.3 学习率调度的配合使用优化器和学习率调度从来不是分开的话题。即使选了Adam也建议配一个学习率衰减策略。我在某个跨平台项目中观察到Adam跑前200个epoch时loss降得很快之后再跑200个epoch几乎没变化后来加上余弦衰减调度倒是又挤出了一些收益。学习率调度和优化器的组合可以这样搭配Adam 线性warmup适合大模型训练避免训练初期参数剧烈变动。Adam 余弦退火适合图像分类、目标检测后期能平滑收敛。SGD Momentum 余弦退火适合迁移学习中的微调阶段在预训练权重基础上做精细调整。一个小劝告不要同时把所有优化器参数都改成奇奇怪怪的值。一个优化器同时动了(\beta_1)、(\beta_2)和(\epsilon)出了问题你根本定位不到是谁的锅。一次只改一个变量记录实验曲线才是可复现的做法。6. 我踩过的一个真实调参坑希望你别再踩最后分享一段真实经历。在某图像处理Demo里我把模型从SGD换成Adam让训练速度提了上来结果验证集准确性肉眼可见地掉了。当时我第一反应是学习率没调好反复试了0.0001、0.00001都不行。后来才发现问题出在权重衰减上——原来的SGD代码里weight_decay是加在损失函数里的Adam和SGD对权重衰减的处理方式不一样直接搬过去导致正则化强度失真。这个问题的经典解法就是改成AdamW把权重衰减放到更新项里显式处理。换过去之后验证集准确性才恢复正常。这个案例给了我一个通用教训更换优化器不是换一行代码的事。SGD时代建立起来的那套调参经验在Adam上并不完全适用。你要重新审视学习率、权重衰减、batch大小这些交互因素而不是指望一个万能优化器替你摆平一切。优化器选型这件事说到底没有银弹。Adam跑得快SGD磨得准稀疏问题找AdaGrad家族动量解决震荡。先把原理吃透再根据自己任务的地形去选择才不会被loss曲线的假象骗到。

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

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

免费获取报价 →
↑