量化是把大模型”压缩”的关键技术。4bit 量化可以让 70B 模型在 48GB 显存里跑起来。
为什么需要量化?
大模型的”重量”问题:
| 模型 | 参数量 | FP16 显存 | INT8 显存 | INT4 显存 |
|---|---|---|---|---|
| LLaMA 3 8B | 8B | ~16GB | ~8GB | ~4GB |
| LLaMA 3 70B | 70B | ~140GB | ~70GB | ~35GB |
| Qwen 72B | 72B | ~144GB | ~72GB | ~36GB |
| Mistral 7B | 7B | ~14GB | ~7GB | ~3.5GB |
一张消费级显卡(RTX 4090 = 24GB)跑不了 FP16 的 70B 模型,但 INT4 量化后可以。
量化的核心思想:用更少的位数表示权重,从 32位浮点(FP32) 或 16位浮点(FP16/BF16) 降到 INT8、INT4、甚至 INT2。
量化基础概念
数值格式
FP32 (32位浮点): 1位符号 + 8位指数 + 23位尾数
[S][EEEEEEEE][MMMMMMMMMMMMMMMMMMMMMMM]
精度高,范围大
FP16 (16位浮点): 1位符号 + 5位指数 + 10位尾数
[S][EEEEE][MMMMMMMMM]
范围和精度都降低
BF16 (16位浮点): 1位符号 + 8位指数 + 7位尾数
[S][EEEEEEEE][MMM]
范围同 FP32,精度降低
INT8 (8位整数): 256 个离散值: -128 ~ 127
体积是 FP16 的 1/2
INT4 (4位整数): 16 个离散值: -8 ~ 7
体积是 FP16 的 1/4
量化误差
原始值: 0.123456789
FP16: 0.12346 (损失小)
INT8: 0.12 (误差约 3%)
INT4: 0.125 (误差约 1.5%)
INT4 看起来误差更小?别忘了那是”重新映射”后的误差。
量化方法分类
1. 训练后量化(PTQ)
在模型训练/微调完成后,直接量化。不需要重新训练,速度快。
动态量化(Dynamic Quantization)
- 权重提前量化,激活值推理时动态量化
- 最简单,效果一般
- 适用于推理场景
import torch
# 动态量化(权重 INT8,激活保持 FP16)
model_dynamic = torch.quantization.quantize_dynamic(
model, {torch.nn.Linear}, dtype=torch.qint8
)
静态量化(Static Quantization)
- 需要校准数据集,计算激活分布
- 权重和激活都量化
- 效果更好,需要额外步骤
# 静态量化流程
model.eval()
# Fuse layers (Linear + ReLU -> Linear)
torch.quantization.fuse_modules(model, [['fc1', 'relu']])
# Prepare (插入观测节点)
model.qconfig = torch.quantization.get_default_qconfig('fbgemm')
torch.quantization.prepare(model, inplace=True)
# Calibrate (用校准数据)
with torch.no_grad():
for batch in calibration_data:
model(batch)
# Convert (真正量化)
torch.quantization.convert(model, inplace=True)
2. 量化感知训练(QAT)
在训练过程中模拟量化,让模型”适应”量化带来的误差。
# QAT 流程
# 1. 在模型中插入 FakeQuant 节点
model.qconfig = torch.quantization.get_default_qat_qconfig('fbgemm')
torch.quantization.prepare_qat(model, inplace=True)
# 2. Fine-tune on training data
train(model)
# 3. 转换
torch.quantization.convert(model.eval(), inplace=True)
QAT vs PTQ 对比:
| 方法 | 精度 | 成本 | 适用场景 |
|---|---|---|---|
| PTQ 动态 | ⭐⭐ | 免费 | 快速部署 |
| PTQ 静态 | ⭐⭐⭐ | 低 | 生产环境 |
| QAT | ⭐⭐⭐⭐ | 高 | 极致精度 |
高级量化技术
1. GPTQ:单卡量化 70B 模型
GPTQ(Generative Pre-trained Transformer Quantization)可以在单张 GPU 上用几小时量化 70B 模型。
from auto_gptq import AutoGPTQForCausalLM
from transformers import AutoTokenizer
model = AutoGPTQForCausalLM.from_pretrained(
"meta-llama/Llama-3-70B",
quantization_config={"bits": 4, "desc_act": True}
)
# bits: 4 或 8
# desc_act: 激活顺序重排,减少精度损失
GPTQ 核心原理:
- 分块量化(Chunk-based)
- 递归最小化量化误差
- 使用 Hickup 优化补偿
2. AWQ:Activation-Aware Weight Quantization
AWQ 观察到:不是所有权重都一样重要,激活值大的权重更重要。
from awq import AutoAWQForCGMModel
from transformers import AutoTokenizer
model = AutoAWQForCGMModel.from_pretrained("meta-llama/Llama-3-70B")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3-70B")
quant_config = {
"zero_point": True,
"q_group_size": 128, # 分组大小
"w_bit": 4,
"version": "GEMM" # GEMM 或 GEMV
}
model.quantize(tokenizer, quant_config=quant_config)
3. GGUF:本地部署的量化格式
GGUF(GPT-Generated Unified Format)是 llama.cpp 推出的量化格式,适合 CPU 推理。
| 格式 | 量子化位数 | 70B 大小 | 适用场景 |
|---|---|---|---|
| Q8_0 | 8bit | ~70GB | 接近无损 |
| Q6_K | 6bit | ~55GB | 高质量 |
| Q5_K_M | 5bit | ~48GB | 均衡 |
| Q4_K_M | 4bit | ~40GB | 主流选择 |
| Q3_K_M | 3bit | ~35GB | 低显存 |
| Q2_K | 2bit | ~30GB | 极致压缩 |
# 使用 llama.cpp 量化
./quantize ./models/llama-70b-f16.gguf ./models/llama-70b-q4_k_m.gguf q4_k_m
4. FP8:新一代量化格式
NVIDIA H100 支持 FP8(8位浮点),兼顾范围和精度。
# PyTorch FP8 支持 (需要 H100)
from torch.cuda.amp import custom_fwd, custom_bwd
@custom_fwd(device="cuda")
def forward_fp8(x):
return x.float8_e4m3fn(x)
量化实战:用 llama.cpp 本地跑大模型
# 1. 安装 llama.cpp
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp && mkdir build && cd build && cmake .. && make
# 2. 下载模型 (Qwen 2.5 7B)
# 3. 量化
./quantize ./models/qwen-7b-f16.gguf ./models/qwen-7b-q4_k_m.gguf q4_k_m
# 4. 推理
./main -m ./models/qwen-7b-q4_k_m.gguf -n 512 -p "你好,介绍一下自己"
内存占用对比(Qwen 2.5 7B):
| 格式 | 内存占用 | 生成速度 |
|---|---|---|
| FP16 | ~14GB | 30 tok/s |
| Q8_0 | ~8GB | 25 tok/s |
| Q4_K_M | ~4.5GB | 20 tok/s |
量化方案的选用指南
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 生产部署 | INT8 + AWQ | 精度损失 < 1% |
| 个人推理 | Q4_K_M (GGUF) | RTX 3090/4090 可跑 70B |
| 极致压缩 | INT2/INT3 | 精度损失较大,仅实验 |
| 最新模型 | GPTQ / AWQ | 支持大多数开源模型 |
| CPU 部署 | GGUF Q4 | llama.cpp 生态成熟 |
💡 小结
量化是让大模型”平民化”的关键技术:
| 量化方法 | 精度损失 | 难度 | 适用 |
|---|---|---|---|
| 动态量化 | 中等 | 低 | 快速部署 |
| GPTQ | 较小 | 中 | 70B+ 模型 |
| AWQ | 较小 | 中 | 最佳性价比 |
| QAT | 最小 | 高 | 极致精度 |
实践建议:
- 优先尝试 AWQ 或 GPTQ(4bit)
- 生产环境用 INT8 或 Q5_K_M
- CPU 推理用 GGUF Q4_K_M
- 评估时用 困惑度(Perplexity) 和 下游任务准确率
相关阅读:AI Agent 记忆机制:让AI更懂你