INT4/INT8 模型量化实战
模型量化是降低模型显存占用和加速推理的最有效手段之一。本文介绍 INT4 和 INT8 量化的原理、方法和工程实践。
量化原理
量化的核心是将浮点权重映射到低精度整数:
量化: Q = round(W / S) + Z
反量化: W' = (Q - Z) × S
其中 S 为缩放因子,Z 为零点对称量化 vs 非对称量化
| 类型 | 公式 | 范围 | 适用 |
|---|---|---|---|
| 对称量化 | Q = round(W/S) | [-127, 127] | 权重(近似对称分布) |
| 非对称量化 | Q = round(W/S) + Z | [0, 255] | 激活值(非负分布) |
量化方法分类
训练后量化(PTQ)
无需重新训练,直接量化预训练模型:
python
# 使用 AutoGPTQ 进行 INT4 量化
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
from transformers import AutoTokenizer
model_id = "meta-llama/Llama-2-7b-hf"
tokenizer = AutoTokenizer.from_pretrained(model_id)
# 准备校准数据
calibration_data = []
for i in range(128):
text = f"校准样本 {i},用于量化校准"
inputs = tokenizer(text, return_tensors="pt")
calibration_data.append(inputs.input_ids)
# 量化配置
quantize_config = BaseQuantizeConfig(
bits=4,
group_size=128,
desc_act=True, # 激活值排序量化
damp_percent=0.01,
)
# 执行量化
model = AutoGPTQForCausalLM.from_pretrained(model_id, quantize_config)
model.quantize(calibration_data)
model.save_quantized("llama-2-7b-gptq-int4")量化感知训练(QAT)
在训练过程中模拟量化误差:
python
# PyTorch 量化感知训练
import torch.quantization as quant
model = torch.load("model.pt")
model.qconfig = quant.get_default_qat_qconfig('fbgemm')
model_prepared = quant.prepare_qat(model)
# 训练若干 epoch
for epoch in range(5):
train_one_epoch(model_prepared, train_loader)
# 转换为量化模型
model_quantized = quant.convert(model_prepared)量化精度对比
| 量化方法 | 位宽 | 7B 模型大小 | MMLU 分数变化 | 推理加速 |
|---|---|---|---|---|
| FP16 | 16 | 13.5GB | 基准 | 1x |
| INT8 | 8 | 7GB | -0.5% | 1.5-2x |
| INT4 (GPTQ) | 4 | 3.9GB | -1.5% | 2-3x |
| INT4 (AWQ) | 4 | 3.9GB | -1.0% | 2-3x |
group_size 选择
group_size=128 是最常用的配置,在精度和效率间取得良好平衡。group_size=32 精度更高但计算开销更大;group_size=-1(per-channel)精度最低但速度最快。
量化校准
量化质量高度依赖校准数据。校准数据应与实际推理数据分布一致,通常需要 128-512 条样本。数据分布不匹配会导致显著的精度下降。