模型量化
模型量化是降低模型计算和存储需求的关键技术。 本文将介绍量化的原理、方法和实践指南, 帮助您有效地应用量化技术。
预计阅读时间:55分钟·难度:中级·更新时间:2024年4月
量化概述
量化是将模型从高精度浮点数转换为低精度整数的过程, 可以显著减少模型大小和计算开销。
量化带来的收益
| 收益维度 | FP32→INT8 | FP32→INT4 |
|---|---|---|
| 模型大小 | 减少4倍 | 减少8倍 |
| 内存带宽 | 减少4倍 | 减少8倍 |
| 计算速度 | 提升2-4倍 | 提升4-8倍 |
| 精度损失 | 通常<1% | 可能较大 |
量化原理
量化数学原理
量化公式: Q(x) = round(x / scale) + zero_point 反量化公式: x' = (Q(x) - zero_point) * scale 其中: - scale:量化缩放因子 - zero_point:零点偏移 - round():四舍五入函数 量化范围映射: FP32: [-max_val, max_val] INT8: [-128, 127] scale = max_val / 127 zero_point = 0 (对称量化)
对称量化
量化范围关于零点对称,实现简单但可能浪费量化范围
非对称量化
根据实际数据分布确定量化范围,精度更高但实现复杂
量化类型
量化精度类型
| 精度类型 | 位宽 | 压缩比 | 适用场景 |
|---|---|---|---|
| FP16 | 16位 | 2倍 | 训练、推理 |
| BF16 | 16位 | 2倍 | 训练 |
| INT8 | 8位 | 4倍 | 推理(主流) |
| INT4 | 4位 | 8倍 | 大模型推理 |
| 混合精度 | 多种 | 可变 | 平衡精度和性能 |
训练后量化
训练后量化(PTQ)在模型训练完成后进行量化, 无需重新训练,实现简单。
PTQ量化流程
PTQ量化流程: ┌──────────────────────────────────────┐ │ 1. 准备校准数据集 │ │ ├── 选择代表性数据(100-500样本) │ │ └── 覆盖典型输入分布 │ ├──────────────────────────────────────┤ │ 2. 校准量化参数 │ │ ├── 前向传播收集激活值统计 │ │ ├── 计算各层的scale和zero_point │ │ └── 可选:逐层优化量化参数 │ ├──────────────────────────────────────┤ │ 3. 量化模型 │ │ ├── 转换权重为INT8 │ │ ├── 插入量化/反量化节点 │ │ └── 优化算子融合 │ ├──────────────────────────────────────┤ │ 4. 验证精度 │ │ ├── 在测试集上评估 │ │ └── 对比原始模型 │ └──────────────────────────────────────┘
PyTorch INT8量化示例
import torch
from torch.quantization import quantize_dynamic
# 动态量化(简单快速)
model_quantized = quantize_dynamic(
model,
{torch.nn.Linear, torch.nn.LSTM},
dtype=torch.qint8
)
# 静态量化(精度更高)
model.qconfig = torch.quantization.get_default_qconfig('fbgemm')
model_prepared = torch.quantization.prepare(model)
# 校准
with torch.no_grad():
for data in calibration_loader:
model_prepared(data)
# 转换
model_quantized = torch.quantization.convert(model_prepared)量化感知训练
量化感知训练(QAT)在训练过程中模拟量化效果, 可以获得更高的量化精度。
QAT训练流程
QAT训练流程: ┌──────────────────────────────────────┐ │ 1. 准备预训练模型 │ │ └── 使用FP32预训练权重 │ ├──────────────────────────────────────┤ │ 2. 插入伪量化节点 │ │ ├── 在权重和激活后插入FakeQuant │ │ └── 前向传播模拟量化误差 │ ├──────────────────────────────────────┤ │ 3. 微调训练 │ │ ├── 使用较小学习率 │ │ ├── 训练1-5个epoch │ │ └── STE近似梯度 │ ├──────────────────────────────────────┤ │ 4. 转换为真实量化模型 │ │ └── 移除FakeQuant,替换为INT8算子 │ └──────────────────────────────────────┘ STE(直通估计器): 前向:x_q = round(x / s) * s 反向:∂L/∂x ≈ ∂L/∂x_q
QAT训练代码示例
import torch
from torch.quantization import get_default_qat_qconfig, prepare_qat
# 准备QAT
model.qconfig = get_default_qat_qconfig('fbgemm')
model_qat = prepare_qat(model, inplace=True)
# 使用标准训练流程
optimizer = torch.optim.SGD(model_qat.parameters(), lr=1e-4)
for epoch in range(num_epochs):
for data, target in train_loader:
optimizer.zero_grad()
output = model_qat(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
# 转换为量化模型
model_quantized = torch.quantization.convert(model_qat.eval())量化工具
主流量化工具对比
| 工具 | 框架 | 特点 |
|---|---|---|
| TensorRT | 独立 | NVIDIA官方,性能最优 |
| PyTorch Quantization | PyTorch | 原生支持,易用性好 |
| ONNX Runtime | ONNX | 跨平台,支持多种量化 |
| GPTQ/AWQ | Transformers | 大模型INT4量化 |
| llama.cpp | 独立 | LLM推理量化 |
最佳实践
1. 选择合适的量化方法
精度要求高选QAT,快速部署选PTQ
2. 关注敏感层
某些层对量化敏感,可能需要保持FP16
3. 充分校准
PTQ需要足够的校准数据覆盖输入分布
4. 逐层验证
量化后逐层对比输出,定位精度损失来源
5. 混合精度策略
对敏感层使用较高精度,非敏感层使用低精度