模型量化

模型量化是降低模型计算和存储需求的关键技术。 本文将介绍量化的原理、方法和实践指南, 帮助您有效地应用量化技术。

预计阅读时间:55分钟·难度:中级·更新时间:2024年4月

量化概述

量化是将模型从高精度浮点数转换为低精度整数的过程, 可以显著减少模型大小和计算开销。

量化带来的收益

收益维度FP32→INT8FP32→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 (对称量化)
对称量化

量化范围关于零点对称,实现简单但可能浪费量化范围

非对称量化

根据实际数据分布确定量化范围,精度更高但实现复杂

量化类型

量化精度类型

精度类型位宽压缩比适用场景
FP1616位2倍训练、推理
BF1616位2倍训练
INT88位4倍推理(主流)
INT44位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 QuantizationPyTorch原生支持,易用性好
ONNX RuntimeONNX跨平台,支持多种量化
GPTQ/AWQTransformers大模型INT4量化
llama.cpp独立LLM推理量化

最佳实践

1. 选择合适的量化方法

精度要求高选QAT,快速部署选PTQ

2. 关注敏感层

某些层对量化敏感,可能需要保持FP16

3. 充分校准

PTQ需要足够的校准数据覆盖输入分布

4. 逐层验证

量化后逐层对比输出,定位精度损失来源

5. 混合精度策略

对敏感层使用较高精度,非敏感层使用低精度

----