GPTQ 论文
Post-Training Quantization for GPT
观察不同量化精度如何影响权重分布和误差。
| idx | FP32 | INT8 | 误差 |
|---|---|---|---|
| 0 | 0.101469 | 0.101469 | ~0 |
| 1 | 0.017998 | 0.015663 | 0.002335 |
| 2 | -0.097147 | -0.102320 | 0.005172 |
| 3 | 0.479816 | 0.476868 | 0.002948 |
| 4 | 0.080805 | 0.080017 | 0.000788 |
| 5 | -0.179686 | -0.177399 | 0.002286 |
| 6 | 0.366209 | 0.369611 | 0.003402 |
| 7 | 0.045511 | 0.047840 | 0.002329 |
| 8 | 0.609812 | 0.605576 | 0.004235 |
| 9 | 0.226797 | 0.230177 | 0.003380 |
💡 7B 模型: FP32=28GB, FP16=14GB, INT8=7GB, INT4=3.5GB
一句话定义:量化是将模型权重从高精度(如 FP32/FP16)转换为低精度(如 INT8/INT4)的技术,可以减少内存占用并加速推理,同时尽量保持模型性能。
| 原图 (FP32) | 压缩后 (INT8) | 极限压缩 (INT4) |
|---|---|---|
| 10MB PNG | 2MB JPEG | 500KB 缩略图 |
| 细节完美 | 肉眼几乎无差 | 有点模糊但能用 |
| 加载慢 | 快 4x | 快 8x |
量化就像图片压缩:牺牲一点精度,换取更小体积和更快速度。
| 模型 | FP32 | FP16 | INT8 | INT4 |
|---|---|---|---|---|
| 7B | 28 GB | 14 GB | 7 GB | 3.5 GB |
| 13B | 52 GB | 26 GB | 13 GB | 6.5 GB |
| 70B | 280 GB | 140 GB | 70 GB | 35 GB |
INT4 量化让 7B 模型可以在消费级 GPU (4GB) 上运行!
| 指标 | 提升 |
|---|---|
| 内存 | 减少 4-8x |
| 推理速度 | 加速 2-4x |
| 能耗 | 降低 50-75% |
| 精度损失 | 通常 < 1% |
将浮点数映射到整数范围:
缩放因子计算:
例如 INT8:
| 粒度 | 说明 | 精度 | 开销 |
|---|---|---|---|
| Per-tensor | 整个张量一个 scale | 低 | 低 |
| Per-channel | 每个通道一个 scale | 中 | 中 |
| Per-group | 每 128 个元素一个 scale | 高 | 高 |
Per-group 是 LLM 量化的主流选择(如 GPTQ、AWQ)。
┌─────────────────────────────────────────────────────┐│ 量化方法分类 │├─────────────────┬───────────────────────────────────┤│ 训练后量化 │ 训练感知量化 ││ (PTQ) │ (QAT) │├─────────────────┼───────────────────────────────────┤│ • GPTQ │ • QLoRA ││ • AWQ │ • LLM-QAT ││ • SmoothQuant │ ││ • GGUF/GGML │ │└─────────────────┴───────────────────────────────────┘from transformers import AutoModelForCausalLM, AutoTokenizerfrom auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
# 1. 配置量化参数quantize_config = BaseQuantizeConfig( bits=4, # INT4 量化 group_size=128, # Per-group 粒度 desc_act=False, # 是否降序激活 sym=True, # 对称量化)
# 2. 加载原始模型model = AutoModelForCausalLM.from_pretrained( "meta-llama/Llama-2-7b-hf", torch_dtype=torch.float16, device_map="auto")tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
# 3. 准备校准数据calibration_data = [ tokenizer(text, return_tensors="pt") for text in calibration_texts[:128]]
# 4. 量化model = AutoGPTQForCausalLM.from_pretrained(model, quantize_config)model.quantize(calibration_data)
# 5. 保存model.save_quantized("llama2-7b-gptq-4bit")
# 6. 加载使用model = AutoGPTQForCausalLM.from_quantized( "llama2-7b-gptq-4bit", device_map="auto")from transformers import AutoModelForCausalLM, BitsAndBytesConfig
# INT8 量化配置bnb_config_8bit = BitsAndBytesConfig( load_in_8bit=True,)
# INT4 量化配置 (推荐)bnb_config_4bit = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", # NormalFloat4,比 INT4 更好 bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_use_double_quant=True, # 双重量化,进一步压缩)
# 加载量化模型model = AutoModelForCausalLM.from_pretrained( "meta-llama/Llama-2-7b-hf", quantization_config=bnb_config_4bit, device_map="auto",)
# 直接使用,内存仅需 ~4GBoutput = model.generate(input_ids, max_new_tokens=100)# 1. 转换模型为 GGUF 格式python convert.py ./llama-2-7b --outtype f16 --outfile llama2-7b.gguf
# 2. 量化./quantize llama2-7b.gguf llama2-7b-q4_k_m.gguf q4_k_m
# 3. 运行推理 (纯 CPU)./main -m llama2-7b-q4_k_m.gguf \ -p "Hello, how are you?" \ -n 100
# 量化级别说明# Q4_0: 最基础 4bit,最快但质量最低# Q4_K_M: 4bit,中等质量 (推荐)# Q5_K_M: 5bit,高质量# Q8_0: 8bit,接近原始精度| 方法 | 精度损失 | 速度 | 易用性 | 适用场景 |
|---|---|---|---|---|
| BitsAndBytes | 中 | 快 | ⭐⭐⭐⭐⭐ | 快速实验 |
| GPTQ | 低 | 很快 | ⭐⭐⭐⭐ | 生产部署 |
| AWQ | 最低 | 最快 | ⭐⭐⭐ | 高性能部署 |
| GGUF | 中 | 中 | ⭐⭐⭐⭐⭐ | CPU/边缘设备 |