深度学习模型量化的 INT8/FP16

FreeGuideOnline 最新 2026-07-10

r = S * (q - Z)

其中:
- `S` 是缩放因子(float32),决定量化的步长。
- `Z` 是零点(INT8 值),对应浮点数的 0 点。
- `q` 是量化后的整数,范围 [-128, 127] 或 [0, 255]。

从浮点数到整数的量化公式:

q = round(r / S) + Z

需要将 `q` 截断到允许的范围内。

### 量化方式分类
1. **动态量化**:推理时动态计算激活值的量化参数(`S` 和 `Z`),只对权重预量化。适合 RNN、LSTM 等模型,但每次前向都会增加校准开销。
2. **静态量化**:使用少量校准数据预先统计激活值的 min/max 或利用 KL 散度等算法确定 `S` 和 `Z`,推理时不需要任何浮点计算。速度最快,适合 CNN 和大部分 Transformer。
3. **量化感知训练(QAT)**:在训练过程中模拟量化误差,让模型适应低精度。往往能恢复因量化损失的精度,适合对精度要求极高的场景。

### 校准方法
要让 INT8 准确工作,必须为每层的激活值确定合适的量化范围。常用校准算法:
- **MinMax**:直接使用校准数据中的最小最大值。简单但对离群点敏感。
- **移动平均 MinMax**:在部分批次上统计滑动平均的最小最大值。
- **KL 散度(熵校准)**:将激活值分布与量化后的分布进行比较,选择使信息损失最小的阈值(NVIDIA TensorRT 常用)。
- **百分位**:取某个百分位值(如 99.99%)作为最大绝对值,忽略极端离群点。

### 实际步骤(以 PyTorch 静态量化为例)
```python
import torch
from torch.quantization import quantize_dynamic, prepare, convert

# 1. 定义模型,插入量化节点
model_fp32 = MyModel()
model_fp32.eval()
model_fp32.qconfig = torch.quantization.get_default_qconfig('fbgemm')

# 2. 准备量化(插入观察器)
model_prepared = prepare(model_fp32)

# 3. 使用代表性数据校准
for data in calibration_dataset:
    model_prepared(data)

# 4. 转换为量化模型
model_int8 = convert(model_prepared)