趋近智
大型语言模型量化 (quantization)在比较环境中得到检验,其中使用了不同的工具包。这涉及利用 bitsandbytes、AutoGPTQ 和 AutoAWQ 等库来量化同一个模型。主要目的是执行命令并观察工作流程、资源需求(尤其是量化阶段的时间)以及生成的模型文件的差异。
本次动手操作将使您更好地理解这些库如何运行,并指出选择量化策略和工具时所涉及的实际利弊。
在开始之前,请确保您已安装并配置好所需的库。我们将使用一个相对较大的模型,因此强烈建议使用具有足够显存 (VRAM)的CUDA GPU,特别是对于涉及校准步骤的GPTQ和AWQ方法。
目标模型: 本次练习中,我们将使用Llama 2 7B模型的一个变体,例如 meta-llama/Llama-2-7b-chat-hf。请记住,访问可能需要通过Hugging Face获得批准。如果您遇到问题或资源受限,可以随意替换为较小的模型,例如 EleutherAI/gpt-neo-1.3B 或 gpt2-large,尽管量化 (quantization)效果会不那么明显。
环境设置: 安装所需软件包。强烈建议使用虚拟环境。
# 基础库
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install transformers accelerate sentencepiece
# bitsandbytes,用于即时量化
pip install bitsandbytes
# AutoGPTQ 及其依赖
pip install auto-gptq optimum
# AutoAWQ 及其依赖
pip install autoawq
# 用于校准数据集(如果GPTQ/AWQ需要)
pip install datasets
注意:请确保您的PyTorch安装与您的CUDA版本兼容。示例假定为CUDA 11.8环境。请查看相应库的文档(bitsandbytes、auto-gptq、autoawq)以了解具体的兼容性要求。
身份验证(如果使用Llama 2等受限模型): 您可能需要登录Hugging Face Hub。
huggingface-cli login
# 按照提示输入您的访问令牌
bitsandbytes 进行量化 (quantization)这通常是应用4位量化最直接的方法,直接集成到transformers加载过程中。当模型加载到内存时,bitsandbytes 会动态执行量化。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import time
model_id = "meta-llama/Llama-2-7b-chat-hf" # 或您选择的模型
# model_id = "EleutherAI/gpt-neo-1.3B" # 如果需要可选择其他模型
print(f"正在加载模型: {model_id}")
# 配置 bitsandbytes 量化
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # 使用NF4以获得更高精度的4位量化
bnb_4bit_compute_dtype=torch.bfloat16, # 推理时的计算类型
bnb_4bit_use_double_quant=True, # 可选:节省内存
)
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_id)
# 加载量化后的模型
start_time = time.time()
model_bnb = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=quantization_config,
device_map="auto", # 自动将层分布到GPU/CPU内存
trust_remote_code=True # 对某些模型来说是必需的
)
end_time = time.time()
print(f"模型已使用 bitsandbytes 4位量化加载。")
print(f"加载时间: {end_time - start_time:.2f} 秒")
# 估算内存占用(需要utils,简化视图)
# 注意:实际显存使用取决于 device_map 和推理工作负载
# 这大致估算了参数内存
param_memory_bytes = sum(p.numel() * p.element_size() for p in model_bnb.parameters())
print(f"大致参数内存 (GPU/CPU): {param_memory_bytes / (1024**3):.2f} GB")
# 可选:测试生成
# prompt = "深度学习中的量化是什么?"
# inputs = tokenizer(prompt, return_tensors="pt").to(model_bnb.device)
# outputs = model_bnb.generate(**inputs, max_new_tokens=50)
# print(tokenizer.decode(outputs[0], skip_special_tokens=True))
观察结果 (bitsandbytes):
model_bnb)可以直接使用。量化在权重 (weight)加载时“即时”进行。默认情况下,此基本方法不会保存单独的量化模型文件。AutoGPTQ 进行量化 (quantization)GPTQ需要校准数据集来确定可最大程度减少精度损失的量化参数 (parameter)。AutoGPTQ 简化了这一过程。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
from optimum.gptq import GPTQQuantizer
import time
from datasets import load_dataset
model_id = "meta-llama/Llama-2-7b-chat-hf" # 或您选择的模型
# model_id = "EleutherAI/gpt-neo-1.3B" # 如果需要可选择其他模型
quantized_model_dir = f"{model_id.split('/')[-1]}-GPTQ"
print(f"正在为 {model_id} 开始 GPTQ 量化")
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_id)
# 准备校准数据集(为演示使用一小部分)
# 使用 'wikitext2' 原始版本,取前几个示例
try:
calibration_dataset = load_dataset("wikitext", "wikitext-2-raw-v1", split="train[:128]")['text'] # 小样本
# 简单分词 - 如有需要,根据模型要求调整
# 注意:为获得最佳效果,可能需要更复杂的预处理
tokenized_dataset = [tokenizer(text, return_tensors="pt").input_ids for text in calibration_dataset if text.strip()]
print(f"正在使用 {len(tokenized_dataset)} 个样本进行校准。")
except Exception as e:
print(f"加载校准数据集失败: {e}")
print("跳过 AutoGPTQ 量化。")
tokenized_dataset = None # 确保变量存在
if tokenized_dataset:
# 配置 GPTQ
gptq_config = GPTQConfig(
bits=4, # 量化到 4 位
group_size=128, # 量化参数的分组大小
dataset=calibration_dataset, # 传递原始文本数据集
desc_act=False, # 激活顺序;False 通常效果不错
tokenizer=tokenizer # 提供分词器用于数据集处理
)
# 初始化量化器
# 首先加载 FP16/BF16 模型用于量化
quantizer = GPTQQuantizer(
bits=gptq_config.bits,
group_size=gptq_config.group_size,
dataset=gptq_config.dataset,
desc_act=gptq_config.desc_act,
model_seqlen=2048 # 检查模型的最大序列长度
)
print("正在加载非量化模型以进行 GPTQ 处理...")
# 首先加载原始模型,使用更高精度
# 此步骤需要大量显存
model_fp = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.float16, # 或 bfloat16,如果支持且更优
device_map="auto",
trust_remote_code=True
)
print("正在开始 GPTQ 量化过程(这可能需要一些时间)...")
start_time = time.time()
# 量化模型
quantized_model = quantizer.quantize_model(model_fp, tokenizer)
end_time = time.time()
print(f"GPTQ 量化完成。")
print(f"量化时间: {end_time - start_time:.2f} 秒")
# 保存量化后的模型和分词器
print(f"正在将量化模型保存到: {quantized_model_dir}")
quantizer.save(quantized_model, quantized_model_dir)
# 如果不使用 quantizer.save 的内置 save_tokenizer,则需要单独保存分词器
tokenizer.save_pretrained(quantized_model_dir)
print("模型和分词器已保存。")
# 清理内存
del model_fp
del quantized_model
torch.cuda.empty_cache()
# 可选:加载已保存的 GPTQ 模型进行验证
# print("正在加载已保存的 GPTQ 模型...")
# model_gptq = AutoModelForCausalLM.from_pretrained(
# quantized_model_dir,
# device_map="auto",
# trust_remote_code=True
# )
# print("GPTQ 模型加载成功。")
# 估算内存占用(不同的加载机制)
# param_memory_bytes = sum(p.numel() * p.element_size() for p in model_gptq.parameters())
# print(f"大致参数内存 (GPU/CPU): {param_memory_bytes / (1024**3):.2f} GB")
观察结果 (AutoGPTQ):
bitsandbytes 更复杂。需要选择和准备校准数据集,配置参数(bits、group_size),并管理一个独立的量化步骤。transformers 或特定的GPTQ加载器相对较快地加载以进行推理 (inference)。AutoAWQ 进行量化 (quantization)AWQ(激活感知权重 (weight)校准)是另一种先进的PTQ方法,其目标是通过找出重要的权重来保持精度。AutoAWQ 提供了一个简化的接口。AWQ量化通常不像GPTQ那样严格需要校准数据集,但它会对模型权重和可能的激活进行分析。
import torch
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
import time
import os
model_id = "meta-llama/Llama-2-7b-chat-hf" # 或您选择的模型
# model_id = "EleutherAI/gpt-neo-1.3B" # 如果需要可选择其他模型
quant_path = f"{model_id.split('/')[-1]}-AWQ"
# 定义量化配置
quant_config = {
"w_bit": 4, # 目标权重位宽
"q_group_size": 128, # 量化缩放因子的分组大小
"zero_point": True, # 使用零点量化(AWQ常见)
}
print(f"正在为 {model_id} 开始 AWQ 量化")
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
# 加载模型并量化 - AutoAWQ 处理基础模型的加载
# 此步骤需要大量显存来加载原始模型
print("正在加载非量化模型以进行 AWQ 处理...")
awq_model = AutoAWQForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.float16, # 或 bfloat16
low_cpu_mem_usage=True, # 尝试在加载期间减少CPU内存使用
device_map="auto", # 让 AWQ 最初处理设备放置
trust_remote_code=True
)
print("正在开始 AWQ 量化过程(这可能需要一些时间)...")
start_time = time.time()
# 执行量化
awq_model.quantize(tokenizer, quant_config=quant_config)
end_time = time.time()
print(f"AWQ 量化完成。")
print(f"量化时间: {end_time - start_time:.2f} 秒")
# AWQ 需要使用特定参数保存以处理潜在的分片
# 如果目录不存在则创建
os.makedirs(quant_path, exist_ok=True)
# 修改配置以兼容 transformers 集成
# AWQ 模型需要特定的配置标志才能在以后正确加载
awq_model.model.config.quantization_config = quant_config
print(f"正在将量化模型保存到: {quant_path}")
# 使用 save_quantized(AutoAWQ 推荐)
# 根据您的偏好/兼容性需求设置 safe_serialization
awq_model.save_quantized(quant_path, safe_serialization=True)
tokenizer.save_pretrained(quant_path)
print("模型和分词器已保存。")
# 清理内存
del awq_model
torch.cuda.empty_cache()
# 可选:加载已保存的 AWQ 模型进行验证
# print("正在加载已保存的 AWQ 模型...")
# from transformers import AutoModelForCausalLM # 使用标准 transformers 加载器
# model_awq = AutoModelForCausalLM.from_pretrained(
# quant_path,
# device_map="auto",
# trust_remote_code=True
# )
# print("AWQ 模型加载成功。")
# 估算内存占用
# param_memory_bytes = sum(p.numel() * p.element_size() for p in model_awq.parameters())
# print(f"大致参数内存 (GPU/CPU): {param_memory_bytes / (1024**3):.2f} GB")
观察结果 (AutoAWQ):
AutoGPTQ 复杂度相似。需要配置量化参数 (parameter)(w_bit、q_group_size)并运行专门的量化步骤。它可能不总是严格需要一个显式的外部校准数据集,因为分析通常侧重于模型自身的权重以及从内部逻辑或小样本中获得的激活。save_quantized)。让我们总结一下本次实践练习中观察到的定性差异。
| 特性 | bitsandbytes(通过 Transformers) |
AutoGPTQ |
AutoAWQ |
|---|---|---|---|
| 主要方法 | 即时加载和量化 (quantization) | 训练后量化(校准) | 训练后量化(分析) |
| 设置难易度 | 最简单 | 中等 | 中等 |
| 量化过程 | 集成到 from_pretrained 中 |
加载FP16后的独立步骤 | 加载FP16后的独立步骤 |
| 校准数据 | 不需要 | 需要(例如,wikitext, c4) | 通常隐式 / 模型分析 |
| 量化时间 | 快(加载一部分) | 慢(校准 + 量化) | 慢(分析 + 量化) |
| 输出 | 内存中的量化模型 | 保存的量化模型文件 | 保存的量化模型文件 |
| 灵活性 | 调整选项有限(量化类型) | 更多参数 (parameter)(分组大小、阻尼) | 更多参数(分组大小、零点) |
| 磁盘空间 | 默认无独立文件 | 量化文件(更小) | 量化文件(更小) |
| 推理 (inference)加载器 | transformers |
transformers / AutoGPTQ |
transformers / AutoAWQ |
要点:
bitsandbytes 提供4位推理的最简单途径,但调整选项较少。AutoGPTQ 和 AutoAWQ 需要更多设置和耗时的量化步骤,但通过校准/分析(GPTQ)或重要的权重 (weight)保留(AWQ),可能更好地保持精度。bitsandbytes)。已保存的量化模型通常比即时量化加载更快。bitsandbytes 将此成本转移到模型加载时间。AutoGPTQ 或 AutoAWQ 量化的模型。本次练习演示了如何使用不同的工具包。下一章“量化LLM的性能评估”将为您提供衡量这些量化过程结果的方法,包括速度、内存使用,以及重要的是,对精度的影响。您将学会如何对在此处生成的模型进行基准测试,以便就哪种量化技术最适合您的特定部署需求做出明智的决定。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•