量化、蒸馏与剪枝:把大模型压缩到可部署¶
本章导读 量化决定“能不能装下、跑得快不快”,蒸馏决定“小模型能不能学到能力”,剪枝决定“能不能真正省掉计算”。 三者经常组合使用:先剪枝或蒸馏得到结构,再量化压缩,最后用评测确认没有丢掉长尾能力。 本文覆盖主流量化公式与算法、误差来源、蒸馏目标、稀疏与结构化剪枝,以及与投机解码、MoE 的关系。 文中比特数、加速比和显存数字均为量级/估算,具体以公开资料、实现和评测集为准。
核心要点¶
- 量化(quantization)的本质是把浮点张量映射到低比特整数或 FP8,并用缩放因子与零点还原,误差来自截断和舍入。
- 对称量化适合零中心权重,非对称量化适合有偏激活;粒度越细精度越高,但元数据与 kernel 开销更大。
- GPTQ 用 Hessian 做逐列误差补偿,AWQ 用激活感知缩放保护显著通道,SmoothQuant 把激活离群值迁移到权重。
- FP8 在 Hopper 及更新硬件上兼具动态范围与吞吐,E4M3 适合前向,E5M2 适合梯度。
- 量化对 WikiText 困惑度的伤害可能很小,但对数学、代码、长上下文和多语言等长尾能力可能很大。
- 蒸馏(distillation)不只是模仿 logits,序列级、on-policy 和带推理链的数据蒸馏各有适用场景,温度 \(T\) 与权重 \(\alpha\) 需要调。
- 非结构化剪枝(pruning)省显存但未必省时间,2:4 半结构化稀疏能吃到硬件加速,结构化剪枝才能直接降低计算量。
1. 量化(quantization)基础¶
1.1 仿射量化与反量化¶
最通用的量化形式是仿射映射(affine quantization):
\(x\) 是 FP16/BF16 浮点值,\(s>0\) 是缩放因子(scale),\(z\) 是零点(zero point),\(q\) 是低比特整数,\(\hat{x}\) 是反量化后的近似值。\(q_{min}\) 和 \(q_{max}\) 由比特数决定,例如 INT8 为 \(-128\) 和 \(127\),INT4 为 \(-8\) 和 \(7\)。
对称量化令 \(z=0\),只保留缩放:
\(b\) 是比特数。对称量化的整数范围通常取 \([-(2^{b-1}-1), 2^{b-1}-1]\),避免使用 \(-2^{b-1}\) 造成正负不对称。权重通常以 0 为中心,适合对称量化。
非对称量化同时使用 scale 和 zero point:
\(x_{max}\)、\(x_{min}\) 是张量或分组内的最大最小值。非对称量化能更充分地利用整数范围,适合明显偏置的激活,但 zero point 会增加存储和 kernel 复杂度。
1.2 量化粒度¶
| 粒度 | 缩放因子数量 | 精度 | 开销与适用场景 |
|---|---|---|---|
| per-tensor | 整个张量 1 个 | 最低 | 开销最小,离群值会拉低整体精度 |
| per-channel | 每个输出通道 1 个 | 较高 | 权重常用,沿输出维度独立缩放 |
| per-group | 每 \(g\) 个权重 1 个 | 最高 | 常见 \(g=64\) 或 128,需存 scale/zero |
| per-token | 每个 token 1 个 | 较高 | 激活常用,按 token 动态统计 |
| per-block | 二维块 1 个 | 高 | FP8 训练/推理常用,如 128×128 |
分组量化的有效比特数不是 4,而是:
\(b_{scale}\) 是缩放因子比特数,\(b_{zero}\) 是零点比特数(对称量化可省略),\(g\) 是分组大小。W4、\(g=128\)、FP16 scale、无 zero point 时,\(b_{eff}=4+16/128=4.125\) bit;若再加 FP16 zero point,则为 4.25 bit。\(g=64\) 时分别升到 4.25 和 4.5 bit。这就是“4 bit 模型实际约 4.1 到 4.5 bit/权重”的来源。
1.3 weight-only、W8A8 与 PTQ/QAT¶
- weight-only:只量化权重,激活保持 FP16/BF16,典型是 W4A16。反量化后仍用 FP16 张量核心计算,主要收益是显存和带宽,适合 memory-bound 的 decode。
- W8A8:权重和激活都量化到 8 bit,可用 INT8 张量核心,prefill 和大 batch 吞吐提升明显,但激活离群值难处理。
- W4A8:权重 4 bit、激活 8 bit,介于两者之间,需要专门的混合精度 kernel,硬件支持不如 W8A8 成熟。
- FP8:权重和激活用 E4M3/E5M2,Hopper、Ada 及更新架构原生支持,训练和推理都可受益。
PTQ(post-training quantization)在训练完成后用校准数据统计 scale,成本低、部署快,是主流选择。QAT(quantization-aware training)在训练中模拟量化误差,通常用直通估计器(straight-through estimator, STE)传梯度:
QAT 在 2 到 4 bit 等极端压缩下明显优于 PTQ,但需要训练资源和原始数据,工程周期长。多数开源量化模型是 PTQ 结果。
1.4 对称量化与反量化代码¶
import torch
def quantize_sym(x, bits=8):
qmax = 2 ** (bits - 1) - 1 # 对称范围 [-qmax, qmax]
scale = x.abs().amax().clamp_min(1e-8) / qmax
q = torch.round(x / scale).clamp(-qmax, qmax).to(torch.int8)
return q, scale # q 为整数,scale 为浮点
def dequantize_sym(q, scale):
return q.to(scale.dtype) * scale # 还原到浮点域
这段代码是 per-tensor 版本,生产实现通常按输出通道或分组计算 scale,并把 scale 与打包后的 4 bit 权重一起存储。
2. 主流量化方法¶
2.1 GPTQ:逐层误差补偿¶
GPTQ 把量化看成逐层的重建问题。给定一层的输入 \(X\) 和权重 \(W\),目标是最小化:
\(X \in \mathbb{R}^{n \times d_{in}}\) 是校准数据经该层得到的输入,\(W,\hat{W} \in \mathbb{R}^{d_{in} \times d_{out}}\) 是原始与量化权重。对 \(W\) 的每一列依次量化,并用剩余列的 Hessian 逆做误差补偿:
\(H = 2X^{T}X\) 是近似 Hessian,\([H^{-1}]_{jj}\) 是其逆的第 \(j\) 个对角元素,\(w_j\) 是第 \(j\) 列,\(\hat{w}_j\) 是量化后的列。直觉是:某一列量化产生的误差,按 Hessian 逆的比例分摊到尚未量化的列,使整层输出误差最小。
def gptq_layer(W, H, bits=4):
# 伪代码:省略分块、act-order 与数值稳定处理
W = W.clone().float()
H_inv = torch.cholesky_inverse(torch.linalg.cholesky(H))
Q = torch.zeros_like(W, dtype=torch.int8)
for j in range(W.shape[1]):
q, scale = quantize_sym(W[:, j], bits)
Q[:, j] = q
err = W[:, j] - q.float() * scale # 当前列的量化误差
W[:, j + 1:] -= torch.outer(err / H_inv[j, j], H_inv[j, j + 1:])
return Q
GPTQ 论文报告可在约 4 个 GPU 小时内量化 175B 模型(量级,具体硬件未在本文展开),3 到 4 bit 在困惑度上接近 FP16,2 bit 明显退化。工程实现会加入分块(block size 128)、act-order(按激活大小重排列)、Cholesky 分解和阻尼,以提升数值稳定性。
2.2 AWQ:激活感知的显著通道缩放¶
AWQ(activation-aware weight quantization)观察到:权重的重要性不由权重本身决定,而由对应激活的 magnitude 决定;少数“显著通道”对量化误差非常敏感。它不直接保留 FP16 权重,而是对权重做逐通道缩放:
\(s \in \mathbb{R}^{d_{in}}\) 是逐输入通道的缩放向量。因为 \(X'W' = XW\),缩放不改变数学结果,但会改变每个通道的相对量化误差。显著通道乘上更大的 \(s\),其在分组量化中的相对分辨率提高,误差被保护;同时激活被反向缩小,避免溢出。
缩放因子通常从激活统计量搜索:
\(\alpha \in [0,1]\) 是搜索的超参数,常见做法在 0 到 1 之间网格搜索,或在每组内用 \(\|X_j\|\) 的幂次。AWQ 还会保留约 0.1% 到 1% 的显著权重不量化,以较小存储代价换取精度。它不需要反向传播,校准成本低,典型配置是 W4A16。论文报告在 TinyChat 上相对 FP16 有约 3 倍加速(量级,依赖硬件与批次)。
2.3 SmoothQuant:把激活离群值迁移到权重¶
LLM 的激活中存在幅值极大的离群通道,直接做 INT8 激活量化会严重截断。SmoothQuant 利用线性层的等价变换,把量化难度从激活迁移到权重:
\(X_{t,j}\) 是第 \(t\) 个 token 在第 \(j\) 个输入通道的激活,\(W_{i,j}\) 是对应权重。\(\alpha\) 控制迁移强度:\(\alpha=1\) 时完全按激活缩放,\(\alpha=0\) 时不缩放。\(s_j\) 让激活和权重的动态范围更接近,从而使 W8A8 的逐张量量化可行。
SmoothQuant 论文报告在 OPT、BLOOM、Llama 等模型上实现 W8A8,内存减半、速度提升约 1.56 倍(量级),同时保持精度。它的前提是线性层对输入通道缩放不变,因此不能随意插入非线性层;LayerNorm、激活函数和残差连接的位置需要仔细处理。
2.4 LLM.int8():混合精度分解¶
LLM.int8() 的核心观察是:激活中约 0.1% 的特征幅值远大于其他特征(论文以超过 6 倍标准差为阈值),这些离群特征如果被 INT8 量化会破坏结果。它把矩阵乘拆成两部分:
\(X_{out}\) 是离群特征对应的子矩阵,用 FP16 计算;\(X_{int}\) 是其余特征,用 INT8 向量级量化计算。最后把两部分结果相加。这样既保留了 INT8 的吞吐和显存优势,又避免了离群值导致的精度崩溃。
LLM.int8() 的意义在于让大模型 INT8 推理在消费级硬件上可行,但它的反量化与拼接开销较大,在某些 GPU 上不一定比 FP16 快。它更适合显存受限、吞吐要求不极致的场景。
2.5 FP8:E4M3 与 E5M2¶
FP8 有两种常用格式:
| 格式 | 符号位 | 指数位 | 尾数位 | 最大有限值 | 最小正规数 | 特点 |
|---|---|---|---|---|---|---|
| E4M3 | 1 | 4 | 3 | 448 | \(2^{-6}\approx 0.0156\) | 精度较高,适合前向权重/激活 |
| E5M2 | 1 | 5 | 2 | 57344 | \(2^{-14}\approx 6.1\times10^{-5}\) | 动态范围大,适合梯度 |
E4M3 的尾数多一位,量化噪声更小,但范围窄,需要缩放因子把数值映射到可表示区间;E5M2 范围大但精度低,常用于反向传播的梯度。FP8 的缩放可以是 per-tensor、per-channel,也可以是 per-block。DeepSeek-V3 公开的技术报告使用 128×128 的权重块缩放和 1×128 的逐 token 激活缩放,并在部分敏感算子保留 BF16/FP32,这是大规模 FP8 训练的典型工程做法。
FP8 的收益依赖硬件:H100、H200、L40S、Ada 及更新架构支持 FP8 张量核心,A100 不支持。FP8 通常比 INT8 更容易保持精度,因为指数位提供了更大的动态范围,但块缩放会带来额外元数据和解量化开销。
2.6 GGUF 与 llama.cpp¶
GGUF 是 llama.cpp 使用的模型文件格式,包含元数据、分词器、张量和量化类型。它支持 mmap 加载,适合 CPU、Apple Silicon、消费级 GPU 以及边缘设备。常见的 K-quants 包括 Q4_K_M、Q5_K_M、Q6_K、Q8_0 等:
- Q4_K_M:主体 4 bit,部分敏感张量用更高比特,平均约 4.5 bit/权重。
- Q5_K_M:平均约 5.5 bit/权重,质量更稳。
- Q8_0:8 bit,接近 FP16,体积约为 FP16 的一半。
7B 模型的 GGUF 体积大致为:Q4_K_M 约 4.4 到 4.8 GB,Q5_K_M 约 5.4 到 5.8 GB,Q8_0 约 7.2 GB(量级估算,随分词器和模型结构变化)。llama.cpp 支持 importance matrix(imatrix)校准,用校准数据的激活统计指导量化,改善低比特质量。
GGUF 的强项是部署简单、硬件覆盖面广、单机低并发延迟低;弱项是高并发吞吐、连续批处理和分布式推理能力不如数据中心级框架。
2.7 方法对比¶
| 方法 | 典型配置 | 是否需要校准 | 主要收益 | 主要局限 |
|---|---|---|---|---|
| GPTQ | W4A16、W3A16 | 是 | 4 bit 精度好,生态成熟 | 依赖 Hessian,2 bit 退化 |
| AWQ | W4A16 | 是 | 保护显著通道,部署快 | 主要是 weight-only |
| SmoothQuant | W8A8 | 是 | 激活离群值迁移,INT8 吞吐 | 对结构有假设 |
| LLM.int8() | W8A8 混合 | 否 | 离群值鲁棒 | 反量化开销,速度不稳定 |
| FP8 | W8A8 | 是或动态 | 范围与吞吐平衡 | 需要新硬件 |
| GGUF | Q4_K_M 等 | 可选 | 边缘/CPU 友好 | 高并发能力弱 |
3. 量化误差与评估¶
3.1 误差来源¶
- 截断误差(clipping error):离群值超出量化范围被截断,往往比舍入误差更致命。
- 舍入误差(rounding error):浮点到整数的最近邻舍入,随比特数降低而增大。
- 分组边界误差:同一组内动态范围差异大时,scale 被少数大值主导,小值分辨率不足。
- 激活离群值:少数通道幅值极大,per-tensor 量化会牺牲其余通道。
- 误差累积:每层的小误差经过数十层传播,可能在注意力 logits 或残差中被放大。
- 部署误差:KV Cache 量化、算子融合、不同 kernel 的累加精度都会引入额外差异。
3.2 评估指标¶
困惑度(perplexity, PPL)是最常用的快速指标,通常在 WikiText-2 上计算:
\(N\) 是 token 数,\(p(x_i \mid x_{<i})\) 是模型对第 \(i\) 个 token 的预测概率。PPL 对整体语言建模敏感,但对下游能力不敏感,不能作为唯一指标。
更完整的评估应覆盖:
- 任务指标:MMLU、GSM8K、HumanEval、BBH 等,观察绝对下降和相对下降。
- 长尾能力:数学推理、代码、多语言、长上下文检索、指令跟随、安全拒答。
- 生成质量:人工或模型裁判评估流畅性、事实性、格式遵循。
- 分布一致性:与 FP16 模型的 KL 散度、top-1 一致率、输出长度分布。
- 鲁棒性:不同 prompt 模板、随机种子、温度下的方差。
评估协议要固定 prompt、few-shot 数量、解码参数和种子,报告置信区间。量化模型可能在某个基准上只掉 1 分,但在长尾子集上掉 10 分,必须分桶看。
3.3 为什么小模型对量化更敏感¶
参数量越小,冗余越少,量化噪声更容易破坏关键表示。大模型有更多通道和层可以补偿误差,小模型的容量缓冲更小。此外,小模型的激活分布可能更尖锐,离群通道占比更高,per-tensor 量化更吃亏。
经验上(量级判断,需实测):70B 模型 4 bit 往往接近 FP16,7B 模型 4 bit 可能有可感知退化,1B 级模型在 4 bit 下更容易在数学、代码和长上下文上明显下降。因此小模型常采用 W8A8、FP8 或更细的分组量化,而不是直接上 W4。
3.4 KV Cache 量化与 W4A16/W4A8 取舍¶
KV Cache 量化的关键是 K 和 V 的分布不同。K 的离群值常集中在少数通道,适合 per-channel;V 的离群值随 token 变化,适合 per-token。常见做法是 FP8/INT8 KV,8 bit 通常接近无损,4 bit 在长上下文更容易退化。
| 配置 | 权重 | 激活 | 计算 | 优势 | 代价 |
|---|---|---|---|---|---|
| W4A16 | 4 bit | FP16 | 反量化后 FP16 | 显存/带宽最省,单流 decode 友好 | 不吃 INT8 算力,prefill 提升有限 |
| W4A8 | 4 bit | 8 bit | INT8/FP8 张量核心 | 高并发吞吐更好 | 激活量化误差,kernel 支持少 |
| W8A8 | 8 bit | 8 bit | INT8 张量核心 | 精度稳,生态成熟 | 显存压缩不如 4 bit |
| FP8 | 8 bit | 8 bit | FP8 张量核心 | 范围大,精度好 | 需要 Hopper 及更新硬件 |
W4A16 在 decode 阶段几乎只受带宽限制,权重从 16 bit 降到 4 bit,理论读取量降到四分之一,因此单用户速度提升明显。W4A8 在高并发、prefill 占比高的场景更有优势,但激活量化会引入额外误差,且并非所有框架都提供成熟 kernel。选择时要看瓶颈在带宽还是算力,不能只看比特数。
4. 知识蒸馏(knowledge distillation)¶
4.1 logits 蒸馏¶
教师模型(teacher)对学生模型(student)的输出分布进行监督。设教师 logits 为 \(z^T\),学生 logits 为 \(z^S\),温度为 \(T\):
蒸馏损失为:
\(y\) 是真实标签,\(q^{1}\) 是学生温度为 1 的预测,\(\alpha\) 是蒸馏权重,\(T^2\) 用来补偿温度对梯度尺度的缩放。softmax 对 logits 的梯度约为 \(1/T\),KL 项再乘 \(T^2\) 后,整体梯度量级与交叉熵接近,避免调温度时还要重调学习率。
温度的作用是“软化”分布:\(T\) 越大,教师输出的尾部概率越突出,学生能学到类别之间的相似性。常见 \(T\) 取 2 到 5,\(\alpha\) 取 0.5 到 0.9。温度过高会让分布接近均匀,丢失判别信息;温度过低则退化为硬标签。
4.2 序列级与 on-policy 蒸馏¶
- 序列级蒸馏(sequence-level distillation):让教师生成完整序列,学生用这些序列做监督微调。实现简单,适合把大模型的推理链、代码、对话能力迁移到小模型;缺点是只能看到教师“成功”的样本,缺少负样本和概率信息。
- on-policy 蒸馏:学生自己生成序列,再由教师对学生的输出打分或提供 token 级分布。这样训练分布与学生推理时的分布一致,能缓解 exposure bias(曝光偏差)。GKD(generalized knowledge distillation)用学生生成的数据配合教师反馈,在序列级任务上效果显著。
- 反向 KL:MiniLLM 等工作使用 \(\mathrm{KL}(q \| p)\) 而不是 \(\mathrm{KL}(p \| q)\),让学生集中覆盖教师分布的高概率区域,减少小模型在低概率区域的平均化倾向。反向 KL 容易模式坍缩,需要配合采样和正则。
4.3 教师选择与常见问题¶
教师不一定是越大越好。教师与学生容量差距过大时,学生难以拟合教师的分布,出现“容量鸿沟”。实践中的选择:
- 同家族、同分词器的更大模型,避免词表映射和对齐成本。
- 教师本身质量要高,教师的错误会被学生放大。
- 多教师集成或按领域路由,可以覆盖不同能力,但推理和训练成本更高。
- 用拒绝采样(rejection sampling)过滤教师输出,只保留答案正确的样本。
常见问题包括:教师数据污染评测集、学生只学会格式没学会推理、长链推理中的中间步骤错误、tokenizer 不一致导致 logits 无法对齐。蒸馏后仍要做端到端评测,不能只看训练损失。
5. 剪枝(pruning)¶
5.1 非结构化与结构化¶
| 类型 | 粒度 | 是否省显存 | 是否省计算 | 典型方法 |
|---|---|---|---|---|
| 非结构化 | 单个权重 | 是(稀疏存储) | 一般否,除非硬件支持 | magnitude、Wanda、SparseGPT |
| 半结构化 | 每 4 个权重保留 2 个 | 是 | 是,2:4 张量核心 | 2:4 稀疏 |
| 结构化 | 头、层、通道、FFN 维度 | 是 | 是 | 头剪枝、层丢弃、宽度剪枝 |
非结构化剪枝把不重要的权重置零,稀疏率可以很高,但 GPU 的稠密张量核心不会自动加速,除非使用 2:4 稀疏或专用稀疏库。结构化剪枝直接删除整块结构,能真实降低计算量,但对精度伤害更大,通常需要恢复训练或蒸馏。
5.2 Wanda 与 SparseGPT¶
Wanda(weights and activations)用权重幅值乘以对应输入激活的范数作为重要性分数:
\(W_{ij}\) 是第 \(i\) 个输出通道、第 \(j\) 个输入通道的权重,\(X_j\) 是该输入通道在校准集上的激活。比较时通常在同一个输出通道内排序,因为不同输出通道的尺度不可直接比较。Wanda 不需要重新训练,按“权重乘以激活”剪枝,在 50% 稀疏度下可与 SparseGPT 竞争。
SparseGPT 把剪枝建模为逐层重建问题:
它用 Hessian 近似做逐列剪枝和误差补偿,与 GPTQ 的思想同源。论文报告可在 175B 模型上以单 GPU 约 4.5 小时完成 60% 稀疏(量级),并支持 2:4、4:8 等半结构化模式。剪枝后通常需要少量恢复训练,用原始数据或蒸馏损失微调。
5.3 2:4 稀疏¶
2:4 稀疏要求每 4 个连续权重中恰好保留 2 个非零,硬件可以把稀疏矩阵压缩存储并用稀疏张量核心计算。A100、H100 等支持 2:4 稀疏,理论吞吐约为稠密的 2 倍。
实际收益取决于:
- 稀疏模式是否与硬件要求对齐,否则会被 padding 抵消。
- 精度恢复是否充分,50% 稀疏对 7B 以下模型可能明显掉点。
- kernel 是否真正调用了稀疏通路,很多框架只是存储稀疏,计算仍然稠密。
- 与量化叠加时的误差累积,稀疏加 4 bit 往往比单独任一更难恢复。
5.4 结构化剪枝与恢复¶
结构化剪枝的对象包括注意力头、FFN 中间维度、整个层、甚至把 MHA 改造成 GQA。它的优势是直接减少矩阵尺寸,真实提升速度、降低显存;劣势是搜索空间大、精度损失大。
常见流程:
- 用重要性分数(激活范数、梯度、Fisher 信息、贡献度)排序。
- 按硬件友好的粒度剪枝,例如每次删除 8 的倍数个通道。
- 用蒸馏或继续预训练恢复,数据量约为原预训练的 1% 到 5%。
- 评估延迟、显存和任务指标,确认不是“纸面稀疏”。
剪枝与量化可以组合,但顺序有讲究:先剪枝再量化,量化误差会作用在已经变小的模型上;先量化再剪枝,稀疏模式可能破坏量化分组。通常建议先做结构化剪枝,再做 PTQ,最后用少量数据校准。
6. 与投机解码、MoE 的关系¶
6.1 投机解码中的量化¶
投机解码的草稿模型可以量化,以减少显存和草稿成本,但量化会改变草稿分布 \(q\),从而影响接受率:
草稿越接近目标分布,接受率越高。若草稿用 4 bit、目标用 FP16,分布差异变大,接受率可能下降;但草稿更便宜,整体仍可能划算。需要端到端测“有效 tokens/s”,而不是只看单步接受率。
目标模型量化也会改变 \(p\),此时验证使用的是量化后的目标分布。若目标是 W4A16,输出分布与 FP16 有差异,投机解码的“无损”只相对于量化目标成立。对质量敏感的场景,建议目标模型保持 FP8/FP16,草稿模型量化。
6.2 MoE 的压缩¶
MoE(mixture of experts)总参数量大、每 token 只激活少数专家,显存容量和专家并行通信是主要瓶颈。量化 MoE 时要注意:
- 路由网络(router)对数值误差敏感,通常保留 FP16/BF16,不参与低比特量化。
- 不同专家的激活分布差异大,per-tensor 量化可能让某些专家退化,per-expert 或分组量化更稳。
- 专家权重占显存大头,W4 可以显著降低容量需求,但专家负载不均会导致某些 GPU 热点。
- 剪枝专家或合并专家可以减少显存和通信,但会改变路由行为,需要重新校准。
MoE 的 decode 仍然受带宽限制,但每次只读激活的专家,理论上比同等总参数的稠密模型便宜;显存中必须容纳全部专家,因此量化对 MoE 的容量收益尤其明显。专家并行(expert parallelism)下,量化还要与 all-to-all 通信的精度和带宽一起考虑。
6.3 组合顺序¶
一个常见的工程流水线是:
- 用蒸馏得到一个更小或更强的学生模型。
- 用结构化剪枝去掉冗余头/层/维度,并做恢复训练。
- 用 GPTQ/AWQ/FP8 做 PTQ,校准数据覆盖目标业务分布。
- 对 KV Cache 做 FP8/INT8 量化,评估长上下文。
- 需要低延迟时叠加投机解码,草稿模型单独量化。
- 端到端压测,比较质量、TTFT、TPOT、吞吐和成本。
每一步都会改变分布,不能假设“单独评测没问题,组合起来也没问题”。
面试高频问题¶
1. 对称量化和非对称量化有什么区别?分别适合什么?¶
参考回答要点:
- 对称量化令零点为 0,只存 scale,整数范围关于 0 对称;非对称量化额外存 zero point,能利用完整整数范围。
- 权重通常零中心,适合对称量化;激活可能有偏置或全正,非对称更合适。
- 对称量化的 kernel 更简单、反量化更快,非对称多一个零点开销。
- 非对称量化在极低比特下更能保住动态范围,但零点估计误差也会引入偏差。
- 选择要看硬件支持、比特数和数据分布,不能只看理论误差。
2. per-tensor、per-channel、per-group 如何取舍?¶
参考回答要点:
- per-tensor 一个 scale,开销最小,但离群值会拉低整体分辨率。
- per-channel 按输出通道独立缩放,适合权重,能显著降低通道间动态范围差异。
- per-group 每 64 或 128 个权重一个 scale,精度最高,但需要存元数据,有效比特数上升。
- 分组越小精度越好,但访存和反量化开销越大,W4 常用 g=128。
- 激活常用 per-token 或 per-channel,要结合 kernel 支持选择。
3. GPTQ 的误差补偿是怎么做的?¶
参考回答要点:
- 把逐层量化建模为最小化 \(\|XW-X\hat{W}\|^2\),用 \(H=2X^TX\) 近似 Hessian。
- 逐列量化,当前列的误差按 \(H^{-1}\) 的比例分摊到尚未量化的列。
- 更新量为 \(\delta=-(w_j-\hat{w}_j)/[H^{-1}]_{jj}\cdot[H^{-1}]_{:,j}\)。
- 配合分块、act-order、Cholesky 和阻尼提升稳定性。
- 3 到 4 bit 精度好,2 bit 明显退化,校准数据分布很关键。
4. AWQ 和 SmoothQuant 的出发点有什么不同?¶
参考回答要点:
- AWQ 关注权重通道的重要性,用激活幅值识别显著通道,通过逐通道缩放保护它们。
- SmoothQuant 关注激活离群值,利用线性层等价变换把量化难度从激活迁移到权重。
- AWQ 主要是 W4A16 weight-only,SmoothQuant 面向 W8A8。
- 两者都不改变数学结果,只改变量化误差的分布。
- 选择取决于瓶颈是显存/带宽还是算力,以及硬件是否支持 INT8 张量核心。
5. FP8 的 E4M3 和 E5M2 有什么区别?为什么前向常用 E4M3?¶
参考回答要点:
- E4M3 有 4 位指数、3 位尾数,最大 448,精度较高但范围窄。
- E5M2 有 5 位指数、2 位尾数,最大 57344,范围大但精度低。
- 前向的权重和激活通常落在有限范围,缩放后 E4M3 的精度更有利。
- 反向梯度动态范围大,E5M2 更不容易溢出。
- 都需要缩放策略,Hopper 及更新硬件才原生支持 FP8。
6. 为什么量化对小模型更敏感?¶
参考回答要点:
- 小模型参数少、冗余少,量化噪声更容易破坏关键表示。
- 小模型的激活分布可能更尖锐,离群通道占比更高,per-tensor 量化更吃亏。
- 大模型有更多层和通道可以补偿误差。
- 经验上 1B 级模型 4 bit 更容易在数学、代码、长上下文上退化。
- 小模型应优先考虑 W8A8、FP8 或更细粒度分组。
7. W4A16 和 W4A8 怎么选?¶
参考回答要点:
- W4A16 只压权重,decode 受带宽限制时收益最大,单流延迟好。
- W4A8 同时压激活,能用 INT8/FP8 张量核心,prefill 和高并发吞吐更好。
- W4A8 多一层激活量化误差,kernel 支持和调优不如 W4A16 成熟。
- 若瓶颈是显存和单用户速度,选 W4A16;若瓶颈是算力和批量吞吐,评估 W4A8。
- 最终要看端到端 tokens/s、P99 延迟和质量,而不是比特数。
8. 蒸馏温度 \(T\) 和权重 \(\alpha\) 如何影响训练?¶
参考回答要点:
- \(T\) 越大,教师分布越软,尾部类别信息越明显,但过大接近均匀。
- \(T\) 越小,越接近硬标签,蒸馏退化为普通交叉熵。
- KL 项乘 \(T^2\) 是为了补偿 softmax 梯度随温度缩放的 \(1/T\) 量级。
- \(\alpha\) 控制硬标签与教师分布的平衡,常用 0.5 到 0.9。
- 要固定其他变量做消融,并监控学生是否只学到格式而没学到推理。
9. 非结构化剪枝、2:4 稀疏和结构化剪枝有什么区别?¶
参考回答要点:
- 非结构化剪枝按单个权重置零,稀疏率高但稠密硬件不一定加速。
- 2:4 稀疏每 4 个权重保留 2 个,能被稀疏张量核心加速,理论吞吐约 2 倍。
- 结构化剪枝删除头、层、通道或 FFN 维度,能真实降低计算和显存,但精度损失更大。
- Wanda 用 \(|W_{ij}|\cdot\|X_j\|\) 评分,SparseGPT 用 Hessian 做逐层重建。
- 剪枝后通常需要 1% 到 5% 原预训练 token 的恢复训练或蒸馏。
本文档为面试复习资料,公式与数字建议结合原始论文复核。