外观
量化(quantization)
一句话定义:量化是把模型中的高精度数值(FP32/FP16)替换成更低位的整数(INT8/INT4)表示的压缩与加速技术——用可控的精度损失,换取体积、显存、带宽与算力上的成倍收益。
行业洞察:量化是当下部署优化里性价比最高的一张牌。FP32→INT8 权重体积直接减 75%,推理提速 2~4 倍,而多数任务精度损失 <1%;INT4 再减一半体积,让 7B 模型跑进 4GB 显存。Meta、NVIDIA、微软都在自己的生产系统里大规模用 INT8/INT4 推理(LLM.int8 论文报告 BLOOM-176B 用 INT8 无精度损失)。难点不在"量化本身",而在量化的工程纪律:谁的能量化校准、谁的误差控制差、谁不跑同分布数据做验收——差距全在后半程。
一、量化是什么,为什么值得做
1. 从 FP32 到 INT8,物理上省了什么
| 收益维度 | 量化 FP32→INT8 | 原因 |
|---|---|---|
| 权重体积 | 减 75% | 4 字节 → 1 字节 |
| 显存占用 | 减 75% | 同上,可装 4 倍大模型 |
| 推理速度(带宽受限时) | 提升 ~2 倍 | 读权重时间近半 |
| 算力(INT8 tensor core) | 提升 2~4 倍 | 每周期算更多整数乘加 |
| 能耗 | 下降 | 整数运算更省电 |
为什么量化对推理比对训练有用:推理是带宽密集型(每读一字节权重只做几次运算),权重字节数减半,等待搬运的时间就减半;而训练要保梯度精度,量化会破坏反向传播,收益远小于风险(详见 推理:从前向传播到推理引擎)。
2. 量化的数学本质
把浮点范围映射到整数范围:
text
float_value ≈ scale × (int_value - zero_point)
对称量化(常用):
scale = max(|float_min|, |float_max|) / 127 # INT8
int_value = round(float_value / scale)误差来源一目了然:量化是把一个连续区间压进 256 个格子(INT8),离群值(outlier)会把格子撑大、让普通值都挤在少数几格里,精度骤降。这是后面所有高级方法的出发点。
二、精度格式全景
| 格式 | 位宽 | 动态范围 | 精度 | 典型用途 |
|---|---|---|---|---|
| FP32 | 32 | ~1e-38~3e38 | 高 | 训练、精度基准 |
| FP16 | 16 | 有限(±65504) | 中 | 通用推理默认档 |
| BF16 | 16 | 同 FP32 | 低(尾数少) | 训练/推理,不怕溢出 |
| INT8 | 8 | -128~127(整数) | 中低 | 推理主力,体积减 75% |
| INT4 | 4 | -8~7 | 低 | LLM 大模型瘦身,需分组校准 |
| FP8(E4M3/E5M2) | 8 | 有限 | 中 | 新一代训练/推理 |
为什么训练用 BF16 而非 FP16
FP16 的动态范围太窄,训练时梯度容易上溢/下溢;BF16 动态范围与 FP32 相同,只损失精度,训练稳定。推理则相反:权重值域已知,FP16 精度更佳,是推理默认档。别搞反了。
三、两条路线:PTQ 与 QAT
1. 后训练量化(PTQ,Post-Training Quantization)
模型训练完后,用一小批校准数据(calibration set)统计权重/激活的数值范围,直接转 INT8。成本低(几十分钟)、无需重训,是首选路线。
text
训练好的模型
│ 收集校准数据(几百~几千条,必须与线上同分布)
│ 统计每层/每通道的 min/max(或百分位)
│ 计算 scale / zero_point
▼
INT8 模型 → 跑验证集对比指标 → 掉点可接受则上线2. 量化感知训练(QAT,Quantization-Aware Training)
在训练中插入"伪量化"(fake quantization)算子,让模型学习对量化误差鲁棒。效果最好(通常掉点 <0.5%),但要重训/微调,成本高。
text
带伪量化算子的训练图:forward 时模拟 INT8 舍入,backward 时按直通估计器(STE)更新权重
微调完成后 → 移除伪量化 → 导出 INT8 模型| 维度 | PTQ | QAT |
|---|---|---|
| 成本 | 小时级 | 天级(需 GPU 训练资源) |
| 精度 | 大模型掉点可控;小模型/激活敏感模型易掉 | 通常最好 |
| 数据要求 | 需校准数据 | 需训练数据 + 训练流程 |
| 适用 | 默认路线 | PTQ 掉点不可接受时 |
经验法则:先 PTQ,掉点超过 1%(或业务不可接受)再 QAT 或蒸馏(见 蒸馏、剪枝与低秩分解)。LLM 参数量大、冗余高,PTQ 效果通常很好。
四、量化什么:权重、激活、KV Cache
1. 权重量化 vs 激活量化
| 对象 | 难度 | 原因 | 收益 |
|---|---|---|---|
| 权重 | 简单 | 值域静态、可离线统计 | 体积减 75%、带宽减半 |
| 激活 | 难 | 值域随输入变化、有离群值 | 顺带压缩激活,内存/带宽进一步降 |
| KV Cache | 中 | 中间产物、随 token 增长 | LLM 长上下文/高并发关键(见 大模型推理优化) |
激活难量化的根源是离群值:同一层内,个别通道的值比其他通道大 100 倍。若按全局 max 定 scale,其余通道几乎全被压成一个值。这就是激活量化在 LLM 上最容易掉点的原因。
2. 量化粒度:per-tensor / per-channel / per-group
| 粒度 | 共享 scale 的张量范围 | 精度 | 存储开销 |
|---|---|---|---|
| per-tensor | 整层一个 scale | 低 | 几乎为 0 |
| per-channel | 每输出通道一个 scale | 中 | 少量 |
| per-group(如 128 权重一组) | 组内一个 scale | 高 | 每 128 权重 2~4 字节 |
精度与开销的平衡点一般是:权重用 per-channel 或 per-group,激活用 per-tensor(激活的 per-channel 难以在推理时高效实现)。
3. 缓解激活离群:SmoothQuant 的思路
SmoothQuant(ICML 2023)的思路很优雅:不动难量化的激活,而是把激活的离群程度"迁移"到容易量化的权重上——给权重除以一个逐通道的平滑因子、给激活乘以它。这让激活变得好量化,从而能用 per-tensor INT8 同时量化权重和激活,且不掉点。它是当前 W8A8(权重激活都 8bit)方案的重要基石。
五、LLM 时代的量化方法
1. GPTQ:贪心 + Hessian 近似
GPTQ(2022)基于"最优脑损伤"(OBC)思想:逐列量化权重,同时用Hessian 近似调整剩余权重,弥补已量化列造成的输出误差。效果好且校准速度快,是 4-bit 量化的经典方案,被 vLLM、TGI 等框架支持。
2. AWQ:按激活幅度保护重要权重
AWQ(2023)观察到:权重的重要性由对应激活的幅度决定。它统计激活的幅度分布,对"重要"权重通道做缩放保护,无需反向传播与重训练,就能在 INT4 下保住精度,常与 TensorRT-LLM、vLLM 配合用于生产。
3. GGUF 的 q4_K_M 等方案
GGUF 里的 q4_K_M 是 llama.cpp 生态的块级量化:每 256 个权重为一组(block),内含量化类型与 scale,_M 表示混合精度(重要部分用更高精度)。特点:开箱即用、以 CPU/本地部署为第一公民(详见 模型格式与转换)。它的局限是与 llama.cpp 运行时绑定较紧。
| 方法 | 位宽 | 校准需求 | 掉点(经验值) | 生产生态 |
|---|---|---|---|---|
| LLM.int8 | INT8 | 小 | ~0 | Hugging Face 内置 |
| GPTQ | INT4/INT8 | 小 | 可控,1~3% | vLLM/TGI/AutoGPTQ |
| AWQ | INT4 | 小 | 优于 GPTQ | vLLM/TensorRT-LLM |
| GGUF q4_K_M | ~4.5bit | 无(内置) | 2~5%(本地可接受) | llama.cpp/Ollama |
| SmoothQuant | INT8 W8A8 | 小 | 最低 | 部分框架内置 |
六、量化误差的来源与缓解
| 误差来源 | 机理 | 缓解手段 |
|---|---|---|
| 离群值 | 个别极大值撑大 scale,挤压普通值精度 | per-channel/per-group、SmoothQuant、AWQ 的保护 |
| 动态范围不匹配 | 校准集与线上分布不一致 | 校准数据必须同分布(这点最容易翻车) |
| 累积误差 | 误差沿层叠加 | 用更细粒度、混合精度(部分层不量化) |
| 激活量化 | 激活值域动态变化 | 用校准集统计激活范围、加 SmoothQuant |
校准数据是量化的命门
用训练集随机抽 1000 条做校准、上线后输入分布是另一种形态,量化误差会显著放大。校准数据必须从线上同分布样本中抽样,且在量化后用同分布测试集验收。
七、量化后的验收纪律
- 跑同分布数据:量化前后的对比要在同一份线上分布数据上做,逐层对比输出分布或直接比任务指标。
- 对比业务指标而非逐位一致:AUC/准确率/Rouge 掉点 <1% 通常可接受;
fp16 vs int8的逐位差异必然存在,别追求。 - 覆盖长尾输入:异常输入、极端文本要单独验证——量化模型对离群输入更敏感。
- 上线后持续监控:量化模型的在线指标基线可能与 FP16 不同,监控体系要单独设基线(见 监控与可观测性)。
权衡与取舍
| 决策点 | 选项 | 怎么选 |
|---|---|---|
| PTQ vs QAT | 省事 vs 更准 | 默认 PTQ;掉点不可接受再 QAT/蒸馏 |
| INT8 vs INT4 | 稳 vs 更省 | 服务端 INT8 起步;LLM/端侧可 INT4 |
| 权重 vs 权重+激活 | 简单 vs 更强 | 先权重;带宽仍是瓶颈再加激活量化 |
| per-tensor vs per-channel | 简单 vs 更准 | 权重 per-channel,激活 per-tensor |
| GPTQ vs AWQ vs GGUF | 生态差异 | 生产服务用 AWQ/GPTQ;本地工具用 GGUF |
一句话总结:量化是"精度换资源"的工程学——选对路线(先 PTQ)、管好误差(校准数据同分布)、守住验收(业务指标不掉点),就能把模型的体积和速度同时提升一个量级。
延伸阅读
- 蒸馏、剪枝与低秩分解 —— 量化之外的另三条瘦身路线与组合策略
- GPU 与硬件选型 —— INT8 的算力/带宽收益如何落到具体硬件
- 大模型推理优化 —— KV Cache 量化与 LLM 部署中的量化实践
- 论文精读:量化经典 —— LLM.int8 / GPTQ / AWQ 论文逐篇拆解
- 模型优化实战 —— 量化从实验到上线的完整流程
参考资料
- LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale(Dettmers et al.)
- GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers(Frantar et al.)
- AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration(Lin et al.)
- SmoothQuant: Accurate and Efficient Post-Training Quantization for LLMs(Xiao et al.)
- NVIDIA INT8 推理与校准白皮书