推理量化
量化(Quantization)是将模型权重和/或激活值从高精度(FP32/FP16)转换为低精度(INT8/INT4)表示的技术。在推理场景下,量化的核心目标是减少显存占用和加速推理,使大模型能在有限硬件上运行。
关于训练阶段的量化(PTQ、QAT),参见 模型压缩。本文聚焦于 LLM 推理部署中常用的量化方法与格式。
基本概念
量化映射
量化的本质是将连续的浮点数映射到离散的整数值:
其中 \(\Delta\) 为缩放因子(scale),\(z\) 为零点(zero-point),\(b\) 为量化位宽。
对称量化 vs 非对称量化
- 对称量化:\(z = 0\),将浮点范围对称映射到 \([-2^{b-1}, 2^{b-1}-1]\),实现简单、计算高效
- 非对称量化:\(z \neq 0\),能更好地利用量化范围,适合分布不对称的激活值
量化粒度
- Per-tensor:整个张量共用一组 \(\Delta, z\),最简单但精度最差
- Per-channel:每个输出通道独立量化,权重量化的标准做法
- Per-group:每 \(g\) 个元素一组(如每 128 个),在精度和开销间取平衡,GPTQ/AWQ 常用 \(g=128\)
主流 LLM 量化方法
GPTQ (GPT Quantization)
GPTQ 基于 Optimal Brain Quantization 框架,通过逐层量化并补偿量化误差来保持精度:
核心思想: 量化某个权重时,将其引入的误差分摊到同一行中尚未量化的其他权重上,使得整层的输出误差最小化。
流程:
- 收集少量校准数据(通常 128 条),计算每层的 Hessian 矩阵 \(H = 2X^TX\)
- 按列顺序逐个量化权重
- 对每个被量化的权重,利用 Hessian 信息将误差最优地分配给未量化权重
- 使用 Cholesky 分解加速 Hessian 逆的计算
特点:
- 支持 4-bit / 3-bit / 2-bit 量化
- 仅需几分钟即可完成量化(在单张 GPU 上)
- 4-bit 量化下精度损失极小,接近 FP16 基线
- 生态支持好:AutoGPTQ、Transformers 原生支持
# 使用 AutoGPTQ 量化
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
quantize_config = BaseQuantizeConfig(
bits=4,
group_size=128,
damp_percent=0.01
)
model = AutoGPTQForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
quantize_config=quantize_config
)
model.quantize(calibration_dataset)
model.save_quantized("llama2-7b-gptq-4bit")
AWQ (Activation-aware Weight Quantization)
AWQ 的核心观察是:不是所有权重都同等重要,少量"显著权重"(salient weights)对模型输出有不成比例的影响。
核心思想: 通过分析激活值的分布找出显著权重通道,对这些通道进行缩放保护,使量化误差集中在不重要的权重上。
流程:
- 用校准数据统计每个权重通道对应的激活值大小
- 激活值大的通道对应"显著权重",为其乘以缩放因子 \(s > 1\)
- 相应地将激活值除以 \(s\),保持数学等价
- 缩放后的权重具有更大的数值范围,量化的相对误差更小
相对 GPTQ 的优势:
- 不需要逆 Hessian 计算,量化速度更快
- 量化后模型更鲁棒,跨任务泛化能力更好
- 在低比特(3-bit)下优势更明显
GGUF (GPT-Generated Unified Format)
GGUF 是 llama.cpp 生态使用的量化格式,专为 CPU 和边缘设备推理设计:
特点:
- 支持多种量化类型:Q2_K, Q3_K, Q4_K, Q5_K, Q6_K, Q8_0 等
- "K-Quant" 系列使用 per-block 量化与重要性加权,质量优于早期的 Q4_0/Q4_1
- 单文件格式,包含模型权重、分词器、元数据,便于分发
- 支持混合精度:不同层使用不同的量化位宽
常用量化级别:
| 格式 | 位宽 | 显存/内存 (7B) | 质量 |
|---|---|---|---|
| Q2_K | ~2.6 bit | ~3 GB | 可用但有明显损失 |
| Q4_K_M | ~4.8 bit | ~4.5 GB | 推荐:质量与大小平衡好 |
| Q5_K_M | ~5.5 bit | ~5.3 GB | 高质量,接近 FP16 |
| Q6_K | ~6.6 bit | ~5.9 GB | 接近无损 |
| Q8_0 | 8 bit | ~7.2 GB | 几乎无损 |
# 使用 llama.cpp 量化
./llama-quantize model-f16.gguf model-q4km.gguf Q4_K_M
FP8 量化
FP8(8-bit 浮点)是 NVIDIA Hopper 架构(H100)原生支持的数据类型,有两种格式:
- E4M3(4位指数,3位尾数):更大的数值范围,适合权重和激活值
- E5M2(5位指数,2位尾数):更大的动态范围,适合梯度
优势: 相比 INT8,FP8 不需要校准数据就能直接量化(无需 calibration),且 H100 的 FP8 Tensor Core 吞吐量是 FP16 的 2 倍。vLLM 和 TensorRT-LLM 均已支持 FP8 推理。
量化方法对比
| 方法 | 典型位宽 | 需要校准数据 | 量化速度 | 推理框架 | 适用场景 |
|---|---|---|---|---|---|
| GPTQ | 4/3/2 bit | 是(~128条) | 中等 | vLLM, TGI, Transformers | GPU 部署 |
| AWQ | 4 bit | 是(~128条) | 快 | vLLM, TGI, TensorRT-LLM | GPU 部署 |
| GGUF | 2-8 bit | 否 | 快 | llama.cpp, Ollama | CPU/边缘部署 |
| FP8 | 8 bit | 否 | 即时 | vLLM, TensorRT-LLM | H100 GPU |
| BitsAndBytes | 4/8 bit | 否 | 即时 | Transformers, TGI | 研究/原型 |
选型建议:
- GPU 高并发服务 → AWQ 或 GPTQ 4-bit(vLLM 部署)
- NVIDIA H100 → FP8(原生支持,无精度损失)
- 本地 CPU/Mac → GGUF Q4_K_M(Ollama / llama.cpp)
- 快速实验 → BitsAndBytes NF4(一行代码加载)
量化质量评估
评估量化模型时,通常关注以下指标:
- Perplexity (PPL):在 WikiText-2 等数据集上测量,PPL 越低越好
- 下游任务准确率:在 MMLU、HellaSwag 等 benchmark 上测量
- 推理速度:tokens/s 吞吐量
- 显存占用:峰值显存使用
经验规则:4-bit 量化的 PPL 增长通常在 0.1-0.5 以内(相对 FP16),对大多数应用场景无感知差异。
参考
- Frantar et al., "GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers", ICLR 2023
- Lin et al., "AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration", MLSys 2024
- Dettmers et al., "QLoRA: Efficient Finetuning of Quantized Language Models", NeurIPS 2023
- llama.cpp - GGUF 格式说明