4 位只剩 16 个数,怎么训?
这是一堂岔路课,挂在第 4 课后面:8 位靠「一小块一个缩放」撑住了,那 4 位呢?4 位一共只有 16 个位型。
本课一问:4 位只剩 16 个数,怎么训?
这一课先不碰:推理时的各种权重量化算法(C13);MoE 本身怎么路由(C11)。
从已有出发
第 4 课的做法:把张量切成小块,每块按自己的最大值缩放,再舍入到 E4M3。4 位沿用同一个思路,只是元素格式换成 E2M1(1 位符号、2 位指数、1 位尾数)。它会出现在训练一步的哪里?第 4 课的格式标签里,「更新」那一格写着「FP32 主权重 → 在线量化成 FP8」;到了 4 位,这一格变成「FP32 主权重 → 量化成 FP4 → 给前向用」,本课最后讲这是怎么做的。
为什么这里换例子:和第 2–4 课一样,这一课讨论的是「一小块数存成 4 位会变成什么」,贯穿例句不进入这一层;下面用的手算块 [0.3, −1.2, 2.7, 0.05] 是 R4 调研的实算用例(教学构造的 4 个数),8 × 256 的张量同样是标注过的教学构造。
- 解决了范围到 ±3.4 × 10³⁸,1 附近的间距 2⁻²³ ≈ 1.2 × 10⁻⁷,数值上几乎不用操心。卡在每个参数 4 + 4 + 4 + 4 = 16 字节(权重、梯度、Adam 的 m、v):锚点 27,781,427,952 个参数就是 444.5 GB,是 80 GB 单卡的 5.6 倍,还没算激活。
- 解决了矩阵乘和激活用 16 位,带宽与激活显存减半;FP32 主权重接住小更新,loss 乘 S 把小梯度推出下溢区,更新前再除回来。卡在指数只有 5 位:fp16(10⁻⁸) = 0,fp16(1 + 10⁻⁴) = 1,fp16(70,000) = inf;缩放倍数要一直调,溢出就得跳过这一步。
- 解决了8 位指数,范围与 FP32 相同:不再下溢,不需要 loss scaling。2026 年的默认训练精度。卡在1 附近间距粗到 1/128:bf16(257) = 256,bf16(1 + 10⁻³) = 1——主权重和优化器状态仍要 FP32,账本还是 16 字节/参数。
- 解决了激活每 1 × 128、权重每 128 × 128 一个缩放:张量 [1000, 0.01, 0.02, 0.5] 里,0.01 的误差从整张量缩放的 12.8% 降到 0.45%;DeepSeek-V3 相对 BF16 的 loss 相对误差 < 0.25%(官方自报)。卡在只有 256 个位型,E4M3 最大 448;块的形状要跟着离群值走——激活梯度改按 128 × 128 块量化,16B MoE 训到约 300B token 发散(附录 B.2);主权重和梯度仍是 FP32。
- 解决了MXFP4 每 32 个数共用一个 2 的幂(4.25 位/参数),NVFP4 每 16 个数一个 E4M3 缩放;K3、DeepSeek-V4 在后训练阶段对 MoE 专家权重做 QAT。卡在E2M1 只有 16 个码点:块 [0.3, −1.2, 2.7, 0.05] 用 MX 缩放后,0.05 → 0;全 FP4 预训练仍是前沿。
- 解决了不把 s × s 的注意力分数存下来:锚点一条 4,096 token 的序列,激活从 162.5 GiB 降到 42.5 GiB(选择性重计算 / FlashAttention);全量重计算每层只存输入,只剩 2.5 GiB(标准块公式近似)。卡在重计算用多算一遍前向换显存;可 444.5 GB 的模型状态一张 80 GB 卡仍然放不下 → C10 并行。
先看 E2M1 一共能表示哪些数。它没有 inf、没有 NaN,16 个位型里正负各 8 个值:
口径:浏览器现算。FP32 用 DataView 取位;其余格式先存成 FP32,再按 RNE 舍入(与 PyTorch 的 dtype 转换逐值一致,开发时用 torch 2.6 对照过)。E4M3 是 OCP 规范的 FN 变体(无 inf,最大 448);E5M2 有 inf(最大 57,344)。
E2M1 的非负值只有 0、0.5、1、1.5、2、3、4、6 这 8 个:0.25 恰在 0 与 0.5 正中间,平局取偶数,落成 0;2.5 落成 2、5 落成 4(同样是平局取偶);7 超过最大值 6,饱和成 6。同样的数进 E4M3,误差都在几个百分点以内——4 位和 8 位的差距,一眼就看出来。
先自己设计:整张量一个缩放
照搬第 4 课的朴素方案:整张量取最大值,缩放到 6,再舍入。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
张量是教学构造:8 个 token × 256 个通道,固定种子的标准正态数,其中第 17、90 两个通道(同在前 128 个通道里)整体乘离群倍数 k——模拟「少数通道数值特别大」,不是任何模型的真实激活。量化、反量化、误差全部由浏览器实算(元素格式与 FloatLab 同一套编解码,开发时与 torch 的 float8_e4m3fn 逐值对照)。
张量是教学构造:8 个 token × 256 个通道,固定种子的标准正态数,其中第 17、90 两个通道(同在前 128 个通道里)整体乘离群倍数 k——模拟「少数通道数值特别大」,不是任何模型的真实激活。量化、反量化、误差全部由浏览器实算(元素格式与 FloatLab 同一套编解码,开发时与 torch 的 float8_e4m3fn 逐值对照)。
改进一:MX——每 32 个数共用一个 2 的幂
2023 年 9 月,AMD、Arm、Intel、Meta、Microsoft、NVIDIA、Qualcomm 联合发布了 OCP Microscaling(MX)格式规范 v1.0:每 32 个元素共用一个缩放因子,缩放因子用 E8M0 存——只有 8 位指数、没有尾数,也就是说它只能是 2 的幂(2⁻¹²⁷ 到 2¹²⁷)。元素格式可以是 FP8(MXFP8)、FP6、FP4(MXFP4)等。
缩放只能是 2 的幂,好处是乘除不引入舍入、硬件做起来便宜;代价是块最大值除以 X 之后落在 [4, 8) 之间,不一定正好是 6,超过 6 的部分只能饱和。上面组件的 MXFP4 一行会报出这张张量里有多少元素被这样截断。
改进二:NVFP4——块更小,缩放更细
NVIDIA 的 NVFP4 做了两处改动:每 16 个元素一个缩放,缩放用 E4M3 存(不必是 2 的幂,可以把块最大值精确对到 6 附近),外加每张量一个 FP32 缩放,把 E4M3 缩放本身的范围也照顾到。每个元素实际占的位数:
| 格式 | 元素 | 块大小 | 块缩放 | 每元素位数 |
|---|---|---|---|---|
| MXFP8 | E4M3(或 E5M2) | 32 | E8M0(8 位) | 8 + 8 ÷ 32 = 8.25 |
| MXFP4 | E2M1 | 32 | E8M0(8 位) | 4 + 8 ÷ 32 = 4.25 |
| NVFP4 | E2M1 | 16 | E4M3(8 位)+ 每张量 FP32 | 4 + 8 ÷ 16 = 4.5 |
4.25 这个数在 gpt-oss 的模型卡里出现过:它把 MoE 权重(占总参数 90% 以上)量化成 MXFP4,每参数 4.25 位 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条原文:在后训练中把 MoE 权重量化到 MXFP4;4.25 bit/参数、占总参数 90% 以上。原文没有用「QAT」这个词。 出处gpt-oss 模型卡(需联网) ↗需联网 。换算到锚点:如果把 Qwen3.8-27B 的全部 27,781,427,952 个参数都存成 MXFP4,是 14.8 GB;BF16 是 55.6 GB(纯算术,锚点实际以 BF16 发布)。
NVFP4 也用来做过预训练:NVIDIA 用它训了一个 12B 的 Mamba-Transformer 混合模型,10T token,loss 与下游指标接近 FP8 基线。要做到这一点,他们加了一整套手段:对 Wgrad 的输入做 16 × 16 的随机 Hadamard 变换、权重按 16 × 16 的二维块量化、梯度用随机舍入,还把最前 2 块和最后 8 块留在 BF16(占线性层的 16%);在 8B、1T token 的对照里,MXFP4 要多用 36% 的 token 才追平 NVFP4 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条全部为作者自报;核实 agent 在 arXiv 原文核对。注意 NVIDIA 官方的 NVFP4 介绍博客讲的是推理。 出处NVIDIA 2025,Pretraining LLMs with NVFP4(需联网) ↗需联网 。4 位能训,但要一整套补丁——全 FP4 预训练在 2026 年仍是前沿,不是默认做法。
回到上面的组件试三件事:① 把离群倍数 k 拖到 1(没有离群值):MXFP4、NVFP4 的误差仍在 10% 上下——1 位尾数的下限摆在那里;② 把 k 拖到 1,000:「FP4 整张量」几乎全变 0,块缩放的几行还活着;③ 在「自定义」里把缩放格式从 E8M0 换成 E4M3,再把块从 1 × 32 改成 1 × 16——你就一步步把 MXFP4 改成了 NVFP4,看误差和每元素位数一起怎么变。
2026 年它用在哪:QAT 与发布格式
4 位在 2026 年的主要用法是量化感知训练(QAT):训练时前向就用量化后的权重,让模型在训练中适应量化误差;反向时梯度「直通」量化这一步,落回 FP32 主权重。
三家的做法(全部为官方自报):
- Kimi K3:从 SFT 阶段起做 QAT,MoE 专家权重 MXFP4、专家的输入激活 MXFP8,其余组件(注意力投影、共享专家、路由器等)保持高精度;SFT 与 RL 全程都用,RL 的采样和训练用同一套量化,消除训练与推理的不一致 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条原文:MoE 专家权重占模型参数显存的大头,所以量化它们;QAT 覆盖整个后训练。 出处Kimi K3 技术报告 §4.1.1、§4.1.4(本地 PDF) ↗ ;
- DeepSeek-V4:后训练做 FP4(MXFP4)QAT,用在 MoE 专家权重和稀疏注意力 indexer 的 QK 路径上;反向按 STE 把梯度传回 FP32 主权重;RL 的采样直接用原生 FP4 权重 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条原文细节:FP32 主权重 → FP4 → 无损反量化到 FP8 计算;1 × 32 的 FP4 子块嵌在 128 × 128 的 FP8 块里。 出处DeepSeek-V4 技术报告 §5.2.1(本地 PDF) ↗ ;
- gpt-oss:在后训练中把 MoE 权重量化到 MXFP4,每参数 4.25 位。
DeepSeek-V4.1-Flash 的 config 把这件事写进了字段:expert_dtype = fp4,weight_block_size = [32, 32],scale_fmt = ue8m0(frontier-models.json)。同一个模型里,不同用途还会选不同的 4 位格式:V4.1 的 indexer 用 OCP 标准的 MXFP4(硬件兼容面最广),主 KV 缓存用去掉了全局缩放的 NVFP4 式格式(精度更高,而 KV 只存储、不进矩阵乘,不需要硬件原生支持)——这就是 C3 第 8、10 课说「把缓存量化到更低精度」的一个真例子(R3 调研 §1.5、§3.10)。
常见误解一:「FP4 训练已经是主流。」
2026 年 FP4 进入训练,主要是后训练阶段的 QAT,对象是 MoE 专家权重,目的是让发布出去的 4 位权重不掉点;主干的预训练仍以 BF16 / FP8 为主。全 FP4 预训练(NVFP4 的 12B / 10T 实验)要叠一整套补丁,仍是前沿。
常见误解二:「MXFP4 和 NVFP4 只是名字不同。」
块大小(32 对 16)、块缩放的格式(E8M0 只能是 2 的幂,E4M3 可以不是)、有没有每张量的第二级缩放,三处都不同;每元素 4.25 位对 4.5 位。在上面的组件里把自定义方案一步步从 MXFP4 改到 NVFP4,误差的变化就是这三处差别的后果。
常见误解三(旧版课程 M7 的说法):「MXFP4 存储会让离群激活溢出。」
K3 报告里,MXFP4 用于 MoE 专家权重,专家的输入激活是 MXFP8。它提出 SiTU-GLU 的理由写的是:SwiGLU 的两个因子都没有上界,大坐标相乘会产生激活离群值,增加低精度算术里的溢出风险(§2.3.2)——说的是激活在低精度里的范围,不是「MXFP4 存储」 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条旧版归因不精确,R5 迁移清单 M7-24 记录;这里按原文改正。 出处Kimi K3 技术报告 §2.3.2、§4.1.4(本地 PDF) ↗ 。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 把权重压到约 4 位(发布与推理的显存、带宽再砍一半),同时不让模型掉点 |
| ② 数学上为什么可能有效? | 每元素位数是计数 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条4 + 8 ÷ 32 = 4.25;4 + 8 ÷ 16 = 4.5。 出处待补 ;块越小、缩放越细,块内的动态范围越可能落进 E2M1 仅有的 12 倍范围——这是动机,不保证训练结果 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条E2M1 的最大值 6 与最小非零值 0.5 之比为 12;块缩放只保证块最大值对齐。 出处待补 ;STE 是近似梯度 |
| ③ 实验上呢? | K3、DeepSeek-V4、gpt-oss 都在后训练用 MXFP4 处理 MoE 权重;NVFP4 做了 12B / 10T 的预训练 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条全部为官方自报,未见第三方复现。 出处NVFP4 预训练(需联网) ↗需联网 |
一句话
4 位只有 16 个码点,只能靠「更小的块 + 各自的缩放」撑住;2026 年它主要以 QAT 的形式用在 MoE 专家权重上,全 FP4 预训练仍是前沿。
回到主线
回主线第 5 课:激活为什么比参数还占显存? → 第 5 课
你可能会问
- 「4.25 位的权重怎么放进显存?」 两个 4 位元素打包成一个字节,每 32 个元素再附一个字节的缩放;读出来时按块乘回缩放。计算时可以直接用硬件的 FP4 矩阵乘,也可以像 DeepSeek-V4 那样先反量化成 FP8。
- 「为什么量化的是 MoE 专家,不是注意力?」 专家权重占了参数的绝大部分(gpt-oss 超过 90%),压它收益最大;注意力投影、路由器这些小而敏感的部分留在高精度。K3 也是这么分的。
- 「QAT 和训练后直接量化(PTQ)差在哪?」 PTQ 不再训练,只挑缩放与舍入;QAT 让模型在带着量化误差的前向里继续学,权重会主动长到「量化后仍然好用」的位置。代价是要多训一段。