模型量化与压缩
问题
什么是模型量化?GPTQ、AWQ、GGUF 有什么区别?如何选择量化方案?
答案
一、量化概念
量化是将模型参数从高精度(FP32/FP16)转换为低精度(INT8/INT4),以减少显存占用和加速推理:
| 精度 | 每参数字节 | 7B 模型大小 | 质量损失 |
|---|---|---|---|
| FP32 | 4 B | 28 GB | 基准 |
| FP16 | 2 B | 14 GB | 几乎无 |
| INT8 | 1 B | 7 GB | 极小 |
| INT4 | 0.5 B | 3.5 GB | 小 |
二、主流量化方法
| 方法 | 类型 | 精度 | 速度 | 特点 |
|---|---|---|---|---|
| GPTQ | 训练后量化 | INT4/INT3 | 快(GPU) | 逐层校准,质量好 |
| AWQ | 训练后量化 | INT4 | 快(GPU) | 保护重要权重,质量最好 |
| GGUF | 训练后量化 | INT2-INT8 | 中(CPU/GPU) | llama.cpp 格式,CPU 友好 |
| bitsandbytes | 动态量化 | INT8/NF4 | 中 | QLoRA 用,加载时量化 |
| SmoothQuant | 训练后量化 | INT8 | 很快 | 均衡 activation 和 weight |
三、GPTQ vs AWQ vs GGUF
四、使用示例
GPTQ(GPU 推理)
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"TheBloke/Llama-2-7B-GPTQ",
device_map="auto",
)
GGUF(CPU/Ollama)
# Ollama 直接使用 GGUF 格式
ollama run llama3.1:8b-instruct-q4_K_M
bitsandbytes(QLoRA 微调)
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B",
quantization_config=bnb_config,
)
五、量化质量对比
以 Llama 2 7B 在常见 benchmark 上的表现为例:
| 量化 | MMLU | HellaSwag | 显存占用 |
|---|---|---|---|
| FP16(基准) | 45.3 | 76.0 | 14 GB |
| GPTQ INT4 | 44.8 | 75.2 | 4 GB |
| AWQ INT4 | 45.0 | 75.6 | 4 GB |
| GGUF Q4_K_M | 44.5 | 75.0 | 4 GB |
关键结论
INT4 量化在大多数任务上质量损失 < 2%,但显存减少 70%。对于生产部署是非常好的选择。
常见面试问题
Q1: 量化会损失多少精度?
答案:
- INT8:几乎无损(< 0.5% 质量下降)
- INT4:轻微损失(1-3%),大多数应用可接受
- INT3/INT2:明显损失(5-10%),不推荐
- 模型越大,量化损失越小(70B 模型量化后比 7B 模型损失小)
Q2: 为什么 AWQ 质量比 GPTQ 好?
答案:
- GPTQ 对所有权重平等对待
- AWQ(Activation-aware Weight Quantization)发现 1% 的关键权重对质量影响巨大
- AWQ 保护这些关键权重(基于 activation 的重要性分析),其余权重正常量化
- 结果:相同量化位数下 AWQ 的质量更接近原始模型