跳转至

第十五章:模型量化

15.1 量化是什么,何时值得做

量化用更少的位表示权重或中间状态。训练通常采用混合精度,可能组合 BF16/FP16、FP32 主权重或优化器状态,也有针对特定硬件的低精度训练;不能把训练中的所有张量都当作同一格式。

只看权重的理想裸存储,使用十进制 GB:

模型 FP16 权重 INT4 权重
7B \(7 \times 10^9 \times 2 = 14\) GB \(7 \times 10^9 \times 0.5 = 3.5\) GB
70B \(70 \times 10^9 \times 2 = 140\) GB \(70 \times 10^9 \times 0.5 = 35\) GB

70B 的 FP16 裸权重约 140 GB,并不能推出「至少四张 A100 80GB」:两张卡的总容量已有可能容纳权重,但能否运行目标上下文与并发,要加上 KV、激活、通信缓冲、workspace 及分片/复制开销。

INT4 的实际存储还包含 scale、zero point、对齐和未量化层,通常大于表中数字。单卡可装下某个量化模型,不代表目标负载的延迟和并发可接受。

15.1.1 第二个收益:速度

低比特权重可降低权重访存量(4-bit 相对 16-bit 为四分之一),但端到端速度取决于硬件是否有匹配 kernel、反量化开销、batch 与是否受 KV Cache 限制,不能从位宽直接推导固定加速比。

15.1.2 但不是免费午餐

把连续权重映射到有限表示会引入表示误差;端到端任务质量是否下降、下降多少,取决于格式、校准、模型和任务。整个量化算法要回答的核心问题是:

如何在最小的精度损失下,把高精度数压到低精度数?

15.2 核心机制:连续到离散的映射

量化应先明确整数范围。以非对称 4-bit 无符号量化为例, \(q_{\min}=0\)、 \(q_{\max}=15\),对校准范围 \([x_{\min},x_{\max}]\):

\[ s = \frac{x_{\max}-x_{\min}}{q_{\max}-q_{\min}},\qquad z = \mathrm{clip}\left(q_{\min}-\mathrm{round}\left(\frac{x_{\min}}s\right),q_{\min},q_{\max}\right) \]
\[ q=\mathrm{clip}\left(\mathrm{round}\left(\frac{x}{s}\right)+z,q_{\min},q_{\max}\right),\qquad \hat{x}=s(q-z) \]

若范围为 \([-2.5,2.5]\),采用 ties-to-even 舍入,则 \(s=5/15=1/3\)、 \(z=8\)。对 \(x=0.7\),得到 q=10,反量化值为 2/3,约 0.667,绝对误差约 0.033。计算时不应先把 scale 截短到 0.333。

常见的对称有符号 INT4则取 \(q\in[-8,7]\),通常令 \(s=\max(|x_{\min}|,|x_{\max}|)/7\)、 \(q=\mathrm{clip}(\mathrm{round}(x/s),-8,7)\)、 \(\hat{x}=sq\)。具体范围、分组粒度和舍入规则由格式与 kernel 决定。

不同算法的差别在于:怎么算 scale 和 zero_point、怎么处理 outlier、怎么补偿量化误差。

上述非对称公式假设非零范围且需要让零可表示;实践通常把 0 纳入校准范围。退化的常量范围须单独处理,不能让 scale 为零。量化误差有两类:范围内的舍入误差,以及超出范围后被截断的 clipping 误差。缩小范围能细化刻度,却可能增加截断误差。

def quantize_uint4(x, x_min, x_max):
    """非对称 4-bit 无符号量化,返回整数、scale 与 zero point。"""
    q_min, q_max = 0, 15
    s = (x_max - x_min) / (q_max - q_min)
    # zero point 让实数 0 落在整数格点上
    z = min(max(q_min - round(x_min / s), q_min), q_max)
    q = min(max(round(x / s) + z, q_min), q_max)  # 超出范围即产生截断误差
    return q, s, z


def dequantize_uint4(q, s, z):
    return s * (q - z)


def quantize_int4(x, absmax):
    """对称有符号量化:q 取 [-8, 7],zero point 恒为 0。"""
    s = absmax / 7
    return min(max(round(x / s), -8), 7), s

15.2.1 对称与非对称

风格 假设 适合
对称量化 用 0 为中心的整数范围,通常令 \(z=0\),公式更简单 常见于权重
非对称量化 用 scale 与 zero point 对齐非对称范围 常见于激活值,也可用于权重

15.2.2 粒度与训练方式是另外两条轴

维度 选择与代价
per-tensor / per-channel / per-group 粒度越细,通常越能适应局部分布,但 scale/零点元数据更多,kernel 布局更复杂
静态 / 动态激活量化 静态范围来自校准,运行开销较小但怕分布漂移;动态范围在运行时估计,增加归约和缩放开销
PTQ 在训练后量化,常用少量校准数据,不进行完整量化感知训练
QAT 训练时模拟或引入目标量化误差,常用近似梯度,使权重适应低精度;需要训练数据和额外优化成本

W4A16 表示 4-bit 权重、16-bit 激活,不等于所有矩阵乘法都用 INT4 算术,也不包含 KV 精度。W8A8、FP8、NF4 的数值编码与计算路径不同,不能只按「几 bit」认定可互换。

例如每 128 个 4-bit 权重共用一个 16-bit scale,仅这一项元数据就使平均位宽变为 4 + 16/128 = 4.125 bit;再加零点、对齐和保留高精度的层,实际文件会更大。这是存储示例,不指定某个 checkpoint 的布局。

15.2.3 FP8、FP4 与 INT8、INT4 有什么不同?

线性整数格式的量化级别是均匀网格:scale s 为正、采用就近舍入且不发生截断时,绝对误差上界为 s/2;这不是截断误差的上界,也不适用于所有舍入模式。浮点格式把一部分位分给指数,级别间距随数值大小增长。在就近舍入且不发生溢出的条件下,正规数范围内的相对舍入误差上界大致恒定。次正规数的绝对间距固定,因此接近零时相对误差可能增大,甚至把非零小值舍入为零。位宽相同时,浮点格式牺牲范围上端的一部分分辨率,换来大得多的动态范围。两者没有谁在所有情况下都更精确。

FP8 论文定义了两种 8-bit 编码:

属性 E4M3 E5M2
指数位 / 尾数位 4 / 3 5 / 2
指数偏置 7 15
最大有限值 448 57,344
最小正规数 / 次正规数绝对值 2^-6 / 2^-9 2^-14 / 2^-16
特殊值 不表示无穷大;NaN 只占一个尾数位模式 沿用 IEEE 风格的无穷大与 NaN
论文建议用途 权重与激活值 梯度

E4M3 放弃无穷大,把最大值扩展到 448;E5M2 多留一位指数,以一位尾数为代价覆盖梯度的宽范围。NVIDIA Transformer Engine 的 HYBRID 配方采用同样的分工:前向用 E4M3,反向用 E5M2。

FP8 通常需要缩放,因为两种格式的范围都装不下任意张量。一种选择是把当前张量或块的绝对值最大值映射到格式最大值附近,但配方不止这一种。Transformer Engine 还支持逐张量的延迟缩放(delayed scaling),使用此前迭代的绝对值最大值,并可通过可配置的 margin 留出余量,不一定精确贴合当前最大值。这里的 s 指反量化乘数:量化时计算 x/s,重构时计算 s*q;有些 API 则把它的倒数称为 scaling factor。

下面沿用前面示例的范围 [-2.5, 2.5] 做一个可以手算的对比,两种格式都选择按当前最大值缩放。对称 INT8 取 s = 2.5/127;E4M3 取逐张量 scale s = 2.5/448,两者都舍入到最近的可表示值:

原值 INT8:整数码 → 反量化值 E4M3:缩放后的值 → 最近级别 → 反量化值
0.7 36 → 0.7087,相对误差 1.2% 125.44 → 128 → 0.7143,相对误差 2.0%
0.01 1 → 0.0197,相对误差 97% 1.792 → 1.75 → 0.00977,相对误差 2.3%

在这个范围的上端,INT8 的均匀步长比 E4M3 的 3 位尾数更细;对仍处于 E4M3 缩放后正规数范围内的小数值,INT8 只剩寥寥几个整数码,E4M3 则保持相近的相对精度。所以同样 8 bit,FP8 可能更能容忍带离群值的激活等宽动态范围数据,而贴合窄且规整分布的 INT8 网格可能更精确。应按目标张量的实际分布和任务评测来选,不要套经验口诀。

块缩放 FP4。 4-bit 的 E2M1 浮点只能表示 0, 0.5, 1, 1.5, 2, 3, 4, 6 这几个绝对值。当不同局部的数值范围差异较大时,整个张量共用一个 scale 可能丢失过多信息。E2M1 本身并不要求块缩放;MXFP4 和 NVFP4 为每个小块配置 scale,以缓解这一问题:

格式 元素类型 块大小 块 scale 平均位宽(数据 + scale)
MXFP4,OCP MX v1.0 E2M1 32 E8M0:2 的整数次幂 4 + 8/32 = 4.25
NVFP4,NVIDIA E2M1 16 E4M3,另加一个 FP32 逐张量 scale 4 + 8/16 + 32/N = 4.5 + 32/N

这里的 N 是一个 NVFP4 张量中共用一个 FP32 scale 的数值个数。上述计算假设每个块都填满,不计填充、对齐和其他元数据。

OCP MX 规范还用同样的 32 元素 E8M0 块 scale 定义了 MXFP8、MXFP6 和 MXINT8。下面的示例采用微软 MX 库实现的最大指数缩放方法,并明确选择「就近舍入、平局取偶」(round="even")。这是一个转换配方,并不要求所有 MX 实现都采用相同的 scale 选择和舍入方式。

对只含有限 FP32 数且不全为零的块,记绝对值最大值为 amax,则 E2M1 的块 scale 为 X = 2^max(floor(log2(amax)) - 2, -127)。未触及 scale 下限时,它等于不超过 amax 的最大 2 的幂,再除以 E2M1 中最大的 2 的幂,即 4。E8M0 的有限 scale 范围为 2^-127 到 2^127,极小数值块需要钳制到 scale 下限。全零块需要一个非零 scale;NaN 和无穷大的处理应遵循转换器策略,不能套用这个有限输入公式。每个元素除以 X 后舍入到 E2M1 网格,并饱和到 ±6。若某块的绝对值最大值为 2.5,则 X = 2/4 = 0.5:

  • 0.7 / 0.5 = 1.4 舍入为 1.5,反量化为 0.75;
  • 2.5 / 0.5 = 5 恰好落在 4 和 6 中间,平局取偶选 4:4 的 E2M1 编码为 0110,有效数最低位为 0,而 6 的编码为 0111,最低位为 1;不是看十进制数值是否为偶整数。块内最大值反量化为 2.0,误差 20%;
  • 0.01 / 0.5 = 0.02 舍入为 0,信息丢失。

在这个最大指数缩放配方下,未触及 scale 下限时,缩放后的块最大值落在 [4, 8):要么处在 E2M1 网格最稀疏的一段,要么被饱和处理。NVFP4 用更小的块和可取小数的 E4M3 scale 更贴合每块的范围,代价是更多 scale 元数据和第二级缩放。两种设计都不能免去质量评测。

由此有两点实践结论:

  • 格式不等于量化方法。 FP8、MXFP4 只规定编码方式;如何选 scale、如何校准、模型是否需要在该误差下训练,仍是独立的决策。OpenAI 的 gpt-oss 模型卡报告:占全部参数 90% 以上的 MoE 权重被量化为 MXFP4,每参数 4.25 bit,模型在后训练阶段就带着这种量化。模型卡称 gpt-oss-120b 可放进一张 80 GB GPU,其 checkpoint 为 60.8 GiB;4.25 bit 不是所有模型参数的平均位宽,checkpoint 大小也不包含运行时的 KV Cache 和 workspace。这个结果属于该模型及其训练流程,不适用于任意上下文长度或并发,也不能说明任意 BF16 checkpoint 都能无损转成 FP4。
  • 核对具体变体与硬件路径。 NVIDIA 从 H100 开始提供 FP8 Tensor Core 支持,Blackwell 又加入 NVFP4 和 MXFP8。AMD CDNA3(MI300 系列)使用 FP8 的 FNUZ 变体,CDNA4 则改用 OCP 的 E4M3FN 与 E5M2。E4M3FNUZ 最大值为 240,没有负零,只有一个 NaN。除负零外,每个表示有限 E4M3FN 数的字节按 E4M3FNUZ 解读时,数值都减半,包括次正规数和最高范围的有限值。但 0x80 在 E4M3FN 中是负零,在 E4M3FNUZ 中是 NaN;FN 的 NaN 编码 0x7F 和 0xFF 在 FNUZ 中则分别表示 +240 和 −240。

对于从 FN 转为 FNUZ 的有限权重,所引用的固定版本 vLLM 实现会把 0x80 改为 0x00,按 FNUZ 解读其余字节,并将反量化 scale s 加倍。只要加倍后的 scale 仍能表示,这样就能保持数值不变,包括次正规数,但会丢失零的符号。源数据中的 NaN 则必须拒绝或显式映射到 FNUZ 的 0x80,不能悄悄变成有限权重。这不是通用的数值类型转换,也不是可逆的字节复制配方:反向转换时,FNUZ 中表示有限值 ±240 的编码在 FN 中是 NaN。缺少原生 kernel 时,运行时可能先反量化到更高精度;是否节省显存或时间取决于实际执行路径。

15.3 各位数的精度边界

量化位数 7B 权重的理想裸存储 质量风险 实用性
FP16 14 GB 相对基线 训练与推理均可使用
INT8 7 GB 通常较低,仍需验证 常见折中
INT4 3.5 GB 对格式和任务更敏感 常见部署选择
INT3 2.6 GB 风险更高 资源受限时评估
INT2 1.75 GB 风险很高 仅在专门验证后使用

15.3.1 不存在固定的位宽断崖

位宽降低通常使误差控制更难,但不存在统一的「INT4 到 INT3 必然陡降、INT2 不能用」。模型大小、group size、量化算法、校准数据和任务都会改变曲线;GPTQ 原论文及作者实现就包含 2/3/4-bit 实验。

%%{init: {"flowchart": {"nodeSpacing": 16, "rankSpacing": 22, "padding": 8, "wrappingWidth": 160}}}%%
flowchart TB
    A["高精度基线"] --> B["选择格式与分组"]
    B --> C["量化并验证质量"]
    C --> D["测容量、吞吐与延迟"]
    D --> E["按业务约束决定是否降位"]

    style C fill:#e6f4ea
    style E fill:#fdecea

即使 INT8 也不是绝对无损。需要检查数学、代码、长上下文和工具调用,不能只看一项困惑度。

15.3.2 平均精度损失掩盖了任务差异

精度损失不是均匀分布的。

任务类型 常见风险
简单分类、抽取 可能较小,但与校准集相关
通用对话 需要质量与风格回归测试
数学推理 对误差、格式和长链推理可能更敏感
长链路代码生成 应测编译、测试通过率与长上下文退化

GPTQ 和 AWQ 分别通过输出重构与激活感知缩放改善低比特权重量化,不能只用任务难度概括其机制。

15.4 GPTQ:基于误差补偿的逐层量化

直接逐元素 round-to-nearest(RTN)不考虑输入通道相关性,相同大小的权重误差可能产生很不相同的输出误差。

GPTQ 逐层近似最小化校准集上的输出重构误差:

\[ \min_{\widehat W}\left\Vert WX-\widehat WX\right\Vert_F^2 \]

其中量化后的权重必须受目标量化网格约束,否则直接取原权重即可使误差为零。X 是当前线性层的校准输入。该二次目标的 Hessian 与 XXᵀ 有关,不是对完整语言模型训练损失计算精确 Hessian。量化一列后,用二阶信息修正同一层剩余未量化的权重,通常配合阻尼和分块更新以提高稳定性与效率。

15.4.1 流程

%%{init: {"flowchart": {"nodeSpacing": 16, "rankSpacing": 22, "padding": 8, "wrappingWidth": 160}}}%%
flowchart TB
    S1["校准输入"] --> S2["收集当前层统计量"]
    S2 --> S3["量化当前层"]
    S3 -->|下一层| S2
    S3 -->|所有层完成| DONE["导出权重"]

使用有代表性的校准输入。对每一层,收集其输入并构造带阻尼的二阶信息。下面的内循环按照指定顺序量化各列,而不是默认先量化最不重要的权重。

%%{init: {"flowchart": {"nodeSpacing": 16, "rankSpacing": 22, "padding": 8, "wrappingWidth": 160}}}%%
flowchart TB
    Q["量化下一列"] --> C["补偿剩余权重"]
    C -->|还有未量化列| Q
    C -->|所有列完成| D["当前层完成"]

补偿只更新同一层尚未量化的权重。完成这一层的列循环后,才收集下一层的输入。

15.4.2 优缺点

优点 缺点
利用输入相关性补偿输出误差 二阶矩阵、分解与更新带来校准时间和内存开销
可评估 2/3/4-bit 与不同分组 低位宽能否满足质量要求需实测
经典方案为 weight-only,不需要全模型重训练 激活常保持高精度;能否加速取决于 kernel,不必然慢于 AWQ

原算法可用固定列顺序;作者后来加入的 act-order 是按激活大小降序量化,不是「优先量化不重要权重」。工具是否仍维护与 GPTQ 算法是否可用是两回事,新部署需检查当前模型支持和输出格式。

15.5 AWQ:激活感知的权重保护

MIT 提出的思路很直接:先找出真正需要保护的权重。

15.5.1 洞见:保护激活敏感的通道

AWQ 论文用「保留约 1% 显著权重为高精度」的对照实验说明,不同权重的量化敏感度差异很大。论文没有给出“1% 权重贡献 99% 输出”的定律,实际 AWQ 也不是必须将这 1% 存成 FP16。

15.5.2 怎么保护:依据输入激活做缩放

对线性层 Y=WX,权重误差引起的输出变化为 ΔY=ΔW·X,因此输入通道的幅度和相关性都重要。

若某些输入通道的激活幅度较大,同样的权重误差会更强地影响层输出。AWQ 使用校准输入的逐通道幅度,而不是只按权重绝对值排序。

设 S 是正的对角缩放矩阵,量化前有等价关系:

\[ WX=(WS)(S^{-1}X) \]

对 WS 量化、同时反向缩放输入,可减小部分显著通道的输出误差;输入缩放通常可合并到前序算子。缩放也可能扩大所在 group 的量化范围,损害其他通道,因此 AWQ 搜索缩放强度并进行裁剪,而非简单无限放大重要权重。

等价的是量化前的缩放变换;量化后的模型仍有误差,不能据此声称 AWQ 与原模型输出完全相同。

15.5.3 优缺点

优点 缺点
可使用高效 kernel:权重布局可针对目标硬件优化 极端低位的表现要实测;不同模型与实现结论可能相反
激活感知缩放:可改善部分模型的低比特质量 同样需要校准数据
不需要 GPTQ 式的二阶矩阵分解 缩放搜索、裁剪和校准仍有耗时,不能按参数量给固定分钟数

AWQ 与 GPTQ 都需比较质量和实际执行路径。W4A16 在低批量、权重带宽受限时可能有效;大批量 prefill 中,反量化和 GEMM 效率可能改变结论。

不混淆层次:GPTQ/AWQ 是算法,FP8/NF4 是数值格式,Marlin/CUTLASS 属于执行内核或内核库,GGUF 是容器。AutoAWQ 官方仓库已声明弃用并指向 llm-compressor;不要把旧工具安装教程当作算法的当前支持矩阵。

15.6 QLoRA 如何在冻结的低比特基座上微调?

QLoRA 冻结低比特基座,训练附加的高精度 LoRA 参数;它降低基座存储,却不把所有训练计算都变成 4-bit。GPTQ 和 AWQ 主要解决部署时的权重量化,QLoRA 则把量化与适配器训练结合起来。

15.6.1 NF4 是非均匀量化

普通 INT4 是均匀分隔(16 个值平均分布)。

NF4 针对近似正态分布的权重设计非均匀 codebook,零附近刻度更密,尾部更稀。实际权重不必严格正态,分块归一化也会改变分布;该假设不是所有张量的保证。

它在 QLoRA 论文的设置中优于所比较的均匀整数或浮点 4-bit 格式,不代表对任意模型和指标均最优。

15.6.2 另外两个优化

优化 作用
双重量化 连量化用的 scale 常数也再量化一次,进一步省显存
分页优化器 用统一内存在 CPU/GPU 间迁移优化器状态,缓解部分显存峰值;迁移有性能成本,也不能消除所有 OOM

QLoRA 论文报告过在单张 48 GB GPU 上微调 65B 的配置,这是特定序列长度、batch、优化器与检查点设置下的结果,不能变成按显存选模型的通用表。长上下文激活仍可能主导峰值。详见第八章。

关键是冻结 4-bit 基座,只训练高精度 LoRA 适配器;计算时按需反量化,让梯度通过基座计算路径传给适配器。它不是直接用梯度更新离散 INT4/NF4 编码,也不等同于全参数 QAT。

15.7 怎么选

场景 推荐方案 理由
生产部署,看重速度 AWQ / GPTQ / FP8 / 框架原生 INT4 看目标框架和 GPU kernel 支持,不能只背一个名字
部署质量优先 高精度基线,再比较 INT8 / INT4 以业务允许的退化为门槛,不承诺量化无损
显存受限的适配器微调 QLoRA NF4 先估算激活、适配器和优化器峰值
边缘部署(手机 / 笔记本) 设备运行时支持的低比特格式,如 GGUF 的 Q4_K_M 检查内存、带宽、功耗与算子支持
CPU 部署 llama.cpp + GGUF 无 GPU 也能跑

15.7.1 三个关键提示

① AWQ vs GPTQ 怎么选

先查目标模型、GPU 与框架支持的量化格式,再在相同位宽、分组、校准集和业务评测下比较。已有权重文件及转换成本也影响选择,不预设 AWQ 速度更快或 GPTQ 精度更高。

不要脱离框架支持谈算法好坏。 最后跑得快不快,取决于量化格式和推理 kernel 是否匹配。

② INT4 vs INT8 怎么选

显存够时用高精度作为质量基线;容量或权重带宽紧张时评估低位宽。若瓶颈是长上下文 KV 而非权重,仅降低权重位宽可能不够;若瓶颈是大批量计算,要看 W8A8/FP8 等算术路径,而不只是压缩率。

③ GGUF 是什么

GGUF 不是量化算法,是 llama.cpp 用的文件格式。

它内部可以存各种量化方案的权重(Q4_K_M、Q5_K_M、Q8_0 等),是一个容器。这跟 AWQ/GPTQ 这种「算法」不是一个层级——混淆这两者是很常见的错误。

15.8 四个副作用与陷阱

15.8.1 Outlier 异常值问题

当一组权重中出现幅度很大的异常值,按最大值定范围会拉宽量化刻度,使该组普通权重的分辨率下降;影响程度取决于分布与分组。

应对:分组缩小受异常值影响的范围,裁剪在尾部误差与主体分辨率间取舍。AWQ 依据激活敏感度缩放,GPTQ 依据输入相关性补偿,都不是简单「找出最大权重优先保护」。SmoothQuant 则通过等价缩放把激活量化难度转移到权重,服务于 W8A8;不要与 AWQ 的权重量化目标混淆。

15.8.2 KV Cache 量化的挑战

KV Cache 已有研究与框架实现,不能用「才刚起步」判断可用性;支持情况取决于模型架构、attention 后端和目标位宽。

在部分长上下文或高并发负载中,KV 可超过权重(见第十四章)。K 的误差影响注意力分数,V 的误差影响聚合结果;实际收益还要计入 scale、残留窗口和转换成本,测长文检索及推理质量。

15.8.3 不同任务的敏感度差异巨大

不存在可迁移的“INT4 平均损失”。部署量化模型前必须在自己的业务场景下做评测,不能直接套用论文或他人的平均数。

15.8.4 与其他优化的兼容性

量化要和 Flash Attention、KV Cache、Speculative Decoding 同时使用,不同框架支持度差别很大。

选量化方案前先看部署框架支持哪些,再用自己的业务集压测质量和吞吐。

15.9 常见错误

15.9.1 说不出量化的基本机制

线性整数格式常用 scale + zero point,NF4 则通过非均匀 codebook 表示;先确定格式再解释映射。

15.9.2 认为精度损失是线性的

损失未必线性,也不存在统一断崖;更换 group size、校准或算法可以改变曲线。

15.9.3 给 INT4 套用统一精度损失

数学推理与长链代码等任务可能更敏感;必须在自己的业务集实测。

15.9.4 说不出 GPTQ 和 AWQ 的核心创新

GPTQ 用校准输入的二阶信息补偿同层未量化权重;AWQ 用激活感知缩放与裁剪保护敏感通道,两者通常都属于 PTQ。

15.9.5 把 GGUF 当成量化算法

它是文件格式、是容器,跟 AWQ/GPTQ 不是一个层级;扩展名也不能说明具体量化精度。

15.9.6 脱离框架和 GPU 谈算法好坏

跑得快不快取决于量化格式与推理 kernel 是否匹配。

15.9.7 忽略 outlier 问题

异常值会放宽所在量化组的范围;权重异常值、激活异常值与输出敏感性并非同一概念。

15.9.8 认为量化模型不能再训练

QLoRA 训练的是适配器,冻结的低比特基座参与前向和梯度传播路径,不是直接更新整数编码。

15.10 本章总结

  1. 线性整数均匀量化常用 scale + zero point 映射;NF4 等非均匀格式使用 codebook,不能一概而论;
  2. FP8 与 FP4 是浮点网格:就近舍入在正规数范围内具有大致恒定的相对误差上界,不能推广到下溢或溢出附近;缩放配方仍需单独选择。MXFP4 与 NVFP4 的块大小和 scale 编码不同,E4M3FN 与 E4M3FNUZ 等 FP8 变体也不能按位互换;
  3. 两个潜在收益:4-bit 权重裸存储与权重访存量可降至 FP16 的四分之一;端到端速度取决于 kernel 和工作负载;
  4. 对称量化常用于权重,非对称量化常用于激活,但不是硬规则;应以格式、kernel、校准数据和任务评测为准;
  5. 位宽越低通常越需谨慎评测;INT8、INT4、INT3 的实际边界不能脱离模型、格式与任务;
  6. 平均指标掩盖任务差异,应分别测试数学、代码、长上下文和结构化输出;
  7. GPTQ 使用逐层重构目标的二阶信息补偿量化误差,不是默认先量化低重要性权重;
  8. AWQ 用激活感知缩放与裁剪改善权重量化,等价变换不代表量化无损;
  9. QLoRA 使用冻结 NF4 基座与可训练适配器,配合双重量化和分页优化器降低微调显存;
  10. GGUF 是文件格式不是算法,是最容易混淆的一点;
  11. 选型不能脱离框架和 GPU kernel,最终性能取决于格式与 kernel 是否匹配;
  12. 四个陷阱:异常值、KV 精度与后端限制、校准/任务分布差异、与其他优化的兼容性。

参考资料

本章的参考资料、阅读建议与来源说明见集中参考资料章节。