Optimization Algorithm
优化算法会在训练过程中更新模型权重,以最小化损失。涵盖梯度下降、动量、Adam、AdamW、Muon 和相关代码。
优化算法(简称优化器)是训练过程用来调整模型参数、以降低损失函数的规则。在深度学习中,优化器会从反向传播中接收损失相对于每个模型权重的梯度,并决定每个权重移动的距离和方向。优化器与学习率共同决定训练收敛的速度、稳定性、内存需求,以及最终模型的泛化能力。
优化器的工作原理#
几乎所有深度学习优化器都是梯度下降的变体:计算损失在一个小批量上的梯度 g,然后让权重沿其反方向迈出一小步,w ← w − η·g。优化器的区别在于迈步前如何处理 g。动量方法会对一段时间内的梯度求平均,以便沿持续一致的方向加速。自适应方法会用梯度大小的运行估计值来缩放每个参数的步长。Muon 会对每个权重矩阵的整体更新进行正交化。二阶方法还会利用曲率,使每一步的依据更充分,但计算成本也高得多。无需梯度的方法(例如进化算法和随机搜索)会通过尝试候选方案并保留最佳方案来进行优化:
当损失曲面条件不佳、某些方向曲率陡峭而另一些方向平缓时,更新规则就尤为重要。从同一起点运行三个优化器,观察它们在狭长谷地中的表现,就能看出差异:
import torch
# A long, narrow valley: f(w) = w1^2 + 50 * w2^2, with its minimum at (0, 0)
scale = torch.tensor([1.0, 50.0])
optimizers = {
"SGD": lambda p: torch.optim.SGD(p, lr=0.015),
"SGD + momentum": lambda p: torch.optim.SGD(p, lr=0.015, momentum=0.9),
"Adam": lambda p: torch.optim.Adam(p, lr=0.1),
}
for name, make_optimizer in optimizers.items():
w = torch.tensor([5.0, 1.0], requires_grad=True)
optimizer = make_optimizer([w])
# Same loss and starting point for every optimizer; only the update rule differs
for step in range(100):
loss = (scale * w**2).sum()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"{name:15s} f(w) after 100 steps: {(scale * w**2).sum().item():.6f}")普通 SGD 会停在 0.056531,因为陡峭的 w2 方向限制了学习率:任何高于 0.02 的学习率都会让 w2 每一步的过冲幅度进一步增大,而学习率为 0.021 时,100 步内损失就会升至约 95 亿。在这个限制下,沿平缓的 w1 方向进展缓慢。动量通过沿 w1 方向加速,将结果降至 0.000216;Adam 则为每个坐标设置各自的步长,将结果降至 0.001953。
常见优化算法#
- 随机梯度下降(SGD):沿小批量梯度的反方向迈步。使用 0.9 的动量时,它曾用于训练大多数经典卷积网络,并且每个参数只需额外存储一个值。
- AdaGrad 和 RMSProp:根据每个参数的梯度平方历史记录来缩放其步长。AdaGrad 用梯度平方的累积和的平方根作除数;由于累积和只会增大,它的步长会在整个训练过程中不断缩小。RMSProp 则使用指数衰减平均值,因此步长能够灵活调整。
- Adam:结合动量与 RMSProp 式缩放,并对两个运行平均值的零初始值进行校正。它的默认设置——学习率 0.001、β1 = 0.9、β2 = 0.999——适用于许多问题。
- AdamW:采用解耦权重衰减的 Adam,它会直接缩小权重,而不是通过自适应梯度缩放来实现。Transformer和大语言模型(LLM)的标准优化器就是 AdamW。
- Muon:通过 Newton–Schulz 迭代对每个二维权重矩阵的动量更新进行正交化,并为每个参数保留一个状态缓冲区。Moonshot AI 已将其扩展到 LLM 预训练。
- L-BFGS:一种拟牛顿方法,根据近期梯度构建曲率估计。它在平滑的全批量问题上能以较少步数收敛,但小批量梯度噪声使它不适合大型网络。
PyTorch 的优化器包实现了所有这些优化器,包括 torch.optim.Muon,还提供可与其中任意优化器配合使用的学习率调度器。
优化器与相关术语的区别#
- 损失函数:优化器要最小化的目标,例如分类中的交叉熵或回归中的均方误差。
- 学习率调度器:在任何优化器的基础上,通过预热、阶梯衰减或余弦退火等方式,在训练过程中调整步长 η。
- 超参数调优:对优化器、学习率和批量大小等设置进行外层搜索,每个候选设置都需要完整或部分训练一次。贝叶斯优化和进化搜索等无梯度方法可以完成这项工作,因为验证分数无法对优化器之类的选择求导。
如何选择优化器#
优化器和学习率需要一起选择,因为每种优化器都有各自适用的范围:带动量的 SGD 通常将学习率设在 0.01 到 0.1 之间,Adam 系列优化器则通常设在 0.001 左右。Ultralytics YOLO 训练会自动做出选择:默认的 optimizer="auto" 会忽略 lr0,对于迭代次数不超过 10,000 次的训练,会选择根据类别数量调整学习率的 AdamW;对于更长的训练计划,则选择 MuSGD,即用于训练已发布的 YOLO26 检查点的 SGD 与 Muon 混合优化器;而指定优化器名称时,lr0 会生效:
from ultralytics import YOLO
# 加载预训练的 YOLO26n 模型
model = YOLO("yolo26n.pt")
# 显式选择 SGD;只有当优化器不是 "auto" 时,lr0 才会生效
results = model.train(data="coco8.yaml", epochs=5, optimizer="SGD", lr0=0.01)使用 optimizer="SGD" 时,训练器还会启用 Nesterov 动量,并使用 momentum 参数作为系数;该参数默认值为 0.937。










