AI概念与词典

深度学习优化器是什么?SGD、AdamW、Muon 选择与调参指南

优化器读取反向传播得到的梯度和内部状态,再按规则更新模型参数;它不保证找到全局最优。本文用训练闭环、选择矩阵和PyTorch代码讲清SGD、AdamW、Adafactor、Muon、学习率、显存与排障。

从前向传播、损失、反向传播到优化器更新参数的闭环,并标出梯度、学习率和优化器状态
本页目录
  1. 优化器到底更新了什么?
  2. SGD、Momentum、Adam 与 AdamW 有什么区别?
  3. 2026 年应该直接改用 Muon 吗?
  4. 怎样在 PyTorch 中正确建立最小基线?
  5. 参数组为什么经常比“换算法”更重要?
  6. 怎样验证 checkpoint 真正可恢复?
  7. 混合精度、显存和 ZeRO 与优化器是什么关系?
  8. 优化器应该怎样选择?
  9. 训练不收敛时,按什么顺序排查?
  10. 常见问题
  11. AdamW 一定比 Adam 好吗?
  12. 用了自适应优化器还需要学习率吗?
  13. fused 或 foreach 会改变算法吗?
  14. 什么时候这篇文章需要再次复核?
  15. 可复制的实验验收单

先给答案:深度学习优化器(optimizer)接收反向传播计算出的梯度,并结合学习率、动量或历史梯度统计量,决定下一步怎样更新可训练参数。它负责“怎样走下一步”,但不负责定义训练目标,也不保证找到全局最优解。损失函数、数据、模型、批大小、精度、调度器和随机性都会共同影响结果。

深度学习训练从前向传播到优化器更新参数的闭环
优化器只处理更新规则;梯度来自反向传播,目标来自损失函数,学习率调度器通常在优化器之外改变步长。

优化器到底更新了什么?

设模型参数为 θ,第 t 步在一个小批次上得到损失 L 和梯度 gt=∇θL。最简单的随机梯度下降可以写成 θt+1t−ηgt,其中 η 是学习率。真实框架还要处理参数组、动量缓冲区、权重衰减、稀疏梯度和数值精度。

训练环节 产生或保存的对象 优化器是否负责 常见误解
前向传播 预测与中间激活 换优化器不会改变模型前向结构
计算损失 一个可求导的标量目标 优化器不能修复错误的标签或目标函数
反向传播 每个参数的梯度 loss.backward() 计算梯度,不更新参数
参数更新 新参数与优化器状态 optimizer.step() 才执行更新
学习率变化 下一步使用的学习率 部分 通常由独立 scheduler 驱动,调用顺序需要按文档确认

如果你还不熟悉目标函数,可先看站内的损失函数说明;学习率的单独定义见学习率词典页。PyTorch 官方的 torch.optim 文档明确给出的基本顺序是清梯度、前向、计算损失、反向、更新。

SGD、Momentum、Adam 与 AdamW 有什么区别?

SGD 使用当前小批次梯度更新参数;加入 Momentum 后,会保存过去梯度的指数累积,使持续一致的方向积累速度。PyTorch 的 SGD API同时暴露 momentum、dampening、weight_decay 和 nesterov,因此“SGD”并不等于只有一个固定配置。

AdaGrad按参数累积历史平方梯度,稀疏特征可能从这种逐参数缩放中受益,但累积量持续增长会压低有效步长。RMSprop用平方梯度的移动平均替代无限累积。Adam进一步同时维护梯度的一阶矩和平方梯度的二阶原始矩,并在早期做偏差修正;算法定义应以 Adam 原论文和框架实现为准,而不是把它概括成“自动找到最优学习率”。

AdamW把权重衰减从梯度更新中解耦。原论文指出,对自适应梯度算法而言,L2 正则与传统 weight decay 并不等价;这正是 Decoupled Weight Decay要解决的问题。PyTorch 的 AdamW API也明确说明权重衰减不会累积进动量和方差。站内另有Adam 专题页,本页不重复制造同意图内容。

方法 额外状态 值得优先测试的场景 不能直接下的结论
SGD 无;Momentum 版增加一份动量 建立朴素基线;已有成熟训练配方 不能脱离调度、批大小和训练预算宣称泛化更好
AdaGrad / SparseAdam 逐参数统计量 真正的稀疏梯度或稀疏嵌入 输入稀疏不等于梯度张量满足稀疏实现要求
Adam 通常为一阶、二阶矩 需要快速建立稳定基线 自适应缩放不等于不需要调学习率
AdamW 通常为一阶、二阶矩 需要解耦 weight decay 的 Transformer 配方 名称相同不代表不同框架默认值和内核一致
Adafactor 可对矩阵状态做因子分解 优化器状态内存是主要约束时 省状态不等于在你的模型上更快或更准
Muon 动量及正交化相关计算 二维隐藏层权重且愿意做严格对照实验 不应直接用于偏置、嵌入等全部参数

2026 年应该直接改用 Muon 吗?

不能只按热度切换。当前 PyTorch 稳定文档已经列出 Muon,但接口说明同时限定:Muon 面向神经网络隐藏层的二维参数,偏置、嵌入以及其他参数应使用 AdamW 等标准方法。这意味着实际代码通常要先按参数形状和用途分组,而不是把 model.parameters() 全部交给 Muon。

Muon 不是“AdamW 的无参数替换”。它对二维隐藏层权重的动量矩阵执行 Newton–Schulz 正交化,而非二维参数仍要走 AdamW/Adam 等路径,因此通常是混合优化器方案。不同参数路径可以需要不同学习率;只有把两边的参数组、学习率、衰减、调度和状态保存清楚,比较才可解释。

从 AdamW 试验 Muon 前 必须确认 失败时优先回退什么
参数分组 只把符合实现要求的二维隐藏层权重交给 Muon;偏置、归一化、嵌入和输出头单独处理 输出每组参数名、形状与数量,先消除漏加/重复
优化器配方 Muon 与 AdamW 分别搜索学习率;固定数据顺序、token 数、batch、精度、调度和停止条件 退回已验证 AdamW 基线,而不是沿用同一学习率下结论
分布式支持 核对框架版本、ZeRO 阶段、梯度是否被提前展平、checkpoint 与 offload 支持 先在单机/小规模恢复测试通过,再扩大集群
收益口径 同时测达到目标质量的 token、墙钟时间、吞吐、峰值显存和失败恢复 不把单个 benchmark 或状态缓冲区减少外推成总训练收益

PyTorch 团队 2026 年 6 月 3 日发布的 DeepSpeed Muon 实现说明解释了为何展平梯度会妨碍矩阵正交化,并在当时列出 ZeRO Stage 2/3 支持以及仍在推进的 CPU offload 等项目。该文给出的质量和显存数字来自指定模型、数据、GPU、精度和 ZeRO 配置,只能作为实现样例,不能写成 Muon 对所有训练任务的固定提升。上线前应按实际安装版本重新查支持矩阵。

同样,PyTorch Adafactor 文档描述的是“次线性内存成本”的自适应方法,但是否节省端到端峰值显存,还取决于参数形状、梯度、激活、混合精度主权重和框架实现。正确问题不是“哪个最新”,而是“在相同数据顺序、token 数、硬件、精度和停止条件下,哪个达到目标质量所需的总时间与资源更可接受”。

深度学习优化器选择的四道决策门
先判断梯度与参数结构,再看显存和成熟配方,最后用同预算实验决策;算法热度不能替代证据。

怎样在 PyTorch 中正确建立最小基线?

import torch

model = MyModel().cuda()
optimizer = torch.optim.AdamW(
    model.parameters(),
    lr=3e-4,
    betas=(0.9, 0.999),
    weight_decay=0.01,
)

for inputs, targets in loader:
    optimizer.zero_grad(set_to_none=True)
    outputs = model(inputs.cuda())
    loss = loss_fn(outputs, targets.cuda())
    loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
    optimizer.step()

这段代码只是可审查的起点,不是通用最佳参数。zero_grad 文档提醒,梯度为 None 和梯度为 0 时,优化器行为可能不同;clip_grad_norm_返回总梯度范数,适合同时记录而不是盲目裁剪。恢复训练时还要保存并恢复模型、优化器、调度器、步数和随机状态。

参数组为什么经常比“换算法”更重要?

一个模型不一定只能使用一组超参数。PyTorch 允许把不同参数字典交给同一个优化器,例如为预训练骨干设置较小学习率、为新分类头设置较大学习率,或把偏置与归一化参数放入 weight_decay=0 的组。分组必须基于明确规则并输出参数名清单;如果同一参数被遗漏、重复加入,或者被冻结参数仍留在实验假设中,结果就无法解释。

微调时还应区分“冻结参数”和“梯度恰好为零”:前者通常不参与优化,后者可能仍会受到动量或衰减状态影响。解冻层后新增参数组、改变组顺序或更名,也会影响旧 checkpoint 的状态映射。正式训练前应保存每组的参数数量、名称模式、学习率、衰减、betas 和可训练状态,并在恢复后逐项核对。

怎样验证 checkpoint 真正可恢复?

不要等训练中断后才验证。可在短跑中保存一次 checkpoint,记录保存前的全局步数、学习率、优化器状态键、梯度缩放值与下一批次 loss;重新启动后继续两到三步,检查学习率曲线和 loss 是否连续。只加载模型权重而遗漏 optimizer 或 scheduler,会把“续训”变成使用旧权重重新起步,尤其会丢失 AdamW 的矩估计和 warmup 位置。

PyTorch 的保存与加载教程要求续训 checkpoint 同时保存模型和优化器状态;若还使用 scheduler、AMP scaler、采样器或梯度累积,也要保存其状态和全局步数。Optimizer.load_state_dict 还提醒,应先初始化学习率调度器,再加载优化器状态,否则加载的学习率可能被覆盖。参数组顺序、数量或模型结构改变时,不能仅以“没有抛异常”判断恢复成功。

更严格的恢复测试是做分叉对照:在同一 checkpoint 处,一条进程不中断继续运行 N 步,另一条完全退出后恢复 N 步;两边使用相同下一批数据和随机状态,比较学习率、loss、梯度范数、参数摘要与优化器状态摘要。分布式训练还要核对每个 rank 的分片和采样进度。数值内核可能带来允许范围内的小差异,但突然回到 warmup 起点、状态数变少或参数组错位必须视为恢复失败。

学习率调度不是 AdamW 的隐藏功能。PyTorch 的 学习率调整说明指出,多数 scheduler 应在优化器更新后调用;但按指标变化的调度器需要传入验证指标。应把 warmup 步数、峰值学习率、衰减曲线和总训练步数一起写入实验记录。

混合精度、显存和 ZeRO 与优化器是什么关系?

混合精度下,梯度缩放由 AMP 的 scaler 协调,不应写成“优化器原生支持 FP16 就自动防止下溢”。PyTorch 的 AMP 示例展示了 scaler.scale(loss).backward()、必要时先 unscale_ 再裁剪,以及 scaler.step(optimizer) 的顺序。不同 dtype、设备和算子支持范围也要单独确认。

Adam 类方法通常要为参数保存一阶、二阶矩,训练还可能保留更高精度主权重;但不能脱离 dtype 和实现给出固定“参数量的几倍”。峰值显存应拆成参数、梯度、优化器状态、激活、临时缓冲和通信桶逐项测量。站内的ZeRO 显存优化说明可继续阅读状态分片。

DeepSpeed 官方 ZeRO 教程把阶段边界写得很清楚:Stage 1 分片优化器状态,Stage 2 再分片梯度,Stage 3 再分片参数。它改变的是状态放置与通信,不会把 AdamW 的数学规则自动变成另一种优化器;offload 还会引入 CPU、NVMe 和互连瓶颈。

观测项 至少记录什么 发现异常后先查什么
训练目标 训练/验证 loss、任务指标、token 或样本数 数据与损失实现,再看优化器
更新尺度 实际学习率、梯度范数、参数范数、裁剪比例 warmup、累积步数、batch scaling
数值稳定 NaN/Inf、scaler scale、跳过更新次数 AMP 顺序、异常 batch、溢出算子
资源 峰值显存、step time、吞吐、通信等待 foreach/fused、状态分片、激活与通信桶
恢复能力 断点前后 step、学习率、loss 连续性 optimizer/scheduler/scaler 是否一起恢复

优化器应该怎样选择?

  1. 先复制可信配方:同一模型家族和训练目标已有官方训练配置时,先复现它,而不是一次更换优化器、学习率、批大小和数据。
  2. 建立 AdamW 或成熟 SGD 基线:固定数据版本、随机种子集合、训练 token/样本预算、精度、硬件与停止规则。
  3. 只改变一个因素:比较优化器时,分别搜索合理学习率;拿 AdamW 的最优学习率直接套给 SGD 或 Muon,不是公平对照。
  4. 同时比较质量和成本:记录达到同一验证指标所需的 wall-clock、GPU 时、峰值显存和失败率,而不是只看前几百步 loss。
  5. 至少复现实验:随机性较强时运行多个种子,报告中位数、离散程度和异常运行;没有原始日志就不要写“提升百分之多少”。
约束或目标 首轮候选 必须控制的变量
成熟 Transformer 微调配方 AdamW 学习率、weight decay、warmup、有效 batch
经典视觉配方已有 SGD 基准 SGD+Momentum 与 AdamW 对照 各自调度与训练时长,不能共用单一学习率
优化器状态导致 OOM Adafactor、ZeRO-1/2、offload 吞吐损失、通信、CPU/NVMe 带宽和恢复
稀疏嵌入梯度 SparseAdam 或支持稀疏参数的配方 梯度布局与算子支持,不只看输入稀疏度
评估 Muon Muon 处理合适二维权重,AdamW 处理其余参数 参数分组、正交化成本、相同 token 与质量目标

训练不收敛时,按什么顺序排查?

  1. 用一个极小数据子集确认模型能够过拟合;做不到时先检查标签、掩码、损失和梯度链路。
  2. 打印可训练参数数量,确认冻结、参数组和 weight decay 排除规则符合预期。
  3. 记录每步实际学习率、loss、梯度范数、是否出现 NaN/Inf,以及 AMP 是否跳过更新。
  4. 暂时关闭复杂调度、梯度累积、分布式和编译优化,建立单卡 FP32 或 BF16 的可解释基线。
  5. 验证 checkpoint 恢复:恢复后的 step、scheduler、optimizer state 与 scaler 必须连续。
  6. 最后才更换优化器;否则可能用算法变化掩盖数据或实现错误。

梯度长期接近零时,还可以结合站内的梯度消失说明检查网络与激活;框架接口和设备差异可参考PyTorch 指南。这些问题与“哪个优化器最强”不是同一个搜索意图。

常见问题

AdamW 一定比 Adam 好吗?

不能无条件断言。AdamW 明确解耦了 weight decay,通常更容易把衰减作为独立超参数管理;最终质量仍取决于任务、实现、调参与预算。报告结果时应写明框架版本和完整参数。

用了自适应优化器还需要学习率吗?

需要。Adam/AdamW 对各参数做自适应缩放,但全局学习率仍控制更新的总体尺度,warmup 和衰减策略也可能显著改变训练轨迹。

fused 或 foreach 会改变算法吗?

它们主要是实现路径。PyTorch 的 优化器总览区分 for-loop、foreach 和 fused,并给出不同设备的支持与稳定状态。速度和峰值显存需在目标版本与硬件上实测,数值也可能因运算顺序产生细小差异。

什么时候这篇文章需要再次复核?

PyTorch 稳定版更改算法默认实现、Muon/Adafactor 参数边界变化、DeepSpeed 调整 ZeRO 状态语义,或站内代码无法在当前稳定版运行时,都应重新核验。本文资料复核日期为 2026 年 7 月 16 日。

可复制的实验验收单

  • 模型、数据快照、代码提交、依赖、硬件、dtype 与随机种子可追溯;
  • 优化器参数组、学习率、调度、batch、累积、裁剪和 weight decay 完整保存;
  • 训练/验证曲线、梯度范数、吞吐、峰值显存、异常和中断均有原始日志;
  • 比较采用相同数据与预算,并为不同优化器分别搜索合理学习率;
  • 断点恢复后 optimizer、scheduler、scaler 和全局步数连续;
  • 只有可复现实验才写定量提升;否则使用“候选”“需要验证”等边界语言。

编辑复核记录:本文于 2026 年 7 月 16 日依据 PyTorch 稳定文档、Adam/AdamW 原论文、DeepSpeed ZeRO 文档及 PyTorch/DeepSpeed Muon 当前实现说明复核;新增 Muon 混合参数组、分布式支持边界和 checkpoint 分叉恢复验证。没有把厂商或项目单次 benchmark 写成全局排名,也没有声称本站完成相同规模实测。

结论:优化器不是模型训练的自动驾驶仪,而是一条有状态的参数更新规则。先证明数据、损失和梯度正确,再用成熟配方建立基线;只有在相同质量目标、训练预算、软件版本和资源口径下,SGD、AdamW、Adafactor 或 Muon 的比较才有意义,也才值得写入生产决策记录。