1-优化算法

1. 优化问题的基本形式

神经网络的训练目标是最小化经验风险:

其中 是模型所有可学习参数(权重矩阵和偏置), 是损失函数。

参数更新的通用形式是对 的每个分量沿着损失函数梯度的反方向做一步更新:

其中 是学习率(learning rate), 是梯度。这是一个一阶优化方法——只使用梯度的一阶信息(梯度向量)。


2. 梯度下降的统一更新框架

所有自适应学习率方法都可以写成如下统一形式:

其中:

  • 一阶矩估计(first moment),梯度的某种滑动平均,替代原始梯度
  • 二阶矩估计(second moment),梯度平方的某种滑动平均,用于归一化更新幅度
  • 是防止除零的小常数(通常
  • 具体算法由 的更新方式决定

3. 各优化算法详解

3.1 SGD(随机梯度下降)

基本形式

SGD 使用随机梯度(mini-batch 梯度)代替完整数据集的梯度:

其中 是第 个 mini-batch。

收敛性分析

使用随机梯度而非真实梯度的代价是: 是对真实梯度 有偏估计(biased estimator),方差为 。batch size 越小,梯度噪声越大,收敛越慢但可能跳出局部最优。

SGD 的收敛速度(在凸函数下)为 ,比使用真实梯度的一阶方法 慢一倍。但实践中,SGD 的泛化能力往往优于使用大 batch + 二阶方法的模型。

为什么 SGD 泛化更好

有研究指出,SGD 的噪声使参数在损失曲面上探索,而非精确收敛到平坦的极小值点。平坦(flat)的极小值点通常泛化能力更强,而 sharp 的极小值点虽然训练 loss 更低,但泛化性能差。SGD 的噪声相当于一种隐式正则化,推动模型趋向平坦区域。

实战经验

SGD 收敛较慢,需要仔细调学习率衰减(learning rate schedule)。典型配置:初始 ,每 个 epoch 乘以 SGD 是大多数视觉检测/分割任务的标准优化器(如 Detectron2、MMDetection 的检测模型多用 SGD 而非 Adam)。


3.2 Momentum(动量法)

为什么需要动量

在山谷地形中,如果梯度在不同方向上交替变化(如在狭长的峡谷中来回振荡),纯 SGD 的每一步更新都会抵消之前的部分进步,收敛极慢。Momentum 引入”速度”的概念,让更新方向带有历史惯性,从而在正确方向上加速,在振荡方向上抵消。

数学推导

设速度 初始化为 。Momentum 的更新规则是:

其中 是动量系数(momentum)。展开递推:

由于 ,可见 是过去所有梯度的指数加权滑动平均(EWMA),权重按 指数衰减。越近的梯度,权重越大; 控制记忆窗口的长度。

物理直觉

Momentum 模拟物理中的动量:参数更新类似于一个有质量的物体在损失曲面(重力场)上滚动,惯性使它不会在每个山谷震荡处停下来,而是沿着谷底滑行。 越大,惯性越强,“滚动”越平滑。

对 SGD 的改进效果

  • 加速收敛:相同 epoch 数下,动量 SGD 的 loss 通常低于普通 SGD
  • 减少振荡:在峡谷地形中,正交于峡谷方向的梯度被历史速度抵消
  • 跳出局部最优:惯性使模型有机会冲出浅的局部最优

实战经验

是几乎通用的经验值。动量累积会导致参数在后期overshoot(越过最优点的现象),通常在收敛后期配合学习率衰减使用。典型配置:SGD + Momentum () + 步衰减 (step decay)。


3.3 Nesterov Momentum

与标准动量的区别

标准 Momentum 在当前位置计算梯度,然后加上历史速度的方向做更新。Nesterov 提前一步”lookahead”:先按历史速度方向探索,再用那个位置的梯度做修正:

区别在于:标准动量的梯度在 处计算,Nesterov 的梯度在 处计算——提前使用了历史速度的方向。

为什么 Nesterov 更有效

Nesterov 的梯度包含了对”即将到来的速度”的修正。当参数即将overshoot 时,Nesterov 提前感知到梯度变化(因为已经往那个方向走了一步),并提前施加反向修正。这使得 Nesterov 比标准动量更早地稳定在极小值点附近,收敛更快、更稳定。

收敛速度的理论保证

在强凸函数下,标准 Momentum 的收敛速率是 ,而 Nesterov 可以达到 ——理论上快了整整一倍。

实战经验

Nesterov 在理论上有优势,但实践中与标准 Momentum 的差异在小批量(small batch)训练中不明显。当 batch size 较大、梯度噪声较小时,Nesterov 的优势才显著。PyTorch 的 SGD(..., nesterov=True) 实现 Nesterov 动量,使用公式:

(具体实现与上述推导等价,但形式略有不同,需注意 PyTorch 文档)


3.4 AdaGrad(Adaptive Gradient)

为什么需要自适应学习率

不同参数在训练中需要的更新幅度差异巨大:Embedding 层的梯度通常较小且稀疏,MLP 的梯度较大且密集。若使用统一学习率,某些参数更新不足(欠拟合),某些参数更新过度(振荡/发散)。

AdaGrad 的核心思想:对频繁更新的参数使用小学习率,对稀疏更新的参数使用大学习率

数学推导

AdaGrad 对每个参数维护一个累积梯度平方和

其中 是逐元素乘法, 是逐元素的学习率调整因子。

解释:若参数在历史上经常收到大的梯度,则 累加得快,归一化因子变大,学习率自动变小;若参数历史梯度小,则归一化因子小,学习率保持较大。这自动实现了”不同参数不同学习率”。

问题:梯度平方的累积导致学习率衰减

AdaGrad 的问题是 只增不减,随着训练进行,归一化因子 持续增大,学习率趋向于 0。在线学习或稀疏任务(如 NLP 的词嵌入训练)后期,模型几乎停止学习。

实战经验

AdaGrad 在稀疏数据、在线学习场景表现良好。但在深度学习(深层网络、长期训练)中几乎不用,因为训练到后期所有参数的学习率都被压到极低。若必须使用 AdaGrad,建议在深度网络中留有一定余量(不要训练到完全收敛)。


3.5 RMSProp(Root Mean Square Propagation)

解决 AdaGrad 累积问题

RMSProp 引入了指数滑动平均来替代 AdaGrad 的无界累积,从而让二阶矩估计保持”跟踪近期梯度方差”的能力,而不被历史梯度主导:

其中 控制 EMA 的窗口。类似动量中的 是近期梯度平方的 EWMA, 越大,历史记忆越长。

为什么叫 “Root Mean Square”

归一化因子 是梯度二阶矩(方差)的平方根(RMS)。RMSProp 在每一步将梯度除以 RMS,归一化后使不同参数的学习率自适应于其局部的梯度方差。

与 AdaGrad 的关键区别

AdaGrad 累积所有历史梯度平方(单调递增),而 RMSProp 用 EMA 让旧的梯度平方逐渐衰减。这意味着 RMSProp 可以适应非平稳目标(non-stationary):训练过程中损失曲面的曲率变化时,RMSProp 可以跟踪这种变化,而 AdaGrad 不行。

实战经验

是常用配置。RMSProp 适合训练过程中损失曲面曲率变化大的场景,如 RNN 训练(梯度随时间步变化剧烈)。但 RMSProp 没有动量项,通常需要配合动量使用(将动量项加到分子上)。


3.6 Adam(Adaptive Moment Estimation)

综合一阶与二阶自适应

Adam 整合了 Momentum 的一阶矩估计和 RMSProp 的二阶矩估计,同时解决两个问题:梯度方向(动量)和梯度量级(自适应学习率)。

数学推导

一阶矩估计(动量):

是梯度的 EWMA, 近似于标准动量。

二阶矩估计(自适应学习率):

是梯度平方的 EWMA, 使二阶矩跟踪长期梯度方差。

偏差修正

由于 ,在训练初期( 较小时),矩估计存在向零的偏差。例如:

因此需要进行偏差修正(bias correction)

时,,偏差修正的影响消失;在训练初期( 较小时),修正量显著。

参数更新

物理直觉

  • :梯度的方向(往哪个方向走)
  • :梯度的”能量”(步幅多大)
  • :归一化后的方向向量,模长由 控制,方向由动量决定

Adam 的优点

  1. 超参数默认效果好 在大多数任务中不需要调参即可工作
  2. 适合大规模训练:二阶矩的自适应学习率使训练稳定,大 batch 下收敛快
  3. 适合稀疏梯度:对稀疏参数(如 Embedding)的学习率自适应调整

实战经验

Adam 的默认配置几乎”开箱即用”,是快速原型实验的首选优化器。但很多实验性研究(Fudan Vision Lab 的研究等)表明,在最终部署模型的训练中,SGD + Momentum 的泛化能力通常更好,尤其在视觉分类任务上。Adam 适合在以下场景使用:(1)需要快速验证想法的初期实验;(2)模型结构复杂、用 SGD 需要仔细调学习率衰减的情形;(3)训练大模型时作为 warmup 阶段。


3.7 AdamW(Adam with Weight Decay)

问题引入:L2 正则化 vs 权重衰减

Adam 原生支持 L2 正则化,方式是在梯度上加上

然后执行标准 Adam 更新。这相当于在损失函数中加入 (L2 正则化)。

但 AdamW 论文(Loshchilov & Hutter, 2019)指出:L2 正则化 ≠ 权重衰减。两者在标准 SGD 中等价(因为 SGD 的更新天然带有 项),但在 Adam 中不等价——L2 正则化在 Adam 中被二阶矩归一化后衰减,其有效强度随参数尺度变化,不是一个恒定的正则化项。

AdamW 的修正

AdamW 的权重衰减直接作用于参数:

即在参数更新时直接减去 ,与梯度的归一化无关。权重衰减的强度是恒定的,不随参数尺度或二阶矩估计变化。

为什么 AdamW 更有效

设参数 在某方向上梯度较大,则 也较大(梯度平方的 EWMA 大),这会使该方向的 L2 正则化项(加在梯度上)被 归一化后衰减,使其效果变弱。但 AdamW 的权重衰减 与梯度无关,始终以恒定强度作用于参数,真正实现正则化目标。

AdamW 与 SGD + L2 的关系

在 SGD 中,权重衰减和 L2 正则化是等价的(因为 正则化对 求导后恰好等于 本身)。在 Adam 中,只有 AdamW 才保留了这个等价性。

实战经验

AdamW 是 Transformer 训练的标准优化器(BERT、GPT、LLaMA 等均使用 AdamW)。权重衰减参数 通常在 之间调,常见取值为 (对 Transformer 的 FFN 权重)或 (对所有参数统一设置)。


4. Adam 训练快但泛化未必最好的原因

4.1 理论分析

Adam 的自适应学习率使每个参数在训练初期就获得较大的有效学习率(因为二阶矩估计在初期较小),这导致快速收敛到某个局部最优,但这个最优未必是泛化能力最强的那个(recall:SGD 的噪声帮助跳出 sharp 的局部最优)。

SGD 在训练初期由于动量尚未累积,参数更新相对保守,在损失曲面上探索更长时间,最终可能收敛到更平坦(flat)的区域。

4.2 经验观察

  • ImageNet 分类、COCO 目标检测 等视觉任务上,SGD + Momentum 的最终测试准确率通常高于 Adam 1~3%。
  • NLP 生成模型、Transformer 上,AdamW 是标准配置,此时泛化差距不明显,可能因为:Transformer 架构本身表达能力足够强,Adam 的自适应学习率足够稳定;或者预训练任务的标签弱(语言建模),不需要 SGD 那种隐式正则化效果。
  • 小数据集、少样本学习 场景,SGD 的隐式正则化更宝贵,应优先用 SGD。

5. 任务特性与优化器适配

5.1 稀疏梯度 → Adam / AdaGrad

稀疏梯度意味着某些参数(如 Embedding)只在少数样本上更新。Adam 的二阶矩归一化自动对这些稀疏参数保持大学习率,避免更新不足。SGD + Momentum 对稀疏参数的处理不友好——稀疏参数可能因为长时间无梯度而完全”死掉”。

5.2 非平稳目标(Non-stationary Objective)→ RMSProp / Adam

非平稳目标指损失曲面的曲率随训练不断变化(如课程学习、RL 的奖励变化)。AdaGrad 的单调累积无法跟踪这种变化,RMSProp 和 Adam 的 EMA 形式可以动态跟踪,适时调整学习率。

5.3 噪声梯度 → SGD / SGD + Momentum

大 batch 训练时梯度噪声小,用 Adam 可快速收敛;小 batch 时梯度噪声大,SGD + Momentum 的噪声帮助探索,可以得到更好的泛化。实践中,batch size 从 32 降到 8 时,Adam 和 SGD 的性能差距会缩小。

5.4 特定任务的优化器偏好

任务推荐优化器理由
视觉分类(ResNet 等)SGD + Momentum泛化更好
目标检测(检测头)SGD + Momentum检测头训练通常用 SGD
Transformer / BERT / GPTAdamW权重衰减、标准配置
RNN / LSTMRMSProp / Adam非平稳梯度,二阶矩自适应
强化学习(PPO/A3C)Adam(常用 Adam)梯度噪声大但不稳定,Adam 默认配置省心
少样本学习SGD + Momentum噪声正则化珍贵
词嵌入训练AdaGrad / AdamEmbedding 稀疏,Adam 自适应学习率

6. 工程实践

6.1 优化器选择建议

选择决策流程

  1. 快速原型 / 深度实验初期 → 选 Adam / AdamW,默认超参数,通常 5~10 分钟就能看到 loss 下降
  2. 视觉分类 / 检测 / 分割 → 选 SGD + Momentum,跑完整训练 schedule
  3. Transformer / 生成模型 → 选 AdamW, 按任务调
  4. Embedding 相关的任务 → 选 Adam 或 AdaGrad
  5. 若 Adam 泛化不好 → 切换 SGD + Momentum,配合 learning rate warmup

6.2 超参数设置建议

Adam / AdamW

超参数常见取值说明
(学习率) ~ 默认 ,Transformer 常用 或更低
通常不调
通常不调;对收敛有影响时(如训练极长)可设为
通常不调;若数值不稳定(如混合精度训练)可设为
(weight decay) ~ AdamW 专用;若用 L2 正则化则效果弱于 weight decay
warmup常用 linear warmup 1000~10000 步防止初始阶段梯度过大,尤其 Transformer
schedule通常配合 cosine decay 或 constantAdam 通常不需要 decay;若衰减则用 cosine

SGD + Momentum

超参数常见取值说明
(初始学习率) ~ 通常比 Adam 大 10~100 倍;需配合 schedule
momentum 通常不调
weight decay ~ L2 正则化(与 SGD 天然等价)
schedulestep decay(每 30 epoch 乘 0.1)或 cosineSGD 必须配合衰减,Adam 通常不需要
NesterovTrue / False对 sharp 极小值有轻微帮助;通常设为 True

6.3 常见问题排查

问题 1:Loss 不下降(训练完全停滞)

诊断:学习率过小?梯度消失?

  • 检查梯度范数:若各层梯度范数 ,很可能是梯度消失。检查激活函数(是否饱和)、初始化(是否 Xavier/He)、归一化层(BatchNorm gamma 是否为 1)
  • 若梯度正常但 loss 不降:学习率可能太小;尝试 10 倍大学习率

解决方案

  • 学习率过低 → 增大学习率(Adam: ,SGD:
  • 梯度消失 → 检查激活函数和初始化;必要时换 ReLU / He 初始化
  • 参数初始化错误 → BatchNorm 的 设为 1, 设为 0

问题 2:Loss 振荡(不收敛但也不停滞)

诊断:学习率过大?Batch size 太小?

  • 观察 loss 曲线:若振荡幅度大但趋势向下(缓慢下降),学习率可能略大
  • 若振荡剧烈且无下降趋势:学习率过大或梯度爆炸

解决方案

  • 学习率略大 → 降低学习率 2~5 倍
  • Batch size 太小 → 若显存允许,增大 batch size(梯度噪声减小)
  • 启用梯度裁剪clip_grad_norm(1.0)):防止梯度爆炸
  • Adam 中若 过小(接近 0.9),二阶矩估计不稳定,改为

问题 3:Loss 发散(变为 NaN / Inf)

诊断:数值爆炸、学习率过大、损失函数数值不稳定

  • 梯度爆炸:启用梯度裁剪,torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
  • 学习率爆炸:检查学习率是否设置正确(如误将 用于 Adam)
  • Softmax/BCE 数值不稳定:检查 logits 范围;若过大(>),对 logits 做裁剪或用框架的安全实现

解决方案

  • 立即降低学习率为原来的 1/10
  • 若 loss 已经 NaN,重新初始化,用更低学习率重启
  • 混合精度训练(AMP)可以缓解某些数值问题

问题 4:训练后期停滞(Loss 降到平台后不再下降)

诊断:学习率衰减到过小?陷入局部最优?

  • 若 loss 曲线在平台期前有明显下降,然后完全水平:学习率衰减到过小,或参数进入 plateau
  • 若 loss 在平台前有振荡:可能是 sharp 极小值,学习率在 plateau 后无法推动参数跳出

解决方案

  • 学习率过早衰减 → 重训,使用更长的 warmup 或更慢的衰减(cosine decay)
  • 若确实是 plateau:使用 SGD 的噪声特性(切换到 SGD 最后一阶段);或尝试增加随机性(Dropout 增强)
  • AdamW 中 weight decay 过大 → 降低

7. 优化器选择速查表

场景推荐优化器超参数建议替代方案
快速原型 / 深度网络调参Adam / AdamW(AdamW)
视觉分类(ResNet, 分类网络)SGD + Momentum,WD=,step decaySGD + Nesterov( 等效)
目标检测(检测头)SGD + Momentum同上
Transformer / 大语言模型AdamW(GPT)或 (BERT),
RNN / LSTMAdamRMSProp + Momentum
词嵌入训练(稀疏)AdamAdaGrad(在线学习)
强化学习(PPO/A3C)Adam(PPO)~ (A3C),
少样本学习SGD + Momentum
大模型预训练(LLM/ViT)AdamW + 分布式 warmup + cosine decay

8. 常见错误配置案例

案例 1:Adam 学习率过大

错误:直接用 的 Adam(这是 SGD 的典型学习率)。

后果:Adam 的自适应学习率已经将有效学习率缩小了数个量级, 会导致参数更新爆炸,loss 在几步内变为 NaN。

正确做法:Adam 常用 (即 ),Transformer 训练可能更低到


案例 2:Adam + L2 正则化(而非 AdamW)

错误:对 Adam 使用 weight_decay 参数,实际上调用的是 L2 正则化(在梯度上加 ),而非真正的权重衰减。

后果:L2 正则化在 Adam 中被二阶矩归一化后衰减,有效正则化强度远弱于预期,无法达到期望的正则化效果。

正确做法:若使用 Adam 且需要权重衰减,使用 AdamW(torch.optim.AdamW),并设置 weight_decay=0.01


案例 3:SGD 不使用学习率衰减

错误:使用 SGD + Momentum 但保持学习率恒定。

后果:SGD 的收敛依赖于学习率逐渐减小。恒定大学习率会导致参数在极小值附近持续振荡,无法收敛到稳定点。

正确做法:配合步衰减(每 epoch 乘以 )或余弦衰减(cosine annealing)。


案例 4:RNN 中误用 SGD

错误:对 LSTM 使用 SGD without momentum。

后果:RNN 的梯度在时间步上传播,噪声大且路径长,SGD 的收敛速度极慢且极易陷入局部最优或梯度消失/爆炸。

正确做法:使用 Adam()或 RMSProp(),配合梯度裁剪。


案例 5:Adam 的 设置过小

错误:将 设为 (与 相同),认为两者应该一致。

后果 控制梯度平方的 EWMA 窗口。 意味着二阶矩估计只跟踪最近 10 步左右的梯度历史,波动剧烈,自适应学习率不稳定。

正确做法 应设为 (长期记忆)或 (极长期),不要与 混淆。


案例 6:训练 Transformer 时不做学习率 warmup

错误:直接使用 开始训练,不做 warmup。

后果:Transformer 的残差连接在训练初期可能导致信号过大(尤其 pre-norm 架构),梯度在第一层可能爆炸或消失。Warmup 让参数在训练初期以小学习率缓慢调整,避免极端梯度。

正确做法:使用 linear warmup(如 1000 步 warmup),然后用 cosine decay 或 constant。