大模型压缩量化技术GPTQ与AWQ原理详解
大模型压缩量化技术:GPTQ 与 AWQ 原理详解 + Python 实战教程
本文不讲复杂数学,只用大白话把量化是怎么回事、GPTQ 和 AWQ 各自怎么干、代码怎么调包,一次讲清楚。
一、先搞懂:什么是模型量化?
一句话概括
把模型里的大数字(比如 16 位浮点数)换成小数字(比如 4 位整数),让模型体积缩小好几倍,跑得更快,显存占用更少。
大白话解释
想象你有一个超大的仓库(模型),里面每个货架上都放着精确到小数点后好几位的价格标签(权重参数),比如 3.14159265,用了 16 位存储(FP16)。
量化就是:把所有价格标签换成整数,比如把 3.14159265 变成 3,只用 4 位甚至更少来存。
- 原来 16 位存一个数 → 现在用 4 位存一个数
- 模型体积直接缩小到 1/4
- 显存占用从 13GB → 3GB 左右
- 推理速度也能提升(整数运算比浮点快)
代价是什么
精度有损失。3.14159265 变成 3,丢掉了 0.14159265 的信息。模型的表现会略微下降。
量化的核心目标就是:在尽量少丢精度的前提下,尽量多压缩体积。 GPTQ 和 AWQ 就是两种"少丢精度"的聪明方法。
量化分几种
| 类型 | 说明 | 典型场景 |
|---|---|---|
| PTQ(训练后量化) | 模型训练完直接压缩,不需要重新训练 | 最常用,GPTQ/AWQ 都属于这类 |
| QAT(量化感知训练) | 训练过程中就模拟量化的效果,让模型提前适应 | 效果更好但成本高,用得少 |
GPTQ 和 AWQ 都是 PTQ(训练后量化)——拿一个已经训练好的模型,直接压缩,不需要重新训练。
量化精度对比
| 精度 | 位宽 | 7B 模型大小 | 说明 |
|---|---|---|---|
| FP32 | 32 位 | ~28 GB | 全精度,几乎没人用 |
| FP16/BF16 | 16 位 | ~14 GB | 标准精度,训练和推理常用 |
| INT8 | 8 位 | ~7 GB | 轻度压缩,几乎无损 |
| INT4 | 4 位 | ~3.5 GB | 主流压缩档位,性价比最高 |
| INT2 | 2 位 | ~1.75 GB | 极限压缩,效果损失明显 |
当前主流:INT4 量化是大模型部署的甜点位——体积压缩 4 倍,效果损失通常在 1-2% 以内,肉眼几乎无感。
二、朴素量化为什么不行?
在讲 GPTQ 和 AWQ 之前,先说说"笨办法"为什么不好,你才能理解聪明办法妙在哪。
笨办法:均匀量化(Min-Max 量化)
最直觉的做法:找到所有权重里最大的值和最小的值,然后把范围均匀切成若干档,每个权重四舍五入到最近的档。
问题在于:一刀切地四舍五入,误差不可控。
打个比方:你有一堆人,身高从 1.5 米到 2.0 米,要量化成 4 档(1.5、1.67、1.83、2.0)。大部分人四舍五入到最近的档,误差不大。但如果有个人恰好 1.58 米,被归到 1.5 这档,误差是 8 厘米——对整体"平均身高"的影响可能不大,但如果这个人的权重(重要性)特别高,这个误差就会显著影响模型输出。
关键洞察:不是所有参数都一样重要。重要的参数量化错了,影响很大;不重要的参数量化错了,无所谓。
GPTQ 和 AWQ 各自从不同角度解决这个问题:
- GPTQ:量化时考虑"这个参数量化后,对输出影响有多大",影响大的就小心量化
- AWQ:量化前先找到"哪些参数最重要",重要的参数特殊保护
三、GPTQ 原理(大白话版)
全称
GPTQ: GPT-Post-Training Quantization
一句话概括
逐层量化,每量化一个参数就考虑它对整个层输出的影响,用二阶信息(曲率)来"补偿"量化误差,让后续参数来"吸收"前面参数的量化误差。
大白话解释
核心思想:量化不是孤立地看每个参数,而是考虑参数之间的"连带影响"
想象你在搭积木塔。朴素量化就像随机抽掉一些积木——抽到承重的积木,塔就塌了。
GPTQ 的做法更聪明:
- 逐个参数处理:不一次性量化所有参数,而是一个一个来
- 量化一个,补偿其余:量化第 1 个参数后产生了误差,GPTQ 会调整还没量化的参数,让它们来"吸收"这个误差
- 用"曲率"信息判断重要性:它不是瞎补偿,而是用一种叫"Hessian 矩阵"的东西来判断——某个方向上参数变化对输出影响大不大。影响大的方向上,补偿就更积极
再打个比方
你在做预算压缩。有 100 个项目,每个项目有预算,现在要砍掉 75%(4 位量化)。
朴素做法:每个项目平均砍 75%。
GPTQ 做法:
- 先砍第 1 个项目的预算
- 砍完发现:“哦,砍这个项目导致总效果差了一点”,于是调整第 2 个项目的预算,多给一点来弥补
- 然后砍第 2 个项目,再调整第 3 个来弥补……
- 逐个项目推进,每砍一个都用之前积累的信息来智能调整后续
这样最终的总误差比"一刀切"小得多。
"逐层"是什么意思
GPTQ 不是对整个模型一起量化,而是一层一层来。每一层(Transformer 的一个 block)独立量化,量化时用一小批校准数据跑一下这层的输入输出,以此计算"曲率"信息。
这也是为什么 GPTQ 量化需要校准数据集——不需要训练,但需要几百条数据跑一遍前向传播。
GPTQ 的特点
| 方面 | 说明 |
|---|---|
| 量化方式 | 权重量化(只量化权重,激活值不量化) |
| 典型精度 | INT4,也支持 INT8、INT2 |
| 需要校准数据 | 是,需要几百条数据 |
| 量化速度 | 较慢(需要逐层计算 Hessian),7B 模型大约几十分钟到 1-2 小时 |
| 推理速度 | 快(配合 GPTQ 推理内核) |
| 效果 | INT4 下效果损失很小,通常 PPL 增加 < 1 |
背后的理论
GPTQ 脱胎于一个经典理论叫 OBQ(Optimal Brain Quantization),核心是用二阶信息(Hessian 矩阵的逆)来指导量化顺序和误差补偿。GPTQ 的贡献是把这个理论工程化,让它能在几小时内量化几百亿参数的大模型。
你不需要记住 Hessian 是什么,只需要知道:它衡量的是"参数变化对输出的影响有多大",GPTQ 用它来智能补偿误差。
四、AWQ 原理(大白话版)
全称
AWQ: Activation-Weighted Quantization(激活感知权重量化)
一句话概括
不是所有权重都一样重要——和"大激活值"对应的权重才是关键,量化时重点保护这部分权重,其余的随便量化。
大白话解释
核心洞察:权重的重要性不是看权重本身的大小,而是看它对应的激活值有多大
模型推理时,输入数据经过每一层,会产生"激活值"(activation)。有些通道的激活值很大,有些很小。
AWQ 发现了一个关键现象:
激活值大的通道,对应的权重量化误差对模型输出影响也大。 把这些权重量化错了,模型效果会明显下降。而激活值小的通道,权重量化错了也无所谓。
打个比方:一个公司有 100 个员工,其中 5 个是核心骨干(激活值大),95 个是普通员工(激活值小)。砍预算时:
- 普通员工的预算随便砍(量化误差大也无所谓)
- 核心骨干的预算要保护(量化误差必须小)
怎么"保护"重要权重?——缩放技巧
AWQ 的巧妙之处在于它保护重要权重的方式。它不是简单地把重要权重保持高精度(那叫混合精度,太复杂),而是用一个缩放技巧:
- 先找出激活值大的通道(通过跑校准数据得到激活值统计)
- 把这些通道的权重乘以一个大于 1 的系数 s(放大)
- 放大后再做量化——同样的量化精度下,大值的相对误差更小
- 推理时,对应的激活值除以同样的系数 s(缩小回来),最终输出不变
再打个比方:你要用一把最小刻度 1 毫米的尺子(4 位量化)量一根 0.3 毫米的细丝(重要权重),误差很大。怎么办?先把细丝放大 10 倍变成 3 毫米,用尺子量出 3 毫米,再除以 10 得到 0.3 毫米——精度从"误差 0.3 毫米"变成了"误差 0.1 毫米"。
关键:放大权重 → 量化误差相对变小 → 缩小回来后误差也变小。数学上等价于保护了重要权重。
不需要反向传播
AWQ 的另一个优点:不需要梯度回传,不需要训练。它只是:
- 跑校准数据得到激活值统计 → 找到重要通道
- 计算最佳缩放系数
- 缩放 + 量化
整个过程是前向计算,非常快。
AWQ 的特点
| 方面 | 说明 |
|---|---|
| 量化方式 | 权重量化(只量化权重) |
| 典型精度 | INT4,也支持 INT3、INT8 |
| 需要校准数据 | 是,但只需少量数据 |
| 量化速度 | 比 GPTQ 快(不需要计算 Hessian),通常几分钟到十几分钟 |
| 推理速度 | 快(配合 AWQ 推理内核) |
| 效果 | INT4 下效果甚至略优于 GPTQ,尤其在小模型上 |
五、GPTQ vs AWQ 正面对比
| 维度 | GPTQ | AWQ |
|---|---|---|
| 核心思路 | 逐参数量化 + 误差补偿 | 找重要权重 + 缩放保护 |
| 用什么判断重要性 | Hessian 矩阵(二阶信息) | 激活值大小 |
| 量化速度 | 较慢(逐层算 Hessian) | 较快(只需前向统计) |
| 效果 | 优秀,大模型上很稳 | 优秀,小模型上略优 |
| 需要校准数据量 | 几百条 | 几百条(可以更少) |
| 推理框架支持 | vLLM、Text Generation Inference、Transformers | vLLM、Transformers、多种框架 |
| 社区生态 | 成熟,auto-gptq 库广泛使用 | 成熟,autoawq 库广泛使用 |
| 适合场景 | 追求极致效果,不介意量化时间长 | 追求快速量化 + 好效果 |
总结建议:
- 想快速量化、追求效率 → AWQ
- 想极致效果、不差时间 → GPTQ
- 实际差异通常很小(INT4 下 PPL 差距 < 0.5),两个都试一下选最好的即可
六、Python 实战:用 GPTQ 压缩模型
6.1 环境安装
# 安装 auto-gptq(GPTQ 的官方 Python 库)
# 注意:auto-gptq 依赖 torch,建议先装好 CUDA 版 PyTorch
pip install auto-gptq optimum
# 如果你用的是 transformers 集成方式
pip install transformers accelerate
重要提示:auto-gptq 安装时需要编译 CUDA 算子,请确保你的环境有 CUDA toolkit。Windows 上可能需要额外配置,建议在 Linux 环境下操作。
6.2 用 auto-gptq 量化模型(完整代码)
import torch
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
from transformers import AutoTokenizer
# ========================
# 第一步:设置模型路径和量化参数
# ========================
# 要量化的原始模型(可以是 HuggingFace 上的模型名,也可以是本地路径)
model_path = "Qwen/Qwen2-7B" # 换成你想量化的模型
# 量化后模型的保存路径
quant_path = "./qwen2-7b-gptq-4bit"
# 量化配置
quant_config = BaseQuantizeConfig(
bits=4, # 量化到 4 位
group_size=128, # 分组大小,每 128 个权重共享一组量化参数,越小精度越高、速度越慢
desc_act=False, # 是否按激活值降序排列权重再量化(True 效果更好但更慢)
)
# ========================
# 第二步:加载 tokenizer 和校准数据
# ========================
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
# 准备校准数据
# GPTQ 需要一小批文本数据来计算 Hessian 信息
# 这里用简单的示例文本,实际建议用领域相关数据
calibration_texts = [
"人工智能是计算机科学的一个分支,它致力于研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统。",
"大语言模型是基于深度学习的自然语言处理技术,通过在海量文本数据上训练,模型能够理解和生成人类语言。",
"模型量化是一种模型压缩技术,通过降低模型参数的精度来减少模型大小和推理时的计算开销。",
"Transformer 架构由 Google 在 2017 年提出,它完全基于注意力机制,摒弃了循环和卷积结构。",
"GPU 图形处理器最初用于渲染图像,后来因其强大的并行计算能力被广泛应用于深度学习领域。",
# 实际使用时建议准备 128~512 条校准文本,覆盖你的使用场景
# 可以从训练集中采样,或者用通用数据集
]
# 将文本编码为模型输入格式
calibration_data = []
for text in calibration_texts:
encoded = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
calibration_data.append(encoded["input_ids"])
# ========================
# 第三步:加载模型并执行量化
# ========================
print("开始加载模型...")
model = AutoGPTQForCausalLM.from_pretrained(
model_path,
quant_config,
trust_remote_code=True,
device="cuda:0", # 量化需要在 GPU 上进行
)
print("开始量化,这个过程可能需要一段时间...")
model.quantify(calibration_data)
# ========================
# 第四步:保存量化后的模型
# ========================
print(f"保存量化模型到 {quant_path} ...")
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)
print("量化完成!")
6.3 加载 GPTQ 量化模型进行推理
from transformers import AutoModelForCausalLM, AutoTokenizer
quant_path = "./qwen2-7b-gptq-4bit"
# 加载量化后的模型(transformers 原生支持 GPTQ 格式)
tokenizer = AutoTokenizer.from_pretrained(quant_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
quant_path,
device_map="auto", # 自动分配到可用的 GPU/CPU
trust_remote_code=True,
)
# 推理测试
inputs = tokenizer("人工智能的未来发展方向是什么?", return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
6.4 使用 transformers 的 GPTQConfig 一行量化(更简洁的写法)
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_path = "Qwen/Qwen2-7B"
quant_path = "./qwen2-7b-gptq-4bit"
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
# 定义 GPTQ 量化配置
gptq_config = GPTQConfig(
bits=4,
group_size=128,
desc_act=False,
dataset="c4", # 使用内置的 c4 数据集做校准,也可以传入自定义数据
)
# 加载模型时就完成量化
model = AutoModelForCausalLM.from_pretrained(
model_path,
quantization_config=gptq_config,
device_map="auto",
trust_remote_code=True,
)
# 保存
model.save_pretrained(quant_path)
tokenizer.save_pretrained(quant_path)
提示:
GPTQConfig的dataset参数支持内置数据集名(如"c4"、"ptb"),也可以传入自定义文本列表。省去手动准备校准数据的麻烦。
七、Python 实战:用 AWQ 压缩模型
7.1 环境安装
# 安装 autoawq(AWQ 的官方 Python 库)
pip install autoawq
# 同时确保有 transformers 和 accelerate
pip install transformers accelerate
7.2 用 AutoAWQ 量化模型(完整代码)
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
# ========================
# 第一步:设置模型路径
# ========================
model_path = "Qwen/Qwen2-7B" # 换成你想量化的模型
quant_path = "./qwen2-7b-awq-4bit"
# ========================
# 第二步:加载模型和 tokenizer
# ========================
print("加载模型...")
model = AutoAWQForCausalLM.from_pretrained(
model_path,
device_map="auto",
trust_remote_code=True,
)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
# ========================
# 第三步:配置量化参数
# ========================
# AWQ 量化配置
quant_config = {
"zero_point": True, # 是否使用零点(Zero Point),通常 True 效果更好
"q_group_size": 128, # 分组大小,和 GPTQ 的 group_size 概念一样
"w_bit": 4, # 权重量化到 4 位
"version": "GEMM", # 量化版本:GEMM(最快,适合 GPU)、GEMV(适合批量=1)
}
# ========================
# 第四步:执行量化
# ========================
print("开始 AWQ 量化...")
# AutoAWQ 会自动使用内置的校准数据集(默认是 pile 数据集)
# 也可以通过传入自定义数据来校准
model.quantize(
tokenizer,
quant_config=quant_config,
# 如需自定义校准数据,可以取消下面注释:
# calib_data="path/to/your/data", # 可以是文件路径、数据集名、或文本列表
)
# ========================
# 第五步:保存量化模型
# ========================
print(f"保存量化模型到 {quant_path} ...")
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)
print("AWQ 量化完成!")
7.3 加载 AWQ 量化模型进行推理
from transformers import AutoModelForCausalLM, AutoTokenizer
quant_path = "./qwen2-7b-awq-4bit"
# transformers 原生支持加载 AWQ 格式的模型
tokenizer = AutoTokenizer.from_pretrained(quant_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
quant_path,
device_map="auto",
trust_remote_code=True,
)
# 推理测试
inputs = tokenizer("大模型量化的优势和劣势分别是什么?", return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
7.4 使用自定义校准数据(推荐)
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
model_path = "Qwen/Qwen2-7B"
quant_path = "./qwen2-7b-awq-4bit-custom"
model = AutoAWQForCausalLM.from_pretrained(model_path, device_map="auto", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
# 自定义校准数据——使用你实际业务场景的文本
# 这样量化出来的模型在你的场景下效果更好
custom_calib_data = [
"你的业务文本1...",
"你的业务文本2...",
"你的业务文本3...",
# 建议准备 128~256 条,覆盖你的使用场景
]
quant_config = {
"zero_point": True,
"q_group_size": 128,
"w_bit": 4,
"version": "GEMM",
}
# 传入自定义校准数据
model.quantize(
tokenizer,
quant_config=quant_config,
calib_data=custom_calib_data, # 关键:传入自定义数据
)
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)
print("使用自定义校准数据的 AWQ 量化完成!")
八、进阶:用 vLLM 部署量化模型(生产环境推荐)
量化后的模型如果在 HuggingFace Transformers 里跑,速度提升有限。要真正发挥量化模型的推理速度优势,推荐用 vLLM:
# vLLM 同时支持 GPTQ 和 AWQ 格式的量化模型
# 安装 vLLM
# pip install vllm
from vllm import LLM, SamplingParams
# 直接加载量化模型(vLLM 会自动识别 GPTQ 或 AWQ 格式)
llm = LLM(
model="./qwen2-7b-gptq-4bit", # 或 "./qwen2-7b-awq-4bit"
trust_remote_code=True,
quantization="gptq", # 如果是 AWQ 就写 "awq"
)
# 批量推理
prompts = [
"请解释什么是深度学习。",
"Python 和 Java 的主要区别是什么?",
]
sampling_params = SamplingParams(temperature=0.7, max_tokens=200)
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
print(output.outputs[0].text)
print("---")
vLLM 的优势:PagedAttention + 连续批处理,推理吞吐量比 Transformers 高 5-20 倍,量化模型在 vLLM 上的加速效果最明显。
九、完整对比速查表
| 维度 | GPTQ | AWQ |
|---|---|---|
| Python 库 | auto-gptq / transformers.GPTQConfig |
autoawq / transformers.AwqConfig |
| 核心代码行数 | ~30 行 | ~20 行 |
| 量化 7B 模型耗时 | 30min ~ 2h(取决于 GPU) | 5min ~ 20min |
| 校准数据需求 | 128~512 条 | 128~256 条 |
| 量化后格式 | GPTQ 格式(HuggingFace 标准) | AWQ 格式(HuggingFace 标准) |
| vLLM 支持 | ✅ quantization="gptq" |
✅ quantization="awq" |
| INT4 效果 | 优秀 | 优秀(通常略优) |
| 安装难度 | 中(需编译 CUDA 算子) | 中(需编译 CUDA 算子) |
| Windows 支持 | 较困难,建议 WSL2 | 较困难,建议 WSL2 |
十、常见问题(FAQ)
Q1:量化后模型效果下降多少?
A:INT4 量化下,主流大模型(7B~70B)在标准 benchmark 上的精度损失通常在 1-3% 以内。对话和生成场景下,人工几乎感知不到差异。INT8 几乎无损。
Q2:GPTQ 和 AWQ 选哪个?
A:如果你追求快速完成量化,选 AWQ(更快);如果你追求极致效果,选 GPTQ(更精细)。实际差异通常很小,建议两个都试,在你的业务数据上评测后选更好的。
Q3:量化需要多大的 GPU?
A:量化过程需要把模型加载到 GPU 显存。7B 模型 FP16 约需 14GB 显存,量化过程中峰值约 16-18GB。建议使用 16GB 以上显存的 GPU(如 V100 16G、A10、RTX 3090/4090)。
Q4:能量化到 INT2 吗?
A:技术上可以,但 INT2 的精度损失非常大(PPL 可能翻倍),通常只在极端资源受限场景下使用。不建议日常使用 INT2。
Q5:量化后还能微调吗?
A:可以,但需要 QLoRA 等技术(用量化模型做 LoRA 微调)。直接对量化模型做全参数微调比较困难。推荐用 peft 库 + bitsandbytes 做 QLoRA。
Q6:group_size 怎么选?
A:group_size=128 是最常用的默认值。更小(如 64)精度更高但速度更慢;更大(如 256)速度更快但精度略低。128 是公认的甜点位。设为 -1 表示不分组(per-channel 量化),精度最高但可能影响推理速度。
Q7:Windows 上能用吗?
A:auto-gptq 和 autoawq 都需要编译 CUDA 算子,Windows 原生环境编译困难。强烈建议使用 Linux 或 WSL2。如果必须在 Windows 上用,可以尝试寻找预编译的 wheel 包,或者直接使用已经量化好的模型(HuggingFace 上有大量社区量化好的 GPTQ/AWQ 模型可直接下载使用)。
十一、总结:三句话记住核心
-
量化就是把模型的大数字换小数字,INT4 是性价比最高的档位——体积缩 4 倍,效果几乎不降。
-
GPTQ 是"逐个参数量化 + 智能补偿"——量化一个参数产生的误差,让后面的参数来弥补。用 Hessian 矩阵判断哪些参数重要,精细但慢。
-
AWQ 是"找重要权重 + 放大保护"——通过激活值找出重要权重,放大后再量化来降低相对误差。思路简洁、速度快、效果优秀。
两者都是 训练后量化(PTQ),都不需要重新训练,只需少量校准数据。Python 调包只需几十行代码,生产部署推荐配合 vLLM 使用。
本文面向概念理解和实操入门。如需深入了解数学原理,建议阅读原始论文:GPTQ (Frantar et al., 2022)、AWQ (Lin et al., 2023)。
更多推荐
所有评论(0)