首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
深度学习优化算法全解:从梯度下降到Adam及调参实战
📅 2026/10/18 13:04:14
✍️ 爱科研究院
👁 阅读 3,247
相信不少人在训练深度学习模型时都遇到过这种情况loss曲线像心电图一样上下狂跳或者收敛到一半死活下不去又或者一个不小心就冒出NaN然后整个实验白跑。遇到这些问题很多人第一反应是模型结构写得不对或者数据预处理出了问题。但往往检查了半天发现错在一个更基础、更容易被忽略的环节——优化算法的选择与参数配置。这一篇“动手学深度学习”系列的内容我打算把深度学习优化算法这件事完整地梳理一遍从最朴素的梯度下降讲到形形色色的改进版本再结合我自己调参时踩过的坑把原理和实战放在一起说清楚。不管你是刚入门的学生还是已经跑过几个项目的研究人员这篇内容都能帮你少走不少弯路。1. 优化算法全景图先看清我们手里有哪些牌1.1 为什么训练离不开“优化算法”这个角色要理解优化算法存在的意义先得明白训练神经网络到底在做什么。简单来说我们有一堆参数权重和偏置有一个损失函数来量化预测值和真实值差得多远训练过程就是不断寻找一组参数让损失函数的值尽可能小。这件事在数学上是一个典型的无约束优化问题只不过自变量的维度特别高动辄百万、千万级别而且函数形状极其复杂没法用解析方法直接求解。优化算法的本质就是回答一个问题已知当前参数点下一步该往哪个方向走、走多大步。方向决定了模型能不能找到更好的参数区域步长决定了收敛速度和最终精度。如果方向选错模型可能在某个局部区域来回震荡如果步长太大可能直接跨过最优区域甚至导致loss爆炸如果步长太小训练会慢到让人怀疑人生。有人可能会说为什么不直接用二阶方法比如牛顿法或拟牛顿法那样收敛不是更快吗。理论上确实如此但在深度学习中参数量通常上千万二阶方法需要计算海森矩阵或其近似存储和计算开销完全承受不起。梯度下降类的算法只需要计算损失对每个参数的偏导数也就是梯度计算量可控得多而且配合梯度累积、分布式训练等技术能很好地扩展到大规模模型。所以业界实际上走的路线是用一阶梯度信息加上各种“启发式”的修正策略让更新过程既稳又快。这一篇要把“优化算法”当作主题其实也是在提醒一个问题训练模型时大部分人把注意力放在网络结构、损失函数、数据增强上但优化器本身怎么选、参数怎么配同样在很大程度上决定了一个模型到底是能跑出漂亮的结果还是停在原地空转。1.2 一张直觉地图从批量梯度到自适应学习率优化算法家族里主流演进路线大体是这样的先从最原始的批量梯度下降出发然后出现随机梯度下降再后来有了动量机制接着又出现了自适应学习率的一派最终汇流成我们现在最常用的那些优化器。批量梯度下降BGD是最朴素的想法它用整个训练集算一次损失函数的梯度然后沿负梯度方向更新一次。这种方法的优点是每次更新方向都比较准确缺点是计算量太大数据集稍微大一点就跑不动而且它只有一个固定的学习率在复杂损失曲面上表现不佳。随机梯度下降SGD的出现解决了批量梯度下降计算量大的问题。SGD每次只用一个样本的梯度来更新参数计算开销瞬间降下来但由于单样本梯度有随机性更新路线很抖收敛过程中会来回震荡。后来大家发现用一个小批量的样本来计算梯度mini-batch SGD是个折中方案既比单样本稳定很多又比全批量高效很多于是mini-batch SGD成了最通用的基础方案。那之后改进方向大致分两条线。一条线在“方向”上做文章代表人物就是动量Momentum和Nesterov加速梯度NAG。它们模仿物理世界里小球滚下坡的惯性把历史梯度的累积方向叠加到当前更新中这样能有效压制震荡帮助参数冲过平坦区域和鞍点。另一条线在“步长”上做文章代表人物是AdaGrad、RMSProp。它们根据不同参数的历史梯度大小自动调节每个参数的学习率让频繁更新的参数步子小一点让稀疏更新的参数步子大一点。Adam可以看作是两条线的集大成者它既引入了一阶动量类似Momentum的累积方向又引入二阶动量类似RMSProp的自适应步长还加上了偏差校正机制让训练前期数值更稳定。后来又有AdamW把权重衰减和动量更新解耦彻底解决了Adam在正则化方面的一些隐性问题。整条演进路线其实是逐步在回答“怎么在复杂的高维损失曲面里更快更稳地求最小值”这个问题。1.3 选型思路不同任务配不同的优化器既然优化器这么多那具体选哪个合适我的经验是不能只看名气要看任务背景、模型规模和可训练的预算。对于计算机视觉任务比如图像分类、目标检测CNN结构配合SGD加动量momentum设为0.9依然是经典且稳健的组合。SGD虽然收敛速度不如Adam这类自适应方法但它的泛化能力往往更好最终测试集精度有望更高。很多人初学时觉得Adam丢上去就完事了但在CV任务里SGD动量有时候能多出一个点的精度这点差距在模型竞赛里可能就是决定性因素。对于自然语言处理任务特别是Transformer结构AdamW基本上是标配。Transformer的训练对学习率波动极其敏感AdamW的自适应步长能稳住更新过程而解耦的权重衰减方式参数更可控。Vision TransformerViT这类把Transformer结构搬到视觉领域的模型通常也沿用AdamW。对于超大模型的预训练阶段比如动辄几十亿、上百亿参数的大语言模型常规的单卡优化器也扛不住了需要专门的分布式优化策略比如LAMB、LARS这类把学习率和各层参数规模解耦的优化器。它们做的事情本质上还是“自适应步长”只不过更进一步把步长的尺度跟模型层的规模接上了头。所以选型没有一套万能公式。我的习惯是先看项目里最主流的框架和文章默认用什么在这些“被验证过”的配置上开始实验。2. 核心算法逐层拆解每个参数更新背后的原因2.1 从BGD到SGD用“噪声”换速度先展开讲讲从BGD到SGD这个步骤因为这个转变是整个优化算法演进中最关键的一次跳跃。BGD的更新公式是w w - lr * grad_full这里grad_full是全体样本梯度的平均值。这样做方向很可靠但每次迭代都扫一遍全量数据训练一轮的成本高得惊人。如果你用GPU训练一个现代神经网络用全批量梯度下降几乎是不现实的。SGD的思路是从梯度计算这个最大的开销上动刀子每次只随机抽一个样本用这个样本的梯度来近似全体梯度。w w - lr * grad_sample。这样做更新一次的成本极低但问题也随之而来——单个样本会引入很大的梯度方差参数轨迹非常崎岖。这个崎岖倒也不完全是坏事因为引入的随机噪声在优化过程中有一种类似“随机扰动”的正则化作用神经网络在纯SGD下训练出来的结果有时泛化性能反而比全批量更好。这就是所谓“噪声换速度”的一种平衡。而mini-batch SGD是中间态每次取一个batch的样本比如32个或128个计算batch内的梯度均值。这样梯度方差比单样本低很多方向更稳定计算开销又远小于全batch。深度学习中实际说的SGD默认指的就是mini-batch版。batch size的大小对这个过程影响非常大。batch比较小时更新方向噪声大但每个step的耗时短迭代次数多模型可能探索到更平坦、更通用的极值区域batch比较大时梯度估计更准确训练曲线更平滑但每一步耗时更长而且容易陷入尖锐极值泛化能力不一定占优。所以很多大batch训练都伴随学习率等比例的放大或余弦调度目的就是抵消大batch带来的泛化劣势。2.2 动量机制给梯度一个“惯性”单纯靠SGD还有一个让人头疼的毛病就是沿着峡谷状的损失函数表面来回震荡。想象一下一个窄而深的峡谷水平方向上梯度很小垂直方向上梯度很大普通SGD会在峡谷壁上左右弹跳前进速度却极慢。更麻烦的是深度学习损失函数里非常多的“鞍点”在这些地方所有方向上的梯度都趋近于零普通SGD会像断电的机器人一样僵在原地。动量机制Momentum的解决办法是维护一个速度变量v每次更新时把历史速度乘上一个衰减系数典型值0.9再加上当前梯度然后沿着更新后的速度方向走。对应公式为v momentum * v gradw w - lr * v。用生活类比来说这就好比滑下坡的雪球就算遇到一段平地它也会因为惯性继续往前滚不至于立刻停下来。这个“惯性”可以有效压制梯度方向的频繁反向震荡同时帮助参数更坚定地越过鞍点。Nesterov加速梯度NAG是在动量基础上再做一步“前瞻”。它先按照当前速度估算出位置更新后的近似位置在那个位置上计算梯度再结合当前速度做最终更新。Nesterov动量在凸优化理论上有更好的收敛边界在实际神经网络训练中它跟标准动量的差距有时候没那么大但在某些问题上确实更稳、更快。如果做CV训练时发现标准Momentum收敛偏慢我会试试NAG这个对比测试的成本很低。2.3 自适应学习率AdaGrad和RMSProp的迭代逻辑动量是在“速度方向”上做文章而自适应学习率的一派盯住的是“每个参数的步长”。为什么要分参数处理步长因为不同参数的梯度量级是不一样的。比如一个稀疏特征对应的权重它只在很少的样本里被更新另一个密集特征对应的权重则几乎每个batch都在更新。用一个全局学习率前者学习得太慢后者又可能震荡。如果能让稀疏参数获得较大的有效步长、密集参数获得较小的有效步长那优化效率会高很多。AdaGrad是第一个里程碑式的自适应方法。它记录每个参数历史梯度的平方和然后更新时把这个平方和开根号放到分母上w w - lr / sqrt(G) * grad。它的逻辑是如果一个参数的历史梯度很大说明它更新频繁有效步长就该自动缩小梯度稀疏的参数历史累积量小有效步长就大。问题也很明显平方和只会越来越大分母单调递增导致有效步长越来越小训练后期几乎学不动。这相当于一个人走到后半程越走越没劲最后僵在原地。RMSProp对AdaGrad做了一个关键修改改用“指数滑动平均”来统计历史梯度的平方而不是简单累加。E[g^2] rho * E[g^2] (1 - rho) * g^2。这样过去很远的历史只保留一个很小的权重不会无限累积有效步长就不会单调递减到零。这相当于给记忆加了一个滑动窗口更符合非平稳环境的优化需求。实际上RMSProp里的更新公式已经非常接近现代优化器的内核了。只不过RMSProp缺少“动量方向”的累积。Adam的出现等于把RMSProp的自适应步长和Momentum的惯性方向做了统一结合。2.4 Adam与AdamW一阶、二阶矩估计和权重衰减解耦Adam全称是Adaptive Moment Estimation它维护了两个指数滑动平均变量一个是梯度的一阶矩估计m用于累积方向一个是梯度的二阶矩估计v用于调节步长。公式看起来比SGD复杂不少但拆开看并不恐怖m beta1 * m (1 - beta1) * gradv beta2 * v (1 - beta2) * grad^2。Adam有一个普通SGD没有的步骤——偏差校正。因为在训练刚开始时m和v都是从0开始累计的早期值会比真实值偏小很多直接除会造成更新步长异常偏大。所以Adam在正式更新前先做一次校正m_hat m / (1 - beta1^t)v_hat v / (1 - beta2^t)其中t是迭代步数。这一步在点击量上看似不起眼但对训练初期的稳定性影响非常大。AdamW则处理了一个深层问题。传统Adam在做权重衰减时直接在最终的梯度里加上weight_decay * w这一项然后再做自适应步长缩放。问题在于Adam里每一步实际有效步长是不一样的同样的惩罚项在不同参数上被缩放了不同倍数这让正则化的作用变得不可控。AdamW的思路是把权重衰减直接从梯度里拿出去不参与自适应步长的缩放而是在参数更新之后单独执行一个衰减操作w w - lr * wd * w。这样正则化和优化器的动态步长就完全解耦了实际使用中AdamW几乎全面替代了Adam尤其是在NLP和Transformer类模型中效果更稳。很多人可能不明白为什么这样一个看起来不算大的改动会带来训练结果上的显著差异。我理解的关键在于解耦让超参数weight_decay有了更清晰、更稳定的语义——它在不同学习率、不同训练阶段下都能保持一致的相对强度。而对于带自适应步长的优化器来说语义清晰的超参数是调出好模型的前提。3. 参数配置与调参实战纸上谈兵之外的门道3.1 学习率怎么定范围测试与三层经验法则学习率可以说是深度学习里最敏感的一个超参数。同一个模型学习率差一个数量级结果可能是收敛爆炸和稳步下降的天壤之别。我看到很多人只用默认的1e-3当学习率跑不动就换优化器实际上问题可能在学习率上。想认真定学习率可以用“学习率范围测试”这个方法。做法很简单让学习率从一个很小的值比如1e-5开始每步迭代逐渐增大一直到1e-1左右记录下每一步的loss值最后画出一条loss随学习率变化的曲线。你会看到曲线至少有一个阶段loss在明显下降这个阶段对应的学习率区间就是模型最敏感也最合适的范围。常见的经验是把曲线下降最陡峭那个点对应的学习率再除以3到10作为正式训练用的初始学习率。关于学习率还有一套“三层经验法则”我整理如下第一层初始化阶段用上文范围测试选出的值作为起始学习率通常在1e-4到3e-3之间。第二层中期训练阶段如果需要更精细控制可以结合学习率调度器比如训练到总步数30%或50%时按余弦规律逐步调低。第三层后期收尾阶段当loss下降到平台期可以手动把学习率再缩小10倍继续训练几个epoch通常能榨出最后的几个点精度。3.2 beta、epsilon、weight_decay藏在默认值里的门道配置优化器时大部分人只关注学习率其他参数全用默认值。这当然没问题因为那些默认值经过千锤百炼覆盖面很广。但如果你想追求更好的效果这些参数是值得花时间研究的。先看beta1和beta2。beta1控制一阶动量速度方向的衰减默认0.9对大多数任务都稳。beta2控制二阶动量自适应步长的衰减默认0.999但这个默认值在部分场景下反而会导致有效步长过小或者训练后期难以收尾。比如训练NLP模型时如果想增加权重衰减的作用很多人会把beta2调到0.95或0.98。这个调整的作用是让二阶矩估计更快地吸收近期梯度变化而不是被非常久的梯度历史拖住。再看epsilon这个数值是为了防止分母除0加的一个极小量。默认值是1e-8但在使用混合精度训练时如果梯度出现很小的变化默认epsilon在低精度下可能失效导致更新异常这时经验上可以把epsilon调到1e-6甚至1e-4。别看它小在数值稳定性上是很关键的一环。最后是weight_decay。这个参数在SGD和AdamW中的语义完全不同。SGD中的weight_decay直接作用于梯度通常设置1e-4到5e-4AdamW中因为解耦了权重衰减经验设置可以在0.01到0.1的范围。很多从SGD迁移到AdamW的人仍然沿用1e-4的权重衰减系数结果会发现正则化几乎不起作用这就是不理解参数语义导致的误用。3.3 学习率调度器不只要在代码里引入还要理解调度节奏有了合适的初始学习率不代表整个训练过程都该用同一个学习率。训练初期模型权重的随机初始化状态离最优还很远这时需要相对较大的步长快速进入一个有希望的区域训练后期参数已经落到一个较优区域这时还用大步长来回震荡会错过精细的极小值。所以学习率调度器的本质是在探索期保持合适的学习率在精细调整期逐步降低步长。我最常用的两个调度器一个是StepLR分段衰减一个是CosineAnnealingLR余弦退火。StepLR的思路很直观每隔一定epoch数就把学习率乘以一个衰减因子比如每30个epoch衰减为原来的0.1倍。它的缺点是衰减节点选择很凭经验衰减太早会拖慢收敛衰减太晚模型又可能一直在最优附近震荡。CosineAnnealingLR则采用了一个连续的余弦曲线让学习率从初始值平滑地衰减到设定的最小值。这种平滑方式不需要硬切衰减节点训练过程更顺滑在不少CV和NLP任务中表现都很好。Transformer类模型还常用warmup decay的组合。warmup是指在训练最开始的一小段步数内学习率从0或很小的值逐渐线性增加到预设的最大值。原因在于Transformer初始化状态下的参数分布比较特殊如果开局就直接用较大学习率很容易把训练带崩。warmup步数通常设定为总步数的5%到10%然后接余弦退火衰减。3.4 常用优化器推荐配置表下面这张表是我在实际项目中常用的配置起点不一定是最优解但作为基线是靠谱的。如果你在写自己的代码可以考虑直接从这里开始再微调。任务类型常用优化器初始学习率关键参数备注CV分类CNNSGD Momentum0.01~0.1momentum0.9, weight_decay1e-4配合Cosine退火效果更佳CV检测/分割SGD Momentum0.001~0.01momentum0.9, weight_decay5e-4学习率通常比分类任务略低NLPTransformerAdamW1e-5~3e-5beta20.98, weight_decay0.01~0.1必须配warmupViT类视觉模型AdamW1e-4~3e-4weight_decay0.05~0.3需要较长的warmup生成对抗网络GANAdam1e-4~2e-4beta10.5~0.9判别器学习率通常比生成器略高提示所有推荐数值仅供参考实际训练时务必把“验证集指标”作为判断标准而不是只看训练loss降得有多快。4. 训练现场的常见问题与排查实录4.1 loss震荡不降问题可能不在模型而在“更新节奏”这是我碰见过最频繁的问题。模型结构照着论文抄、数据加载没问题但loss曲线像锯齿一样来回弹而且长时间没有下降趋势。有一次我检查了一天代码最后发现罪魁祸首只是学习率设成了0.01对那个模型来说实在太大了。loss震荡不降优先考虑几个方向。第一学习率太高。梯度方向来回反转自然会出现震荡现象最简单的做法是把学习率除以10再试一次。第二batch size太小。当每个batch只装8个或者16个样本时梯度噪声太大模型很难沿着稳定方向前进可以试试把batch size调大。第三数据本身没有做好标准化。不同特征的数值范围差异太大会让梯度分布失衡模型更新时有的参数动得太快、有的动得太慢。最直接的办法是对训练数据做归一化或标准化让所有特征落在相似的数值尺度上。还有一个小细节容易被忽略就是随机种子不固定。同一个模型、同样的学习率种子不同可能跑出来的loss曲线略有差异但差异不至于非常夸张。如果跑出来曲线差异大到离谱那基本可以确定是有数据泄露或者梯度更新逻辑写错了。4.2 收敛很快但泛化差警惕“优化成功”与“泛化失败”另一种常见情况是训练集loss下降得很漂亮但验证集指标一直上不去典型的过拟合信号。很多人第一反应是加数据增强、加正则化这些都对但优化器这一侧也有值得调整的地方。我之前在一个图像分类项目里SGD与普通Adam对比SGD收敛略慢但最终测试集精度高了一个多点。这里面有一个大家经常讨论的现象自适应优化器虽然能快速降低训练loss但它倾向于收敛到参数空间里那些更尖锐的极值点这些点对输入扰动和参数扰动都非常敏感泛化性自然就差。而SGD加动量轨迹更随机反而更容易“冲”到比较平缓的极值区域。平缓极值在测试集上的表现通常更稳定。所以如果发现训练集收敛极快、但验证集一般不妨先换掉自适应优化器用带动量的SGD跑同样的epoch数很多时候会有惊喜。如果确实需要保留AdamW带来的快速收敛那可以通过更强的数据增强、更大的weight_decay来抑制过拟合并配合EMA指数移动平均来平滑参数也能在验证集上捞回一些精度。4.3 训练中途NAN一个老问题的几个新诱因训练到某个epoch突然loss变成NaN是让所有人都很崩溃的问题。但这类问题排查起来方向通常比较明确。首先看学习率是否设置过大这在零基础时最容易遇到。损失值一下子变成NaN十有八九是数值溢出了把学习率调小问题往往立刻消失。其次要看模型中是否出现了除零或者根号下负数之类的运算。Adam、RMSProp这类算法在分母上会加上一个epsilon如果epsilon设置得太小或者梯度平方和长时间为0就可能出现数值问题。混合精度训练下epsilon更敏感调大到1e-6通常能解决。还有就是输入数据本身带了NaN或无穷大。这个问题挺隐蔽的尤其在处理文本或视频数据时某个样本里漏了一个异常值模型一碰到那个样本梯度就爆炸。排查办法很简单在数据加载器里加一个断言检查mini-batch里有没有非有限值。要是发现“训练到固定epoch就NaN”就很可能是某一条特定数据引起的。4.4 一张排查速查表整理一个排查清单下次训练出异常可以先过一遍。现象首要检查项次要检查项参考调整方向loss完全不下降学习率是否过小输出层是否有nan调大学习率检查梯度是否消失loss震荡剧烈学习率是否过大batch size是否过小调小学习率增大batch size训练集收敛但验证集差优化器是否自适应过强是否缺少数据增强换SGDMomentum加大weight_decay中途loss变成NaN学习率是否爆炸batch内是否有异常数据调小学习率调大epsilon清理数据训练后期loss停住学习率是否过大是否缺少调度器接入Cosine退火或手动调小学习率5. 我的几点实操体会与建议聊到这儿关于深度学习优化算法的核心内容差不多讲完了最后说几点我自己的主观体会。第一点优化器没有绝对意义上的“好坏”只有“合不合适”。我在项目中见过太多人无脑上Adam也见过有人因为某篇文章用了SGD就迷信SGD。更合理的做法是针对你的数据规模和模型结构至少对比一到两种优化器用同样的训练轮数在验证集上做对比。这个对比实验的时间成本并不高却能避免你在错误的优化器上浪费时间。第二点学习率和调度策略永远值得优先调。就算你选对了优化器学习率不对依然是白搭。我个人的调参顺序是先用范围测试确定合理学习率区间再选定一个优化器配warmup衰减策略训练几个epoch看趋势最后再根据验证集表现微调weight_decay和其他参数。这套流程下来大部分模型都能在一个可控的时间内达到不错的水平。第三点也是我最想强调的一点记录每一次实验的超参数配置。哪怕只是在本地起一个训练脚本也建议顺手把优化器类型、学习率、调度器、batch size等写进实验日志里。很多时候模型效果好了你却说不清是哪个参数起了作用这种“不可复现的成功”对后续工作毫无价值。我个人在实作中几乎所有复杂模型最后都会回到“一个合理的基线设置 一个明确想验证的变量”这种实验思路。优化算法是很底层的配置但它和后处理、损失函数、模型结构一样都是左右最终结果的环节。切忌把优化器看作一个“填上默认值就不管”的选项它是你调试模型的工具箱里最常用、也最值得了解的一把扳手。
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/18 13:04:14
Kitematic 0.17.11 for Mac:Docker 图形化入门跳板
2026/10/18 12:59:12
AHA-CNN-LSTM-Attention客流预测模型(Matlab实现)
2026/10/18 12:59:12
长序列预测新利器Informer:原理、实践与避坑指南
2026/10/18 13:59:19
DVWA暴力破解实战:从靶场练习到企业级认证加固
2026/10/18 13:59:19
AI电商落地实战:从客服到选品,把重复劳动省下的时间变利润
2026/10/18 13:59:19
易语言远控源码实现:主控、被控与协议设计全解析
2026/10/18 13:59:19
Axure浏览器调试插件原理与实战避坑指南
2026/10/18 13:59:19
程序写完了,怎么发给用户?Windows 打包工具怎么选
2026/10/18 13:54:18
Rust泛型编程实战:编写类型安全的通用算法库
2026/10/18 0:02:43
OpenResearch实战:Claude Code、Codex、OpenCode、Cursor 工作流搭建与故障排查
2026/10/18 0:02:43
知识管理核弹:用Obsidian构建第二大脑的工程化方案(TaoToken 统一 Key 接入版)
2026/10/18 0:02:43
金融AI落地指南:从调研报告到技术选型与工程实践
2026/10/18 0:02:43
OpenResearch实战:Claude Code、Codex、OpenCode、Cursor 工作流搭建与故障排查
2026/10/18 0:02:43
知识管理核弹:用Obsidian构建第二大脑的工程化方案(TaoToken 统一 Key 接入版)
2026/10/18 0:02:43
金融AI落地指南:从调研报告到技术选型与工程实践
2026/10/17 10:15:50
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/16 18:46:48
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/16 18:46:46
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)