趋近智
权重 (weight)量化 (quantization)是一种主要技术,用于减少大型语言模型的内存占用,并通常加快其推理 (inference)速度。其基本思路是将模型通常用32位浮点数(FP32)存储的权重参数 (parameter),转换为8位整数(INT8)甚至4位整数(INT4)等低精度整数格式表示。每个参数的比特宽度减少直接导致模型尺寸变小,并可能在支持低精度计算的硬件上实现更快的运算。
回顾一下,标准FP32格式提供宽泛的动态范围和高精度,这在敏感的训练过程中非常重要。然而,对于推理 (inference)来说,通常可以使用更少的比特位,而不会造成模型准确率的严重下降。
权重量化 (quantization)的核心难点在于将范围宽泛的FP32权重映射到INT8或INT4值的有限范围,同时最大限度地减少对模型性能非常重要的信息损失。
最常用的方法是仿射量化,它使用一个缩放因子 (一个正浮点数)和一个零点 (一个整数,通常与 类型相同),将浮点数值 映射到整数值 。关系如下:
反之,反量化将整数反向映射回近似浮点数:
缩放因子和零点可以以不同方式确定:
权重张量的逐张量和逐通道量化方法的比较。逐通道量化为每个输出通道(本例中为行)使用不同的缩放因子/零点值。
PTQ是一种更简单的方法。您将一个已经用FP32训练好的模型,之后将其权重 (weight)转换为INT8等低精度格式。激活值在推理 (inference)过程中也可能被动态量化。
流程:
示例 (PyTorch 权重):
import torch
import torch.quantization
# 假设 'model' 是您训练好的 FP32 模型
model.eval()
# --- PTQ 静态量化示例 (权重 + 激活值) ---
# 注意:实际的 PTQ 涉及更多步骤,如操作合并和观察器放置
# 指定量化配置(例如,权重的对称 INT8 量化)
# 'fbgemm' 是 x86 常见的后端,'qnnpack' 是 ARM 的后端
qconfig = torch.quantization.get_default_qconfig('fbgemm')
model_prepared = torch.quantization.prepare(model, inplace=False)
model_prepared.qconfig = qconfig
# 校准步骤(输入有代表性的数据)
# calibration_data_loader 提供校准样本
print("正在运行校准...")
with torch.no_grad():
for input_batch, _ in calibration_data_loader:
model_prepared(input_batch) # 前向传播以收集统计数据
print("校准完成。")
# 将模型转换为量化版本
model_quantized_static = torch.quantization.convert(
model_prepared, inplace=False
)
print("模型已转换为静态量化版本。")
# --- PTQ 动态量化示例 (仅权重) ---
# 更简单:权重被量化,激活值实时量化
model_quantized_dynamic = torch.quantization.quantize_dynamic(
model, # 原始的 FP32 模型
{torch.nn.Linear}, # 需要动态量化的层集合
dtype=torch.qint8 # 权重的目标数据类型
)
print("模型已转换为动态量化版本。")
# 现在 'model_quantized_static' 或 'model_quantized_dynamic' 可用于
# 推理。
# 保存/加载这些模型需要专门处理
# 量化参数。
# 示例:检查模型大小减少情况
def print_model_size(mdl, label):
torch.save(mdl.state_dict(), "temp.p")
size = os.path.getsize("temp.p")/1e6
print(f"{label} 的大小: {size:.2f} MB")
os.remove("temp.p")
# print_model_size(model, "FP32 模型")
# print_model_size(model_quantized_dynamic,
# "动态量化 INT8 模型")
# print_model_size(model_quantized_static,
# "静态量化 INT8 模型") # 通常最小
PTQ 的优点:
PTQ 的缺点:
QAT通过在微调 (fine-tuning)或训练过程中模拟量化效果来解决PTQ的准确率限制。这使得模型的权重 (weight)能够适应量化引入的精度损失。
流程:
示例 (PyTorch):
import torch
import torch.quantization
# 假设 'model' 是您训练好的 FP32 模型
# 通常最好从一个收敛的 FP32 检查点开始 QAT
model.train() # QAT 需要训练模式
# 指定 QAT 配置
# 使用 get_default_qat_qconfig 获取适当的伪量化节点
qig_config = torch.quantization.get_default_qat_qconfig(
'fbgemm') # 或 'qnnpack'
model_prepared_qat = torch.quantization.prepare_qat(model, inplace=False)
model_prepared_qat.qconfig = qig_config
# --- QAT 微调循环 ---
print("开始 QAT 微调...")
optimizer = torch.optim.Adam(
model_prepared_qat.parameters(),
lr=1e-5) # 使用较小的学习率
num_qat_epochs = 3 # 通常较短
for epoch in range(num_qat_epochs):
for input_batch, target_batch in qat_training_data_loader:
optimizer.zero_grad()
output = model_prepared_qat(input_batch)
loss = loss_function(output, target_batch) # 使用您的标准损失函数
loss.backward() # 梯度通过伪量化节点经由 STE 传播
optimizer.step()
print(f"QAT 第 {epoch+1}/{num_qat_epochs} 周期完成。")
print("QAT 微调完成。")
# 将 QAT 模型转换为真正的量化模型
model_prepared_qat.eval() # 在转换前设置为评估模式
model_quantized_qat = torch.quantization.convert(model_prepared_qat, inplace=False)
print("模型已转换为 QAT 量化版本。")
# 此模型通常比 PTQ 具有更好的准确率,特别是对于 INT8/INT4
# print_model_size(model_quantized_qat, "QAT 量化 INT8 模型")
QAT 的优点:
QAT 的缺点:
将量化 (quantization)推向INT4甚至更低比特宽度(例如,三元或二元权重 (weight))能提供最大的内存节省,但大幅增加了保持准确率的难度。
bitsandbytes 等库在Hugging Face生态系统中被广泛用于对大型模型应用INT4量化(通常是NF4 - NormalFloat 4位等变体),这些库经常使用将量化与专用矩阵乘法内核相结合的技术。
torch.quantization,而TensorFlow通过TensorFlow Lite或模型优化工具包提供类似工具。Hugging Face的 optimum 和 bitsandbytes 等库专门为Transformer模型集成了量化功能。模型准确率和尺寸之间不同权重量化方法的示意性权衡。实际结果根据模型、任务和使用的具体量化技术而明显不同。
权重量化,特别是通过PTQ或QAT进行的INT8量化,是一种广泛采用的技术,可使大型语言模型更适合部署。尽管INT4提供进一步压缩,但它通常需要更复杂的方法和仔细评估,以确保可接受的性能水平。选择正确的策略取决于模型尺寸、推理延迟和允许的准确率下降的具体要求。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•