Adam 把一个权重矩阵当成一堆独立的数,浪费了什么?
本课一问:第 2 课的旋转峡谷说明 Adam 只认坐标轴。一个权重矩阵被 Adam 当成一堆互不相干的数来更新——浪费了什么?
这一课先不碰:原版 Muon 下注意力 logit 失控、QK-Clip 怎么按住它(C8 兑现);大矩阵的 Newton-Schulz 怎么在多卡上算(本课程不展开,见 Kimi K3 与 DeepSeek-V4 报告的分布式 Muon 实现)。
从已有出发
「小明把苹果给了小王」里每个 token 的向量穿过 FFN 时,要乘一个 gate_proj 矩阵——Qwen3.8-27B 里它是 17,408 × 5,120,89,128,960 个数,每层 3 个这样的矩阵、64 层合计 17,112,760,320 个参数(与 safetensors 实测分项一致)。这个矩阵作为一个整体把输入空间映到输出空间,有它自己的「主方向」。前六课的优化器里,Adam 把这 89,128,960 个数当成 89,128,960 个独立的标量,各除各的 √v̂。
这一课用两个替身。矩阵更新长什么样,要在一个真实训练中的矩阵上看:浏览器里小模型的隐层矩阵 W1(64 × 64);矩阵「把圆变成椭圆」的几何,用一个 2 × 2 矩阵画出来。
先自己设计:继续用逐元素的 Adam
最省事的就是照旧:每个矩阵元素一个 m、一个 v,逐元素相除。先看看它给一个矩阵的更新长什么样——把更新矩阵做奇异值分解,64 个奇异值就是它在 64 个「主方向」上各走多大:
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
数字来源:浏览器实时训练(纯 JS,Float64)。模型、语料、种子写在上方;同一组对照里所有 run 共用初始化和取批顺序,只改被比较的那一项。换种子重跑可以看到噪声有多大——差异小于种子间波动时不下结论。
试三件事(先看「朴素方案」):① 读表格第一列:最大方向占 57.0%、前 5 个占 82.8%;左边的条形图用对数纵轴,64 个奇异值从 1 一路掉到 10−3 附近。② 把「快照」切到第 50 步再到第 200 步:越早越集中(训练初期更新几乎只沿一个方向)。③ 看右边那张条形图:同一个矩阵送进 5 步 Newton-Schulz 之后,奇异值全部落在 0.41–1.19 之间——下面讲它怎么做到的。
改进:Muon——让每个方向走差不多大的一步
任何矩阵都可以写成 G = UΣVT:先转一下(VT),沿各主方向拉伸(Σ 的对角线就是奇异值),再转一下(U)。几何上,G 把单位圆变成一个椭圆,两条半轴就是两个奇异值。Muon(Keller Jordan 2024-12-08)的做法是把动量矩阵换成它的「正交化」版本 UVT:方向保留,奇异值全部变成 1——每个主方向走一样大的一步 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条原文的动机是经验观察:SGD-momentum 和 Adam 对 Transformer 二维参数的更新条件数很高、几乎低秩;并推测正交化放大了那些很少被更新的方向 出处Keller Jordan《Muon》(2024-12-08) ↗需联网 。
精确的 UVT 要做 SVD,又慢,在 BF16 下也不稳。Muon 改用 Newton-Schulz 迭代:先除以 Frobenius 范数(保证最大奇异值 ≤ 1),再做 5 步 X ← aX + b(XXT)X + c(XXT)²X。这一步对每个奇异值恰好作用同一个五次多项式 φ(σ) = aσ + bσ³ + cσ⁵,奇异向量不变 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条把 X = UΣVᵀ 代入即得 UΦ(Σ)Vᵀ;上面「改进方案」里标量迭代和矩阵迭代两列的数完全相同 出处Jordan 博客「Proving that NS iteration orthogonalizes the update」 ↗需联网 。系数 (a, b, c) = (3.4445, −4.7750, 2.0315) 是调出来的:让 φ 在 0 附近尽量陡(小奇异值每步放大 3.4 倍),代价是 1 不再是不动点。
试三件事(「改进方案」里的 NewtonSchulzViz):① 默认的 diag(3, 0.1):归一化后是 (0.9994, 0.0333),把 k 拖到 5,变成 (0.697, 1.129)——两个都被拉进了 0.7–1.2 的带里,虚线椭圆变成接近圆的实线。② 读下方「[0.01, 1] 经 5 步映到 [0.682, 1.134]」:不是精确的 1。Jordan 的实验是这点误差(约 ±0.3)不伤 loss。③ 系数切到「基线五次」,k = 5:[0.312, 1.002]——它能精确收敛到 1,但太慢;再切到「DeepSeek-V4」:前 8 步用 Jordan 系数快速拉起来,后 2 步换基线系数钉在 1 上,10 步后是 [1.0000, 1.0005]。
把 Newton-Schulz 放到锚点模型的真实形状上,看一步要做什么运算:
| 维度 | 含义 | 真实规模 | 小规模 |
|---|---|---|---|
| F | FFN 中间维 intermediate_size | 17,408 | 6 |
| D | 隐藏维度 hidden_size | 5120 | 4 |
🔍 为什么是「正交化」?有没有比「经验观察」更硬的理由?
有一条理论线索:把「每一步在谱范数(最大奇异值)约束下让 loss 下降最多」写成优化问题,解正好是 UVᵀ 的方向——正交化更新等价于谱范数下的最速下降(Bernstein 等人的系列工作;R3 §3.9 摘录)。它解释了「为什么是 UVᵀ」,但没有证明「谱范数是对的那把尺子」,所以仍是理论动机。另一个性质是可以证明的:对任意正交矩阵 Q₁、Q₂,Ortho(Q₁GQ₂) = Q₁·Ortho(G)·Q₂——整个矩阵在输入、输出两侧怎么转,正交化都跟着转。这正是第 2 课旋转峡谷里 Adam 做不到的事:逐元素的 √v̂ 只认坐标轴。
真训练对比:结论随设置翻转
数字来源:浏览器实时训练(纯 JS,Float64)。模型、语料、种子写在上方;同一组对照里所有 run 共用初始化和取批顺序,只改被比较的那一项。换种子重跑可以看到噪声有多大——差异小于种子间波动时不下结论。
试三件事:① 默认(cosine、weight decay 0.1)读最后一行:AdamW 3.691、Muon 3.656。② 把调度切到「常数」、weight decay 切到 0 再训练:AdamW 3.677、Muon 3.704——Muon 反而更差。原因和第 5 课一样:正交化后每一步都是「满幅」的更新,步子不会随梯度变小而变小,不降学习率就停不稳。③ 回到默认,再到实验课用三个学习率、两个种子去比:差距要大于种子间的波动才算数。
这个翻转本身就是本课最值得带走的证据课:同一个模型、同一份数据,优化器的比较结论会随调度和衰减翻转。Moonlight 把「加 weight decay」和「调整每个参数的更新尺度」列为 Muon 扩展到大模型的两个关键 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条原文:这两项让 Muon 在大规模训练上开箱即用;scaling law 实验显示在算力最优训练下约为 AdamW 的 2 倍算力效率 出处Liu et al. 2025(Moonlight)摘要 ↗需联网 ,和上面的现象方向一致;但我们的小模型不能替它作证:2.5 万参数对 30 亿激活、160 亿总参数,规模差了五个数量级以上。
现代做法:Muon 管矩阵,AdamW 管其余
| 模型 | 优化器分工 | 出处 |
|---|---|---|
| NanoGPT speedrun(Jordan) | Muon 把达到 3.28 验证 loss 的速度记录提高到 1.35 倍 | Jordan 博客 |
| Moonlight 3B/16B MoE | Muon + weight decay + 更新 RMS 0.2;报告约 2 倍算力效率 | arXiv 2502.16982 |
| Kimi K2 | MuonClip:原版 Muon 在中等规模 run 中 max logit 超过 1,000,于是加 QK-Clip(τ = 100);15.5T token 全程无 loss spike | arXiv 2507.20534(R4 摘录) |
| Kimi K3 | Per-Head Muon:Q、K、V 的动量按头切开各自正交化,并沿用 K2 的权重裁剪 | K3 报告 §2.5(本地 PDF) |
| GLM-4.5 / GLM-5 | 除 embedding、bias、RMSNorm 外全用 Muon(NS 5 步、μ = 0.95、RMS 0.2);GLM-5 起按头拆开(Muon Split) | R2 摘录 |
| DeepSeek-V4 | 多数模块用 Muon;embedding、预测头、mHC 的静态偏置与门控、RMSNorm 用 AdamW;混合 NS 10 步(8 + 2);动量 0.95、wd 0.1、更新 RMS 0.18;Q 与 KV 上的 RMSNorm 按住 logit,不用 QK-Clip | 报告 §2.4、§4.2.2(本地 PDF) |
| Qwen3.8-Flash-Next | Muon 负责主体;embedding、lm_head、MoE router、输出门等用 AdamW;NS 8 步;融合矩阵先按头或 gate/up 拆开 | 技术报告(R2 摘录,官方自报) |
| Llama 3、OLMo 2 | AdamW | R4 摘录 |
| Qwen3.8-27B(本课锚点) | 未公开 | R2 §1.5.1 |
证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条「Muon 管矩阵、AdamW 管其余」是 2025–2026 年中国前沿实验室的共识(R3 §3.9);正交化的粒度(整矩阵还是按头)、怎么按住 logit 仍有分歧 出处DeepSeek-V4 §2.4;Kimi K3 §2.5;其余见表中出处 ↗ 对我新 ≠ 对领域新:Newton-Schulz 迭代本身是数值分析里的老方法(Jordan 引用了 Kovarik 1970、Björck & Bowie 1971、Higham 2008),更早的矩阵预条件优化器有 Shampoo(2018);「Q、K、V 分开正交化更好」在 Jordan 2024 年的博客里就写过,GLM-5 的 Muon Split、K3 的 Per-Head Muon 是各自的工程版本,彼此没有互相引用(R2)。
一个证据三问的反面例子。Qwen3.8-Flash-Next 报告做过压力测试:学习率固定在最优值的 4 倍,「AdamW 加 Qwen3.5 结构」每万步 183 次 loss spike,「Muon 加 Gated Residual」为 0 次(官方自报)。这组对比同时换了优化器和残差结构,不能单独归功于 Muon——引用时要把两个变量一起说出来。
项目里的同一个观察(同一步、同一个隐层矩阵,AdamW 一阶矩、Muon 动量、Newton-Schulz 输出的奇异值):
⚠ 常见误解
「Muon 可以替换所有参数的优化器。」它只处理二维的隐藏层矩阵。embedding、输出头、归一化增益、偏置仍用 AdamW(Jordan 的建议,DeepSeek-V4、GLM、Qwen 的实际做法);Qwen3.8-Flash-Next 还专门把 MoE router 留给 AdamW,理由是用 Muon 会让 router 早期不稳定。
「正交化之后,奇异值严格等于 1。」Jordan 系数 5 步后落在 0.68–1.13,1 甚至不是不动点(φ(1) = 0.701);要精确到 1,得像 DeepSeek-V4 那样最后换系数多迭代两步。上面的组件可以直接读出这两组范围。
「Muon 更稳,就不需要别的稳定手段。」Kimi K2 用原版 Muon 时注意力 max logit 很快超过 1,000,才加了 QK-Clip;DeepSeek-V4 靠 Q 与 KV 上的 RMSNorm。优化器只管「怎么走」,模型内部的数值会不会失控是另一回事(C8)。
在演进地图上的位置
- 全量梯度下降
- 小批量随机梯度下降 SGD
- 动量(重球法)
- Adam:每个参数一把尺子
- AdamW:解耦权重衰减
- 学习率 warmup
- 学习率衰减:cosine → WSD
- batch 大小:渐增,还是一开始就大
- 全局梯度范数裁剪
- Muon:按矩阵的奇异方向更新
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 逐元素的更新让矩阵的更新几乎低秩:少数奇异方向独占大部分步长,其余方向几乎不动 |
| ② 数学上为什么可能有效? | NS 迭代对奇异值作用同一个多项式、不改奇异向量;正交化对两侧旋转等变 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条代数恒等式 出处Jordan 博客的推导 ↗需联网 ;「正交化 = 谱范数下的最速下降」是理论动机 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条解释了方向为什么是 UVᵀ,没有证明这把尺子最优(R3 §3.9) 出处待补 |
| ③ 实验上为什么最后选了它? | NanoGPT speedrun 1.35 倍、Moonlight 约 2 倍算力效率;Kimi、GLM、DeepSeek 的旗舰先后采用 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条都是提出方或采用方自己的实验;小模型上结论还会随调度翻转 出处Jordan 2024;Moonlight 2025;K3、DeepSeek-V4 报告 ↗需联网 |
一句话
Adam 看坐标,Muon 看矩阵的奇异方向:把更新的奇异值都拉到 1 附近。
先停在这里:记住「Muon 管隐藏层矩阵、AdamW 管其余」和「NS 只是近似正交化」,去实验课把三种优化器放在一起比一次。
再深一层:打开 chunhuizhang/llm_rl 的 muon_basics notebook(公开),把 NS5 与精确 SVD 的差在自己机器上算一遍。
下一个缺口
「参数怎么更新得又快又稳」这一章到此结束:每一步怎么走(SGD → 动量 → Adam → AdamW → Muon)、学习率怎么随时间变(warmup、cosine / WSD)、异常怎么挡(裁剪)。下一个问题换了一个尺度:优化器定了,该训多大的模型、喂多少数据? → C6 规模。先去实验课把本章的优化器在同一个模型上比一遍。
回扣先记下:Kimi K2「max logit 超过 1,000」会在 C8(稳定性)兑现。
你可能会问
这一课还没有收到真实提问;你的提问会记到 05-问答记录/C5-L7.md。
🔍 Muon 省显存吗?
Muon 对每个矩阵参数只存一份动量,Adam 存 m、v 两份,所以矩阵部分的优化器状态少一半。但 embedding、输出头这些仍用 AdamW 的参数照旧是两份;Qwen3.8-27B 的 embedding 与 lm_head 合计 2,542,796,800 个参数,这部分省不了。代价在另一头:NS 需要完整的矩阵,分布式训练时要先把切到各卡上的矩阵拼回来(Kimi K3、DeepSeek-V4 都专门写了这部分的工程实现;本课程不展开,C10 讲的是切法本身)。