
1. 优化器到底在解决什么问题先说句实在话很多人入门大模型训练时把注意力全放在网络结构、数据配比和loss设计上觉得优化器无非就是选个AdamW设个学习率的事。但真到训练跑起来loss不降、loss爆炸、收敛慢、泛化差追根溯源一大半都出在优化器上。优化器做的事情说白了就一句话在参数空间里决定每一步往哪个方向走、走多远。你有个loss函数它告诉你当前参数错得有多离谱但怎么从这个位置走向更低点是优化器的全部工作。大模型参数量动辄几十亿loss面高维且崎岖优化器的一丁点差异放大到几万步之后就是天壤之别。这篇文章我从最朴素的SGD开始逐个拆解EMA、Momentum、RMSProp最后落到大模型训练事实上的标配——Adam和AdamW。重点不是贴公式而是结合我在实际训练LLM过程中踩过的坑讲清楚每个优化器为什么这样设计、适合什么场景、参数怎么调才不翻车。无论你是在做微调还是从零预训练这篇都能给你一套可以直接用的选型依据。2. SGD与EMA最朴素的起点最实用的技巧2.1 SGD朴素但不可缺的基本盘随机梯度下降Stochastic Gradient Descent是所有优化器的原点。它的更新规则极其简单θ θ - η * ∇L(θ)其中η是学习率∇L是当前batch算出来的梯度。每一步直接把参数往梯度反方向挪一点。随机体现在用mini-batch采样估计完整梯度而不是把整个数据集算一遍。这个算法的问题在预训练场景下非常致命它对学习率极其敏感且更新方向抖动剧烈。mini-batch的梯度是带噪声的batch越小噪声越大。如果η设大了参数会在最优解附近来回震荡甚至发散设小了收敛慢得像蜗牛爬。而且SGD对所有参数一视同仁使用同一个学习率但不同参数在loss面上的陡峭程度完全不同这显然不合理。不过SGD并没有被淘汰。在不少CV模型微调、或者对泛化性能要求极高的场景里带momentum的SGD仍然有一席之地。它收敛出来的模型往往比Adam族更平滑——原因后面讲到Adam时细说。而且SGD对超参数的响应比较直觉化调试起来容易定位问题。2.2 EMA低成本的模型参数平滑神器EMAExponential Moving Average指数移动平均不是优化器但它跟优化器配合得极其紧密值得放在一起讲。EMA的做法是在训练过程中额外维护一份参数的滑动平均副本每个step更新θ_ema β * θ_ema (1-β) * θβ一般取0.99或0.999。训练结束后你拿θ_ema去做推理而不是用最终的θ。为什么这招有用因为训练后期参数会在最优点附近来回抖动这个抖动本身就是噪声。EMA相当于给参数轨迹做了一次平滑滤波把抖动滤掉往往能拿到更稳的验证集表现。我在实际训练中观察过同一个checkpoint用EMA权重的评估loss通常比原始权重低那么零点几个点别小看这点差距在模型融合或者比赛场景里可能就是决定性的。大模型训练框架里EMA通常作为可选开关训练时几乎不增加额外计算成本只多一份参数拷贝和一次线性加权。我最推荐的实践是预训练阶段把EMA权重用于验证集评估而checkpoint保存时保留原始权重。这样既不影响训练迭代又能在评估时收益。3. Momentum与Nesterov让更新方向有记忆3.1 Momentum给梯度下降装上惯性普通SGD最大的问题是没有记忆——每一步完全由当前梯度决定梯度一抖动方向就乱。Momentum的灵感来自物理世界引入一个速度变量v让更新方向带上历史积累的惯性v β * v ∇L θ θ - η * vβ通常取0.9。每一轮的速度v是历史梯度方向的加权平均如果历史方向一直朝某个方向走速度就越滚越大如果梯度方向频繁反转惯性会在一定程度上抵消抖动。这个设计带来的实际收益有两个。第一在梯度方向一致的平坦区域加速收敛——速度项累积起来相当于放大了有效学习率。第二在梯度方向剧烈变化的狭窄区域抑制震荡——历史速度项拉扯住突变的方向。我在训练中遇到过loss卡在平台期迟迟不动的情况把普通SGD换成momentum SGDβ0.9之后基本一两千步就能突破平台期往下走。这个体验说明momentum本质上是把只看当前升级为结合历史这在满是噪声的高维loss面上几乎是刚需。3.2 Nesterov Momentum看得更远一步Nesterov是momentum的一个改良版思路是先按当前速度方向预冲一步再在该位置算梯度θ_lookahead θ - η * β * v v β * v ∇L(θ_lookahead) θ θ - η * v翻译成人话普通momentum是先看当前位置的梯度再按速度走Nesterov是先按速度冲出去看看冲出去那个位置的梯度再决定怎么走。因为预冲了一步Nesterov对梯度变化更敏感尤其在接近最优点需要刹车时它比普通momentum更快感知到前方要减速。实际使用中Nesterov的收敛速度确实比标准momentum略快但这个优势在Adam出现后基本被覆盖了。现在你几乎只在一些偏学术的框架和传统CV微调代码里见到它。理解它的核心价值倒不必抠性能差异而是帮你建立优化器可以预见性地决策这个思维模型。4. RMSProp自适应学习率的转折点4.1 从Adagrad到RMSProp解决学习率一视同仁的问题SGD家族无论怎么加momentum始终有一个死穴所有参数共用同一个学习率。但真实情况是不同参数维度上梯度量级可能差几个数量级。有些参数一直拿到很小的梯度学习率太小就永远挪不动有些参数梯度爆炸学习率太大又直接飞掉。Adagrad是第一个尝试解决这个问题的算法它对每个参数维护梯度平方的累积和除以这个累积值来归一化学习率。思路是对的但致命缺陷在于累积和单调递增、永不衰减导致学习率不断缩小训练到后期直接学不动了。RMSProp的改进非常优雅把累积和换成滑动平均用指数衰减的方式跟踪最近的梯度平方量级E[g²] β * E[g²] (1-β) * g² θ θ - η / sqrt(E[g²] ε) * gβ默认0.9ε取1e-8左右防止除零。这样每个参数都有自己最近一段时间的梯度大小的估计梯度大的参数步子自动缩窄梯度小的参数步子自动放宽而且这个估计是动态跟进的不会像Adagrad那样越走越死。4.2 RMSProp在实践中的表现RMSProp在非凸优化问题里表现相当好对冲浪状loss面有很强的适应能力。我早期练过一个图像分类模型用momentum SGD调了半天学习率都不理想换RMSProp之后几乎不用怎么调就稳定收敛了。原因就在于它免去了人为给不同参数设定学习率的麻烦。不过RMSProp有一个要注意的坑它对β比较敏感。β太小梯度平方的估计过于近视失去平滑作用β太大估计跟不上梯度突变会导致训练后期学习率失真。实测下来0.9到0.99区间问题不大超过0.995在小batch训练时容易出问题。另外RMSProp没有momentum那样的方向记忆在梯度方向不稳定的初期loss曲线会比momentum类更毛糙。5. Adam与AdamW大模型训练的默认答案5.1 Adam的原理与偏见修正AdamAdaptive Moment Estimation把momentum和RMSProp合体了同时维护梯度一阶矩均值代表方向和二阶矩方差代表量级。一阶矩用β1控制二阶矩用β2控制m β1 * m (1-β1) * g # 一阶矩方向记忆 v β2 * v (1-β2) * g² # 二阶矩梯度量级 m_hat m / (1-β1^t) # 偏差修正 v_hat v / (1-β2^t) θ θ - η * m_hat / (sqrt(v_hat) ε)t是当前step数。为什么要做偏差修正因为m和v初始化为0训练刚开始时移动平均被严重拉向零直接使用会导致每一步更新被错误缩小。偏差修正把早期step的估计拉回到无偏状态这一步极其关键——很多人自己手写Adam没做修正训练出来的loss曲线前半段明显不自然。Adam的优秀之处在于方向上有momentum的平滑尺度上有RMSProp的自适应同时偏差修正保证了冷启动阶段也能正确走步。这些特性让Adam对学习率的鲁棒性远超SGD——即使学习率设得偏大一点二阶矩归一化会自动限制实际步长不太容易在几步之内爆炸。5.2 AdamW解耦权重衰减为什么更优AdamW是当前大模型训练的事实标准跟Adam的核心区别在于如何看待权重衰减。传统Adam做L2正则的方式是在梯度里加上一项λ*θ即把权重衰减混进梯度再参与一阶矩和二阶矩的计算。问题在于自适应优化器会不规则地缩放梯度导致L2正则项也被缩放最终实际权重衰减的量级跟名义上的λ对不上。这在大模型场景尤其致命因为权重衰减对泛化性能影响显著不精确的衰减等于白调。AdamW的思路是把权重衰减从梯度计算中剥离出来直接在参数更新时做乘法衰减θ θ - η * (m_hat / (sqrt(v_hat) ε) λ * θ)看到区别了吗L2在Adam里是先加进梯度再归一化AdamW是归一化之外单独衰减。后者保证了无论自适应缩放因子多大权重衰减的实际效果都和λ严格线性相关。实际训练LLM时这个区别直接反映在验证集困惑度和最终下游任务分数上。我做过对比实验相同batch size、相同学习率下AdamW的收敛曲线和最终指标普遍优于Adam尤其在训练后期Adam的过拟合信号出现得更早。5.3 LLM训练场景的AdamW参数配置大模型预训练/微调的AdamW参数业界默认值大概是这样的参数默认值我的经验和说明学习率1e-4 ~ 3e-4预训练常用1e-4级别微调用3e-4左右起步β10.9一阶矩衰减基本不用动β20.95预训练/ 0.999默认预训练用0.95能让二阶矩更灵敏快速适应梯度变化εeps1e-8注意fp16/bf16训练可能需要调整到1e-6附近weight decay0.01 ~ 0.1常见0.01越大的模型有时用0.1这里有个容易忽略的点fp16混合精度下eps太小可能导致数值不稳定。因为fp16的最小可表示精度有限二阶矩v_hat如果非常小除以sqrt(v_hat)ε时可能放大浮点误差。我遇到过几次loss突然出现NaN的情况排查到最后就是eps设太小梯度被截断到很小时除零导致的。6. 实际选型与参数调优LLM训练的正确打开方式6.1 五个优化器的横向对比先上一张对比表方便你按场景直接选优化器自适应学习率方向记忆权重衰减方式大模型适用度主要坑点SGD无可选momentum直接L2/衰减不推荐学习率极敏感SGDMomentum无有直接L2勉强调参成本高RMSProp有无直接L2不推荐β敏感Adam有有L2混入梯度可用衰减不精确AdamW有有解耦衰减强烈推荐ε数值稳定性选型逻辑很简单做LLM预训练无脑AdamW。如果是少量数据的任务微调、或者调参空间极其充裕、确信自己能把SGD调好那SGDmomentum的泛化性偶尔有惊喜但不建议新手折腾。RMSProp更多是作为理解自适应优化器的中间步骤存在生产环境里很少独挑大梁。6.2 学习率策略warmup与cosine衰减的配合优化器选好只是第一步真正的技巧在学习率怎么用。大模型训练几乎标配两段式学习率调度第一段是warmup。训练前几百到几千步学习率从接近0线性爬升到目标值。为什么需要这个因为模型刚初始化时参数状态很差梯度方向信息噪声极大这时候直接上大学习率容易把参数推到危险区域。warmup给了参数一个稳定下来再加速的空间。第二段是cosine衰减。学习率按余弦曲线从峰值逐步降到接近0。这背后的直觉是训练前期参数离最优点远可以大步走后期靠近最优点步子必须收窄否则会在最优解周围来回震荡损失精度。我常用的组合是warmup占总step数的1%~3%cosine衰减到峰值的十分之一左右配合AdamW的β20.95。这套组合在多个规模从几千万到数十亿参数的模型上都验证过稳定性和最终loss表现都很好。6.3 一个实操案例从零预训练时的优化器配置拿我之前做的一个从零预训练项目举例参数量大约10亿具体配置如下优化器AdamW学习率峰值1.5e-4warmup步数2000步总step约10万β1 0.9β2 0.95eps 1e-6weight decay 0.1学习率调度cosine衰减最终学习率1.5e-5这个配置在训练过程中loss前1万步快速下降中段稳定下探后段没有出现明显的loss尖峰或者发散。对比另一个用默认Adamβ20.999weight decay0.01跑的对照组同step数下验证集困惑度低了约3%。差距不大但稳定可复现这说明细节参数的累积效应在长训练中确实会放大。7. 常见问题与排查实录7.1 Loss突然变成NaN这是大模型训练最头疼的问题之一。按优先级排查顺序整理如下可疑原因排查手段解决方案学习率过高看NaN出现前的loss曲线是否急剧拉升降低峰值学习率或增强warmup梯度范数过大查看log里的grad norm是否持续增长加梯度裁剪max_grad_norm设为1.0ε数值不稳定fp16/bf16混合精度下eps过小将eps从1e-8调到1e-6到1e-4β2过小导致二阶矩失真β2低于0.9时v估计太近视恢复到0.95以上数据中有脏值检查batch的loss是否单点异常清洗数据或增加样本过滤我在实践中遇到最多的是第三种——混合精度下eps问题。你盯着梯度裁剪调了半天最后一查是eps过小导致除零放大那种感觉真的想摔键盘。7.2 Loss降得很慢或者直接卡住如果训练前几百步loss几乎不动先别急着换优化器。按这个顺序检查第一确认学习率真的生效了。很多人会在warmup阶段就下结论说不收敛其实warmup本身学习率就很小耐心等它爬完。第二检查数据顺序如果一个batch里数据分布差异过大梯度方向会被互相抵消建议打乱数据后重新训练。第三尝试增大batch size——大batch能压低梯度噪声让优化器的方向记忆更稳定。第四真正需要换优化器的信号是warmup结束、学习率到达峰值后loss曲线仍然一条直线——这时候把AdamW的β2调低到0.95或者检查weight decay是否设得过大把有效更新压制住了。7.3 训练正常但验证集表现差这是优化器选型对了但细节没对的典型症状。最常见的原因是weight decay设太小导致过拟合。我见过很多人用LLM微调weight decay照抄论文里的0.01但自己数据集只有几万条训练却有几十个epoch——这必然过拟合。这时候把weight decay提到0.1结合EMA评估验证集分数往往立竿见影。另一个容易被忽略的点是权重衰减对embedding层和大输出层的影响。有些实践会把部分层设置为不衰减但实际上embedding是典型的会被权重衰减压过头的位置如果embedding的梯度量级本身就很小再去衰减它相当于把embedding往零推——对训练不利。在实践中我倾向于全参数统一weight decay但单独调低embedding层的衰减系数到正常的十分之一。7.4 一张速查表优化器选择与参数设定最后整理一份速查表覆盖几个主流场景直接照着抄场景推荐优化器学习率关键参数LLM从零预训练AdamW1e-4~2e-4β20.95wd0.1cosinewarmup对话模型微调AdamW2e-5~5e-5β20.999wd0.01线性/余弦均可图像分类迁移SGDMomentum1e-2~1e-3momentum0.9wd1e-4小数据微调AdamW1e-5起步重点防过拟合EMA加持这套表是我反复横跳测试后的浓缩结果。注意微调和预训练的学习率差距可能接近一个数量级——预训练用1e-4没问题微调直接用1e-4经常炸原因在于预训练已经把参数磨得比较平滑微调阶段一点扰动就可能破坏已有信息。8. 一点个人心得把优化器从SGD一路捋到AdamW你会发现每个优化器都是在解决前一个的遗留问题SGD没有记忆Momentum补上记忆SGD没有自适应RMSProp补上自适应Adam把两者合并AdamW修正了合并后暴露出来的正则化失真。这条演进路线本身就是理解优化器最好的框架。实操层面我想强调一个态度不要追求用什么优化器最牛而是搞清楚当前问题卡在哪一环。loss不降先查学习率和数据loss爆炸先查数值稳定性泛化差先查weight decay和EMA——照着这个思路排查比盲目换优化器高效得多。我自己早期犯过的错误就是频繁切换优化器最后发现问题根本不在优化器而在学习率调度白白浪费了训练时间和计算资源。如果你刚开始接触大模型训练建议先把AdamW跑通一个不错的baseline再逐项调参感受每个参数的影响。这套顺序走完你对优化器的理解会比只看十篇原理文章都扎实。