name: gptq description: 后训练4位量化,用于大型语言模型,精度损失最小。用于在消费者GPU上部署大模型(70B,405B),当需要4倍内存减少和<2%困惑度退化时,或用于比FP16快3-4倍的推理加速。与Transformers和PEFT集成进行QLoRA微调。 version: 1.0.0 author: Orchestra Research license: MIT tags: [优化, GPTQ, 量化, 4位, 后训练, 内存优化, 消费者GPU, 快速推理, QLoRA, 分组量化] dependencies: [auto-gptq, transformers, optimum, peft]
GPTQ(生成预训练Transformer量化)
后训练量化方法,通过分组量化将大型语言模型压缩到4位,精度损失最小。
何时使用GPTQ
使用GPTQ时:
- 需要在有限GPU内存上部署大模型(70B+)
- 想要4倍内存减少和<2%精度损失
- 在消费者GPU上部署(RTX 4090,3090)
- 需要更快推理(比FP16快3-4倍)
使用AWQ代替时:
- 需要稍好精度(<1%损失)
- 拥有新GPU(Ampere,Ada)
- 想要Marlin内核支持(在某些GPU上快2倍)
使用bitsandbytes代替时:
- 需要简单集成到Transformers
- 想要8位量化(压缩较少,质量更好)
- 不需要预量化模型文件
快速开始
安装
# 安装AutoGPTQ
pip install auto-gptq
# 使用Triton(仅Linux,更快)
pip install auto-gptq[triton]
# 使用CUDA扩展(更快)
pip install auto-gptq --no-build-isolation
# 完整安装
pip install auto-gptq transformers accelerate
加载预量化模型
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM
# 从HuggingFace加载量化模型
model_name = "TheBloke/Llama-2-7B-Chat-GPTQ"
model = AutoGPTQForCausalLM.from_quantized(
model_name,
device="cuda:0",
use_triton=False # 在Linux上设置为True以加速
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 生成
prompt = "解释量子计算"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda:0")
outputs = model.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0]))
量化自己的模型
from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
from datasets import load_dataset
# 加载模型
model_name = "meta-llama/Llama-2-7b-chat-hf"
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 量化配置
quantize_config = BaseQuantizeConfig(
bits=4, # 4位量化
group_size=128, # 分组大小(推荐:128)
desc_act=False, # 激活顺序(False用于CUDA内核)
damp_percent=0.01 # 阻尼因子
)
# 加载模型进行量化
model = AutoGPTQForCausalLM.from_pretrained(
model_name,
quantize_config=quantize_config
)
# 准备校准数据
dataset = load_dataset("c4", split="train", streaming=True)
calibration_data = [
tokenizer(example["text"])["input_ids"][:512]
for example in dataset.take(128)
]
# 量化
model.quantize(calibration_data)
# 保存量化模型
model.save_quantized("llama-2-7b-gptq")
tokenizer.save_pretrained("llama-2-7b-gptq")
# 推送到HuggingFace
model.push_to_hub("username/llama-2-7b-gptq")
分组量化
GPTQ工作原理:
- 分组权重: 将每个权重矩阵分成组(通常128个元素)
- 每组量化: 每组有自己的尺度/零点
- 最小化误差: 使用Hessian信息最小化量化误差
- 结果: 4位权重,接近FP16精度
分组大小权衡:
| 分组大小 | 模型大小 | 精度 | 速度 | 推荐 |
|---|---|---|---|---|
| -1(每列) | 最小 | 最好 | 最慢 | 仅研究 |
| 32 | 较小 | 较好 | 较慢 | 需要高精度 |
| 128 | 中等 | 好 | 快 | 推荐默认 |
| 256 | 较大 | 较低 | 更快 | 速度关键 |
| 1024 | 最大 | 最低 | 最快 | 不推荐 |
示例:
权重矩阵: [1024, 4096] = 4.2M 元素
分组大小 = 128:
- 组数: 4.2M / 128 = 32,768 组
- 每组: 自己的4位尺度 + 零点
- 结果: 更好粒度 → 更好精度
量化配置
标准4位(推荐)
from auto_gptq import BaseQuantizeConfig
config = BaseQuantizeConfig(
bits=4, # 4位量化
group_size=128, # 标准分组大小
desc_act=False, # 更快CUDA内核
damp_percent=0.01 # 阻尼因子
)
性能:
- 内存:4倍减少(70B模型:140GB → 35GB)
- 精度:约1.5%困惑度增加
- 速度:比FP16快3-4倍
高精度(3位,大分组)
config = BaseQuantizeConfig(
bits=3, # 3位(更高压缩)
group_size=128, # 保持标准分组大小
desc_act=True, # 更好精度(较慢)
damp_percent=0.01
)
权衡:
- 内存:5倍减少
- 精度:约3%困惑度增加
- 速度:快5倍(但精度较低)
最大精度(4位,小分组)
config = BaseQuantizeConfig(
bits=4,
group_size=32, # 小分组(更好精度)
desc_act=True, # 激活重排序
damp_percent=0.005 # 更低阻尼
)
权衡:
- 内存:3.5倍减少(稍大)
- 精度:约0.8%困惑度增加(最好)
- 速度:快2-3倍(内核开销)
内核后端
ExLlamaV2(默认,最快)
model = AutoGPTQForCausalLM.from_quantized(
model_name,
device="cuda:0",
use_exllama=True, # 使用ExLlamaV2
exllama_config={"version": 2}
)
性能: 比Triton快1.5-2倍
Marlin(Ampere+ GPU)
# 使用Marlin格式量化
config = BaseQuantizeConfig(
bits=4,
group_size=128,
desc_act=False # Marlin所需
)
model.quantize(calibration_data, use_marlin=True)
# 用Marlin加载
model = AutoGPTQForCausalLM.from_quantized(
model_name,
device="cuda:0",
use_marlin=True # 在A100/H100上快2倍
)
要求:
- NVIDIA Ampere或更新(A100,H100,RTX 40xx)
- 计算能力 ≥ 8.0
Triton(仅Linux)
model = AutoGPTQForCausalLM.from_quantized(
model_name,
device="cuda:0",
use_triton=True # 仅Linux
)
性能: 比CUDA后端快1.2-1.5倍
与Transformers集成
直接使用Transformers
from transformers import AutoModelForCausalLM, AutoTokenizer
# 加载量化模型(Transformers自动检测GPTQ)
model = AutoModelForCausalLM.from_pretrained(
"TheBloke/Llama-2-13B-Chat-GPTQ",
device_map="auto",
trust_remote_code=False
)
tokenizer = AutoTokenizer.from_pretrained("TheBloke/Llama-2-13B-Chat-GPTQ")
# 像任何Transformers模型一样使用
inputs = tokenizer("你好", return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=100)
QLoRA微调(GPTQ + LoRA)
from transformers import AutoModelForCausalLM
from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model
# 加载GPTQ模型
model = AutoModelForCausalLM.from_pretrained(
"TheBloke/Llama-2-7B-GPTQ",
device_map="auto"
)
# 准备LoRA训练
model = prepare_model_for_kbit_training(model)
# LoRA配置
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 添加LoRA适配器
model = get_peft_model(model, lora_config)
# 微调(内存高效!)
# 70B模型可在单A100 80GB上训练
性能基准
内存减少
| 模型 | FP16 | GPTQ 4位 | 减少 |
|---|---|---|---|
| Llama 2-7B | 14 GB | 3.5 GB | 4× |
| Llama 2-13B | 26 GB | 6.5 GB | 4× |
| Llama 2-70B | 140 GB | 35 GB | 4× |
| Llama 3-405B | 810 GB | 203 GB | 4× |
实现:
- 70B在单A100 80GB上(相比FP16需要2×A100)
- 405B在3×A100 80GB上(相比FP16需要11×A100)
- 13B在RTX 4090 24GB上(相比FP16会OOM)
推理速度(Llama 2-7B,A100)
| 精度 | 令牌/秒 | 相比FP16 |
|---|---|---|
| FP16 | 25 tok/s | 1× |
| GPTQ 4位(CUDA) | 85 tok/s | 3.4× |
| GPTQ 4位(ExLlama) | 105 tok/s | 4.2× |
| GPTQ 4位(Marlin) | 120 tok/s | 4.8× |
精度(在WikiText-2上的困惑度)
| 模型 | FP16 | GPTQ 4位(g=128) | 退化 |
|---|---|---|---|
| Llama 2-7B | 5.47 | 5.55 | +1.5% |
| Llama 2-13B | 4.88 | 4.95 | +1.4% |
| Llama 2-70B | 3.32 | 3.38 | +1.8% |
优秀精度保持 - 退化低于2%!
常见模式
多GPU部署
# 自动设备映射
model = AutoGPTQForCausalLM.from_quantized(
"TheBloke/Llama-2-70B-GPTQ",
device_map="auto", # 自动跨GPU分割
max_memory={0: "40GB", 1: "40GB"} # 每GPU限制
)
# 手动设备映射
device_map = {
"model.embed_tokens": 0,
"model.layers.0-39": 0, # 前40层在GPU 0上
"model.layers.40-79": 1, # 后40层在GPU 1上
"model.norm": 1,
"lm_head": 1
}
model = AutoGPTQForCausalLM.from_quantized(
model_name,
device_map=device_map
)
CPU卸载
# 将某些层卸载到CPU(用于非常大的模型)
model = AutoGPTQForCausalLM.from_quantized(
"TheBloke/Llama-2-405B-GPTQ",
device_map="auto",
max_memory={
0: "80GB", # GPU 0
1: "80GB", # GPU 1
2: "80GB", # GPU 2
"cpu": "200GB" # 溢出卸载到CPU
}
)
批量推理
# 高效处理多个提示
prompts = [
"解释AI",
"解释ML",
"解释DL"
]
inputs = tokenizer(prompts, return_tensors="pt", padding=True).to("cuda")
outputs = model.generate(
**inputs,
max_new_tokens=100,
pad_token_id=tokenizer.eos_token_id
)
for i, output in enumerate(outputs):
print(f"提示 {i}: {tokenizer.decode(output)}")
查找预量化模型
HuggingFace上的TheBloke:
- https://huggingface.co/TheBloke
- 1000+ GPTQ格式模型
- 多种分组大小(32,128)
- CUDA和Marlin格式
搜索:
# 在HuggingFace上查找GPTQ模型
https://huggingface.co/models?library=gptq
下载:
from auto_gptq import AutoGPTQForCausalLM
# 从HuggingFace自动下载
model = AutoGPTQForCausalLM.from_quantized(
"TheBloke/Llama-2-70B-Chat-GPTQ",
device="cuda:0"
)
支持模型
- LLaMA系列: Llama 2,Llama 3,Code Llama
- Mistral: Mistral 7B,Mixtral 8x7B,8x22B
- Qwen: Qwen,Qwen2,QwQ
- DeepSeek: V2,V3
- Phi: Phi-2,Phi-3
- Yi,Falcon,BLOOM,OPT
- HuggingFace上100+模型
参考资料
资源
- GitHub: https://github.com/AutoGPTQ/AutoGPTQ
- 论文: GPTQ:准确后训练量化(arXiv:2210.17323)
- 模型: https://huggingface.co/models?library=gptq
- Discord: https://discord.gg/autogptq