> For the complete documentation index, see [llms.txt](https://yeasy.gitbook.io/llm_internals/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yeasy.gitbook.io/llm_internals/di-er-bu-fen-xun-lian-pian/06_training_techniques/6.1_loss_optimizer.md).

# 6.1 损失函数与优化器：为什么选择 Adam

Transformer 训练中最常用的损失函数是**交叉熵损失**（Cross-Entropy Loss）。本节从它出发，一直走到把这个标量变成参数更新的那一端：SGD 差在哪里、Adam 补上了什么、AdamW 又改了 Adam 的哪一处，以及 AdamW 这个“默认”近来为什么开始被 Muon 动摇。第五章停在“15 万亿词元”这样的数据规模上，但同一批词元交给不同的优化器，收敛到的并不是同一个模型。学习率本身随训练进程如何变化不在本节，见 6.2 节。

可运行的梯度核对见 [A.6 实验一](/llm_internals/di-si-bu-fen-mo-xing-yu-qian-yan-pian/appendix/a6_practice_path.md)：用同一组矩阵对照手算、自动微分与有限差分，再观察一次参数更新。

## 6.1.1 交叉熵损失

对于一个分类问题（语言模型的每步预测本质上就是在词汇表中分类），交叉熵衡量的是模型预测分布 $\hat{p}$ 与真实分布 $p$ 之间的差异：

$$\mathcal{L} = -\sum\_{c=1}^{n\_{\text{vocab}}} p(c) \log \hat{p}(c)$$

在语言建模中，真实分布是独热的（正确词元概率为 1，其余为 0），因此简化为：

$$\mathcal{L} = -\log \hat{p}(x\_{\text{true}})$$

直觉上，交叉熵惩罚的是 **“对正确答案分配的概率太低”**——模型越不确定正确答案，损失越大。

**对 logits 的梯度只有一行。** 反向传播真正用到的不是上面这个标量，而是它对 LM head 输出 $z$ 的导数。设 $\hat{p} = \operatorname{softmax}(z)$、$y$ 为独热标签，代入 Softmax 的导数 $\partial \hat p\_i/\partial z\_j = \hat p\_i(\delta\_{ij} - \hat p\_j)$ 可得：

$$\frac{\partial \mathcal{L}}{\partial z\_i} = \hat{p}\_i - y\_i$$

形状上，这一步是 `logits[B, T, n_vocab] → dlogits[B, T, n_vocab]`（符号沿用 [5.1 节](/llm_internals/di-er-bu-fen-xun-lian-pian/05_pretraining/5.1_autoregressive.md)：`B` 是批大小、`T` 是序列长度、`n_vocab` 是词表大小），逐格相减即可：正确词元那一格减 1，其余各格保持自己的概率。整条反向链条的第一环就是这样一个不含指数、不含对数的差值，数值上极其稳定；不稳定发生在它前面那一步，即算 $\hat p$ 时的指数，实现上一律先减去每行最大值再取指数。

**训练第一步的损失应当约等于 $\ln n\_{\text{vocab}}$。** 随机初始化时模型对词表里每个词元给出近似相等的概率 $1/n\_{\text{vocab}}$，于是 $\mathcal{L} \approx -\log(1/n\_{\text{vocab}}) = \ln n\_{\text{vocab}}$，几个常见词表的锚点见 [5.1 节](/llm_internals/di-er-bu-fen-xun-lian-pian/05_pretraining/5.1_autoregressive.md)的表 5-1。这里要补的是偏离方向怎么读：首步损失明显低于这个值，通常意味着标签泄漏或数据管线把输入和目标对错了位；明显高于它，则说明初始化或 logits 缩放有问题。

### 困惑度：交叉熵的“人话”版本

**困惑度**（Perplexity，PPL）是衡量语言模型好坏最常用的指标，本质就是对每词元平均交叉熵取指数：

$$\text{PPL} = \exp!\left(\frac{1}{N}\sum\_{i=1}^{N} -\log \hat{p}(x\_i)\right) = \exp(\mathcal{L})$$

它可以直观理解为模型在每一步“等效地在多少个候选词元之间犹豫”——PPL=1 表示完全确定，PPL=10 表示平均纠结于约 10 个等概率选项。代几个数：`L = 3.0 → PPL = 20.09`，`L = 2.0 → 7.39`，`L = 1.8 → 6.05`。注意指数的放大效应：损失从 2.0 降到 1.8 只动了 0.2，困惑度却降了 18%。

但要特别注意：**PPL 依赖于分词方式**——词表与切分粒度不同的两个模型，其困惑度不可直接比较。跨模型评测因此常改用与分词无关的 **bits-per-byte**（BPB）：

$$\text{BPB} = \frac{\mathcal{L}}{\ln 2}\cdot\frac{\text{词元数}}{\text{字节数}}$$

第一项把 nats 换成 bits，第二项把“每词元”换成“每字节”。同一份文本上，若某分词器平均每词元覆盖 4.2 个字节，则 `L = 2.0` 对应 `BPB = 2.0 / 0.693 / 4.2 = 0.687`。分词器越“贪”，每词元的损失越高，但除以字节数之后两边可比。

**标签平滑**（Label Smoothing）把真实标签从硬性的 \[0, 0, ..., 1, ..., 0] 软化为均匀分布与 one-hot 标签的混合：正确类概率为 $1-\epsilon+\epsilon/n\_{\text{vocab}}$，其他类为 $\epsilon/n\_{\text{vocab}}$。原始 Transformer 取 $\epsilon\_{ls} = 0.1$，并直言这一项**损害困惑度**（模型被迫变得不那么确定），换来的是 BLEU 和准确率的提升。当代 LLM 预训练一般不用它：PaLM 明确写明损失是全部词元对数概率的平均、不含标签平滑。原因与它的收益方向有关——预训练的评测口径就是困惑度本身，而下游用法（采样、对齐）也不需要一个被人为抹平的分布。

**损失层是显存的一个隐形大户。** logits 的形状是 `[B, T, n_vocab]`，它与 $d\_{\text{model}}$ 无关，只由批量、序列长度和词表决定。取 `B = 8, T = 8192, n_vocab = 128256`，这个张量有 84.1 亿个数：bf16 下 16.8 GB，fp32 下 33.6 GB，已经超过多数中间层的激活（6.4.3 会给出整层的激活账）。减少这一峰值，可以按词元分块执行词表投影和损失，或用融合内核把 `矩阵乘 → logsumexp → 取标签项` 合成一遍。普通 [F.cross\_entropy](https://docs.pytorch.org/docs/stable/generated/torch.nn.functional.cross_entropy.html) 接收已经生成的 logits，不会自动融合前面的词表投影；先生成完整 logits 再分块计算损失，并没有消除这个大张量。其中 `ignore_index` 用来跳过填充位置（惯例取 −100），`reduction` 决定是求和还是求平均——6.3.4 会说明在梯度累积下这个选择为什么不能随手定。

## 6.1.2 SGD 的局限

随机梯度下降（SGD）是最基本的优化算法：$\theta \leftarrow \theta - \eta \nabla\_\theta \mathcal{L}$。它在卷积网络上一直工作得很好，在 Transformer 上却明显吃亏。问题不在于“损失地形复杂”这种对任何深网都成立的说法，而在于**梯度噪声的分布形状在两类模型上不一样**。

[一项对比研究直接量了这件事](https://arxiv.org/abs/1912.03194)：把一个小批量的梯度噪声看成高维向量，估计其分布的尾指数 $\hat\alpha$（$\hat\alpha = 2$ 对应高斯，越小尾巴越重、方差越发散）。ImageNet 上训练 ResNet 得到 $\hat\alpha = 1.99$，几乎就是高斯；BERT 预训练得到 $\hat\alpha = 1.08$，是明显的重尾。同一篇工作还给出了反向证据：在 ImageNet + ResNet-50 上，SGD 的验证准确率 0.754 高于 Adam 的 0.716——**噪声集中时 SGD 反而更好**。

重尾意味着什么，可以一步推出来。SGD 的单步位移正比于梯度本身，因此一次罕见的大梯度会原样变成一次大更新；尾巴越重，这种罕见事件越频繁。Adam 把更新除以 $\sqrt{\hat v}$，减弱了更新对梯度绝对尺度的依赖，但实际步长仍由一阶矩、二阶矩和当前梯度共同决定，并不以 $\eta$ 为硬上限。梯度裁剪进一步限制异常梯度进入这些状态的幅度，见 6.3.2。

还有一层原因来自各参数块之间的**尺度差异**：嵌入表、注意力投影、归一化增益工作在完全不同的量级上，而 SGD 只有一个全局 $\eta$，它对某一块合适就对另一块过大或过小。PaLM 用带“参数缩放”的 Adafactor，理由正是这个——它把学习率按参数矩阵自身的均方根缩放，于是在不同尺度上工作的参数矩阵（嵌入、归一化增益）不会被按同一比例压低学习率。6.2 节讲到 μP 时会看到，这条尺度问题在模型变宽时还会继续恶化：标准参数化下调小全局学习率压住了 logits，词嵌入就几乎学不动。

## 6.1.3 Adam 优化器：自适应学习率

**Adam**（Adaptive Moment Estimation，Kingma & Ba，2015）通过维护梯度的一阶矩（均值）和二阶矩（未中心化方差）的指数移动平均来解决上述问题：

$$m\_t = \beta\_1 m\_{t-1} + (1 - \beta\_1) g\_t \quad \text{（一阶矩估计）}$$ $$v\_t = \beta\_2 v\_{t-1} + (1 - \beta\_2) g\_t^2 \quad \text{（二阶矩估计）}$$

由于 $m\_t$ 和 $v\_t$ 初始化为零，在训练初期会产生有偏估计。为此，Adam 引入了**偏差修正**：

$$\hat{m}\_t = \frac{m\_t}{1 - \beta\_1^t} \quad \text{（修正一阶矩）}$$ $$\hat{v}\_t = \frac{v\_t}{1 - \beta\_2^t} \quad \text{（修正二阶矩）}$$

参数更新规则为：

$$\theta\_t = \theta\_{t-1} - \eta \frac{\hat{m}\_t}{\sqrt{\hat{v}\_t} + \epsilon}$$

这里 $t$ 是时间步数（从 1 开始），$\eta$ 是学习率，$\epsilon$ 是数值稳定性项。

**把前两步算出来。** 取当代 LLM 的常见配置 $\beta\_1 = 0.9$、$\beta\_2 = 0.95$、$\eta = 3\times10^{-4}$、$\epsilon = 10^{-8}$，看某一个参数连续两步的梯度 $g\_1 = 0.02$、$g\_2 = -0.01$。

第 1 步：$m\_1 = 0.1 \times 0.02 = 0.002$，$v\_1 = 0.05 \times 0.02^2 = 2\times10^{-5}$。偏差修正 $\hat m\_1 = 0.002/(1-0.9) = 0.02$，$\hat v\_1 = 2\times10^{-5}/(1-0.95) = 4\times10^{-4}$，$\sqrt{\hat v\_1} = 0.02$。于是比值恰为 1，更新量 $= 3\times10^{-4} \times 1 = 3.0\times10^{-4}$。

第 2 步：$m\_2 = 0.9\times0.002 + 0.1\times(-0.01) = 8\times10^{-4}$，$v\_2 = 0.95\times2\times10^{-5} + 0.05\times10^{-4} = 2.4\times10^{-5}$。修正后 $\hat m\_2 = 8\times10^{-4}/(1-0.81) = 4.211\times10^{-3}$，$\hat v\_2 = 2.4\times10^{-5}/(1-0.9025) = 2.462\times10^{-4}$，$\sqrt{\hat v\_2} = 0.01569$，比值 0.2684，更新量 $= 8.05\times10^{-5}$。梯度反号，一阶矩被抵消掉大半，步子自动缩小到约 0.27 倍。

这两步给出两条后面反复要用的结论。

**其一，学习率给出更新的基准尺度，不是位移上限。** 忽略 $\epsilon$ 且 $g\_1\ne0$ 时，首步的比值绝对值等于 1；但后续的 $\hat m\_t$ 与 $\hat v\_t$ 使用不同的历史权重，不能保证 $|\hat m\_t|\le\sqrt{\hat v\_t}$。沿用上面的 $\beta\_1$、$\beta\_2$，让前 999 步梯度都为 1，第 1,000 步变为 2，代入 [Adam 更新公式](https://docs.pytorch.org/docs/stable/generated/torch.optim.Adam.html)得到当步位移约为 $1.0258\eta$，已经超过 $\eta$。监控真正的更新量，需要同时看 $\eta\hat m\_t/(\sqrt{\hat v\_t}+\epsilon)$；使用 AdamW 时还要计入权重衰减。

**其二，全部历史梯度按同一正常数缩放时，Adam 的更新近似不变。** 把上面两步的梯度同乘 10（$g\_1 = 0.2$、$g\_2 = -0.1$），$\hat m$ 与 $\sqrt{\hat v}$ 同比放大；忽略 $\epsilon$ 后更新量不变，保留它则只在分母远大于 $\epsilon$ 时近似成立。这个前提不适用于只缩放当前一步的梯度裁剪：已有的 $m$、$v$ 没有同比变化，裁剪会同时改变当步更新和后续状态，见 6.3.2。

**$\beta\_2$ 决定二阶矩看多长的历史。** 指数移动平均的有效窗口约为 $1/(1-\beta\_2)$ 步：

| $\beta\_2$ | 0.999 | 0.99 | 0.98 | 0.95 | 0.9 |
| ---------- | ----: | ---: | ---: | ---: | --: |
| 有效窗口（步）    |  1000 |  100 |   50 |   20 |  10 |

表 6-1：二阶矩的指数移动平均看多长的历史。窗口越短，$v$ 对梯度分布的突变反应越快，代价是估计噪声更大。

原始 Transformer 取 $\beta\_2 = 0.98$、$\epsilon = 10^{-9}$，对应 50 步的窗口。当代 LLM 预训练普遍压到 $\beta\_2 = 0.95$（20 步），GPT-3 与 DeepSeek-V3 都写明了这个值，见 6.1.4 的表 6-3。取短窗的理由是大规模训练中梯度的尺度会随数据配比、批量和课程阶段变化，$v$ 必须跟得上；代价是 $v$ 本身更抖。PaLM 走的是另一条路，让 $\beta\_2 = 1 - k^{-0.8}$ 随步数 $k$ 变化，理由是罕见词元的嵌入在短窗口里估不准二阶矩。

**$\epsilon$ 有两个截然不同的工作区间。** 当 $\sqrt{\hat v} \gg \epsilon$ 时，它可以忽略，更新与梯度尺度无关，即上面那两条结论成立的区间。当 $\sqrt{\hat v} \ll \epsilon$ 时，更新退化为 $\eta\hat m/\epsilon$，即一个学习率为 $\eta/\epsilon$ 的动量 SGD；梯度长期极小的参数就落在这一侧。$\epsilon$ 能取多小还受实现精度约束：若二阶矩与更新不在 FP32 上算，$10^{-9}$ 量级的项会被直接舍掉（混合精度的标准做法是把它们留在 FP32，见 [7.6 节](/llm_internals/di-er-bu-fen-xun-lian-pian/07_distributed_training/7.6_mixed_precision.md)）。公开配置里这一项并无统一取值，原始 Transformer 取 $10^{-9}$，GPT-3 取 $10^{-8}$，见 6.1.4 的表 6-3。

**每个参数的状态要占多少字节。** Adam 的自适应不是白来的：它为每个参数多存两个浮点数。混合精度训练下这笔账要连同 16 位参数、16 位梯度和 FP32 主权重一起算（机制见 [7.6 节](/llm_internals/di-er-bu-fen-xun-lian-pian/07_distributed_training/7.6_mixed_precision.md)）：

| 优化器             | 16 位参数 | 16 位梯度 | FP32 主权重 | 优化器状态           |  合计 |
| --------------- | -----: | -----: | -------: | --------------- | --: |
| SGD + 动量        |      2 |      2 |        4 | 动量 4            |  12 |
| AdamW           |      2 |      2 |        4 | $m$ 4 + $v$ 4   |  16 |
| Muon（矩阵参数）      |      2 |      2 |        4 | 动量 4            |  12 |
| 8-bit AdamW     |      2 |      2 |        4 | $m$ 1 + $v$ 1   |  10 |
| Adafactor（不带动量） |      2 |      2 |        4 | 行和列各一份，$O(n+m)$ | ≈ 8 |

表 6-2：每参数的常驻字节数（混合精度口径）。[8-bit AdamW](https://arxiv.org/abs/2110.02861) 的依据是它把两个状态各量化到 8 位，原文的说法是 32 位状态下 Adam 每参数 8 字节、10 亿参数 8 GB，量化后降到 2 GB。[Adafactor](https://arxiv.org/abs/1804.04235) 只保存二阶矩的逐行和逐列和，对 $n\times m$ 的矩阵把 $O(nm)$ 降到 $O(n+m)$，合计一栏因此写成近似值；它默认不带一阶矩。Muon 只维护一个动量缓冲，Moonlight 报告的说法是“Muon 只用一个动量缓冲，而 AdamW 用两个，因此优化器多占的显存是 AdamW 的一半”。

代进具体模型：AdamW 的 16 字节/参数下，GPT-3 6.7B 的模型状态是 107 GB，Llama 3 8B 是 128 GB，Llama 3 405B 是 6,480 GB。第一个数就已经放不进一张 80 GB 的卡，这正是 ZeRO 与 FSDP 要分片的对象（[7.2 节](/llm_internals/di-er-bu-fen-xun-lian-pian/07_distributed_training/7.2_zero.md)）。6.4.3 会把它和激活放在一起比较。

## 6.1.4 AdamW：权重衰减的修正

在实践中，更常用的是 **AdamW**（Loshchilov & Hutter，2019）——它修正了 Adam 中权重衰减（L2 正则化）的实现方式。

**问题根源**：把 L2 正则写进损失函数，等价于在梯度上加一项，即 $g\_t \leftarrow g\_t + \lambda\theta\_{t-1}$，然后照常走上面五条公式。关键在于这一项**同时进入了 $m\_t$ 和 $v\_t$**：它先被一阶矩平滑，又被自己贡献的二阶矩除掉。结果是，梯度历史大的参数（$v\_t$ 大）受到的实际衰减被 $1/\sqrt{v\_t}$ 压得更小——衰减强度反而与参数的梯度历史挂钩，而这并不是正则化想要的。

**AdamW 的改进**：AdamW 把权重衰减从梯度里拿出来，直接施加在参数上：

$$\theta\_t = \theta\_{t-1} - \eta \frac{\hat{m}\_t}{\sqrt{\hat{v}*t} + \epsilon} - \eta \lambda \theta*{t-1}$$

第二项与优化器状态无关，对所有参数一视同仁。AdamW 原文的实验做在 CIFAR-10 与 ImageNet32x32 的 ResNet 上，结论是解耦后测试误差相对改善约 15%，并且超参搜索空间更可分离（学习率与衰减系数不再强耦合）。把这个结论直接外推成“显著改善大模型的泛化”并不成立——原文没有做大模型实验；它在 LLM 上被普遍采用，靠的是后来的训练实践，而非这组实验。

**实现口径：衰减项跟着学习率一起变。** PyTorch 的 `torch.optim.AdamW` 写成 $\theta\_t \leftarrow \theta\_{t-1} - \gamma\lambda\theta\_{t-1}$，其中 $\gamma$ 就是当前学习率。这意味着 6.2 节的调度在衰减学习率时，**也在同步削弱权重衰减**。把两者放在一起看，能得到一个有用的量：只受衰减作用的参数按 $(1-\eta\lambda)$ 逐步收缩，其特征时间尺度是 $1/(\eta\lambda)$ 步。$\eta = 3\times10^{-4}$、$\lambda = 0.1$ 对应约 3.3 万步；DeepSeek-V3 的峰值 $2.2\times10^{-4}$ 配 $\lambda = 0.1$ 对应约 4.5 万步，而它 14.8 万亿词元按末期批量（15,360 条 × 4,096 词元）折算约 23.5 万步。收缩的时间尺度比总训练长度短，说明权重衰减在整个训练周期内反复起作用，不是可有可无的小项。

**不是所有参数都做衰减。** 训练脚本里几乎总会看到一个 no-decay 参数组：偏置、归一化层的增益与偏移通常被排除，很多实现连嵌入表一起排除。理由是权重衰减的先验是“范数越小模型越简单”，而这条先验对这些参数不成立——归一化增益的合适尺度由它要还原的激活方差决定，把它往 0 推只会让后面的层重新学回来。判断标准很直接：参数是不是一个作用在向量上的线性映射；是，就归入衰减组。

**公开模型的配置。** 表 6-3 把几个可核对的预训练配置放在一起，值都取自各自论文的训练超参段落。

| 模型             | 优化器             | $\beta\_1$ |   $\beta\_2$ | $\epsilon$ |            权重衰减 |     梯度裁剪 |
| -------------- | --------------- | ---------: | -----------: | ---------: | --------------: | -------: |
| 原始 Transformer | Adam            |        0.9 |         0.98 |  $10^{-9}$ |               — |        — |
| GPT-3（全部规模）    | Adam            |        0.9 |         0.95 |  $10^{-8}$ |             0.1 | 全局范数 1.0 |
| PaLM 540B      | Adafactor（不做分解） |        0.9 | $1-k^{-0.8}$ |          — | $\text{lr}^{2}$ | 全局范数 1.0 |
| DeepSeek-V3    | AdamW           |        0.9 |         0.95 |          — |             0.1 |      1.0 |

表 6-3：几个公开模型写明的优化器配置，“—”表示该论文未在训练超参处给出。GPT-3 一行出自其附录的训练细节，PaLM 一行出自其训练设置一节——它的 $\beta\_2$ 随步数 $k$ 变化，权重衰减取当前学习率的平方，是本表里唯一一个动态口径，理由是罕见词元的二阶矩在短窗口上估不准。Llama 3 405B 没有进表：其预训练配方只写明用 AdamW 以及峰值 $8\times10^{-5}$、线性预热 8,000 步、余弦降到 $8\times10^{-7}$ 共 120 万步，$\beta$ 与 $\epsilon$ 未在原文给出；论文另在 scaling-law 实验一节写明“每一步的权重衰减取当步学习率的 0.1 倍”，是与 PaLM 同类的动态写法。

AdamW 长期是大模型训练的默认选择，DeepSeek-V3 等前沿模型均采用。同一位置上还有另外两支。一支是针对大批量训练的 LAMB（Layer-wise Adaptive Moments optimizer for Batch training），另一支是 T5 等模型采用的 Adafactor 一类低内存优化器。但自 2024 年底 Muon 提出、并在 2025—2026 年被多个前沿模型采用之后，这个“默认”开始被动摇。

## 6.1.5 Muon：把更新矩阵正交化

Adam 系优化器把每个参数当作独立标量来自适应缩放，完全忽略了权重本身是一个**矩阵**。**Muon**（MomentUm Orthogonalized by Newton-Schulz）正是从这里切入，[原始设计](https://kellerjordan.github.io/posts/muon/)由 Keller Jordan 于 2024 年底给出。它只作用于隐藏层的二维参数。每一步先算出常规的 SGD 动量更新，再用 **Newton-Schulz 迭代**对这个更新矩阵做近似正交化，然后才施加到参数上。正交化等价于取更新矩阵的 SVD 后只保留 $U$ 和 $V$、丢掉奇异值。标量与向量参数、以及输入输出层，仍交给 AdamW——这是 Muon 原始设计就明确的分工。

**三行公式。** 按 Moonlight 论文的写法，给定当前权重 $W\_{t-1}$、动量系数 $\mu$、学习率 $\eta\_t$：

$$M\_t = \mu M\_{t-1} + \nabla\mathcal{L}*t(W*{t-1}),\quad O\_t = \text{Newton-Schulz}(M\_t),\quad W\_t = W\_{t-1} - \eta\_t O\_t$$

中间那一步要近似算的是 $(M\_tM\_t^{\top})^{-1/2}M\_t$。若 $M\_t = U\Sigma V^{\top}$ 是奇异值分解，这个量恰好等于 $UV^{\top}$：方向全部保留，奇异值全部抹成 1。

**Newton-Schulz 迭代做了什么。** 先把动量矩阵除以自己的 Frobenius 范数，得到 $X\_0 = M\_t/|M\_t|\_F$，然后重复

$$X\_k = aX\_{k-1} + b(X\_{k-1}X\_{k-1}^{\top})X\_{k-1} + c(X\_{k-1}X\_{k-1}^{\top})^2X\_{k-1}$$

每一项都只含矩阵乘法，因此在 GPU 上很便宜。系数取原始设计的 $a = 3.4445$、$b = -4.7750$、$c = 2.0315$，迭代 $N = 5$ 次（Moonlight 沿用这组系数，并说明 $N = 10$ 正交化更准但不带来更好的效果，故取 5）。

关键在于这条递推只作用在**奇异值**上：$X$ 的奇异值 $\sigma$ 每次按标量多项式 $f(\sigma) = a\sigma + b\sigma^3 + c\sigma^5$ 更新，奇异向量不动。取一个能手算的例子，$M = \operatorname{diag}(10, 1)$，两个奇异值相差 10 倍。$|M|\_F = \sqrt{101} = 10.05$，归一化后是 0.99504 与 0.09950。逐次代入 $f$：

| 迭代次数 |   大奇异值 |   小奇异值 |  两者之比 |
| ---: | -----: | -----: | ----: |
|    0 | 0.9950 | 0.0995 | 10.00 |
|    1 | 0.7047 | 0.3381 | 2.085 |
|    2 | 1.1093 | 0.9889 | 1.122 |
|    3 | 0.7153 | 0.7097 | 1.008 |
|    5 | 0.7020 | 0.7087 | 0.991 |

表 6-4：Newton-Schulz 迭代在 $M = \operatorname{diag}(10, 1)$ 上的五步轨迹，由 $f(\sigma) = 3.4445\sigma - 4.7750\sigma^3 + 2.0315\sigma^5$ 逐次代入算出，可用计算器复核。

两件事从这张表里读得出来。一是收敛的是**比值**：三步之后两个方向的更新幅度已经基本拉平，这正是“防止权重只沿少数主导方向学习”的那句话的数值含义。二是奇异值并没有停在 1，而是在 0.70 到 1.11 之间来回跳。这组系数本就是为“小奇异值也能快速抬起来”而调的，五步之后所有奇异值落在一个带子里而不是一个点上。正因为如此，Muon 的更新尺度不能靠迭代本身保证，要在外面另行校准。

**更新尺度的校准。** Moonlight 给出的引理是：形状为 $\[A, B]$ 的满秩矩阵参数，其 Muon 更新的理论 RMS 为 $\sqrt{1/\max(A,B)}$——**同一个学习率作用在不同形状的矩阵上，实际步长不同**。AdamW 没有这个问题，它的更新 RMS 理论上在 1 附近、实测常在 0.2 到 0.4。于是 Moonlight 把更新按 $\sqrt{\max(A,B)}$ 放大再乘 0.2，并把权重衰减加回来：

$$W\_t = W\_{t-1} - \eta\_t\left(0.2\cdot O\_t\cdot\sqrt{\max(A,B)} + \lambda W\_{t-1}\right)$$

代入 Llama 3 8B 的形状验算：$W\_Q$ 是 `[4096, 4096]`，理论 RMS $= \sqrt{1/4096} = 0.0156$，乘 $0.2\sqrt{4096} = 12.8$ 得 0.2；MLP 的 $W\_1$ 是 `[4096, 14336]`，理论 RMS $= \sqrt{1/14336} = 0.00835$，乘 $0.2\sqrt{14336} = 23.9$ 同样得 0.2。两个形状差别很大的矩阵被拉到同一个更新尺度，这就是“不必重新调参就能换上 Muon”的来历。加权重衰减的理由是实测：不加时权重与层输出的 RMS 会一路涨到超出 bf16 的高精度区间。

**代价在分布式那一侧。** 正交化需要**完整的**梯度矩阵，而 ZeRO/FSDP 把参数和梯度按元素切开了。Moonlight 的分布式实现因此要先把本地分片对应的梯度在数据并行组内聚齐，做完 Newton-Schulz 再丢掉不属于本地的部分；额外通信可以用 bf16，全程通信量是分布式 AdamW 的 1 到 1.25 倍，实践中接近下界。计算侧的开销则不大：5 次迭代只是几次矩阵乘法，论文给出的量级是优化器端到端延迟通常占前后向时间的 1% 到 3%。

**它管不到哪些参数。** 嵌入表、输出头、所有一维参数（归一化增益、偏置）都不走 Muon。判据与 6.1.4 的 no-decay 组是同一条：这些张量不是“作用在残差流上的线性映射”，把它们的更新矩阵正交化没有对应的几何意义。实践中它们仍由 AdamW 更新，因此一次训练里两个优化器是同时在跑的。工程上 Muon 已经进了 NVIDIA Megatron Core，配套的是一个**逐层分布式优化器**：把整层指派给某个数据并行 rank，使整层的预条件不需要额外通信就能算出来，绕开了上面那条分片冲突。Megatron-LM 的命令行一侧可以直接对照：`--optimizer` 的可选值里有 `muon`，`--muon-num-ns-steps` 的默认值正是 5，`--muon-scalar-optimizer` 指定一维参数交给谁、默认 `adam`。

**为什么正交化会更快？** 这正是本节“为什么选择 Adam”要追问的层次。一项曲率视角的分析（[Why Muon Outperforms Adam: A Curvature Perspective](https://arxiv.org/abs/2606.04662)，2026 年 6 月）对训练曲面做二阶泰勒展开后发现：在相同验证损失下，Muon 与 Adam 的**一阶收益相当、更新范数也相当**，差别出在二阶的曲率惩罚项——把该惩罚拆成“更新范数平方”与“归一化方向锐度”（Normalized Directional Sharpness，NDS）两部分后，Muon 的优势**主要来自更低的 NDS**，而不是更新幅度。换句话说，正交化的作用更像是让更新避开高曲率方向，而非走得更远。

多个前沿模型已在训练中使用它——

* **Moonlight**（[Muon is Scalable for LLM Training](https://arxiv.org/abs/2502.16982)）：3B/16B MoE、5.7T 词元，论文报告在计算最优设置下达到与 AdamW 相当的性能只需约 52% 的训练 FLOPs（该倍数为特定设置下的结论，不宜外推为通用常数）
* **Kimi K2**：1T 总参数 / 32B 激活、15.5T 词元训练无损失尖峰，使用的是 Muon 的变体 **MuonClip**（在 Muon 基础上增加 QK-clip 以抑制训练不稳定，机制见 6.3.6）
* **Kimi K3**：延续 K2 用 Muon 优化矩阵参数，并对注意力投影再细化出 **Per-Head Muon**——不对完整的 Q/K/V 投影矩阵做 Newton-Schulz 正交化，而是把动量矩阵按头维切开、逐头分别正交化。其理由是：整矩阵正交化把所有头当成一个耦合块，梯度或动量尺度较大的头会主导共享的更新方向，尺度较小的头则得不到充分归一化；逐头正交化使各头的更新尺度对齐，在更大规模上训练更稳，且因为在瘦长的逐头块上做 Newton-Schulz 比在整个投影矩阵上更便宜，优化器开销还略有下降（[arXiv:2607.24653](https://arxiv.org/abs/2607.24653)）。该报告的口径是 **Muon**，不再沿用 MuonClip 这个名字，但 K2 的权重裁剪机制本身仍在使用
* **DeepSeek-V4**：对**大部分模块**使用 Muon，而嵌入层、预测头、mHC 的静态偏置与门控因子、以及所有 RMSNorm 权重仍保留 AdamW（[技术报告](https://arxiv.org/abs/2606.19348)的优化器一节）

需要注意两点分寸：一是各家的“Muon”往往是变体而非原版（Kimi K2 是 MuonClip），引用时应以模型方自己的论文口径为准；二是 Muon 的收益体现在**收敛速度与稳定性**上，而非单步吞吐——[NVIDIA 在 GB300 上的实测](https://developer.nvidia.com/blog/advancing-emerging-optimizers-for-accelerated-llm-training-with-nvidia-megatron/)表明其训练吞吐与 AdamW 大致持平，官方措辞是“使用 Muon 相对 AdamW 有很小的训练性能损失”；同一篇还写明，若把 Newton-Schulz 迭代中矩阵乘法的浮点运算也计进去，Muon 的 MFU（Model FLOPs Utilization，模型浮点运算利用率，口径见 [7.5.6 节](/llm_internals/di-er-bu-fen-xun-lian-pian/07_distributed_training/7.5_activation_checkpointing.md)）反而更高。
