Quantization-Aware Training (QAT)
量化感知训练 (QAT) 会在训练过程中模拟 INT8 舍入,让权重在导出前完成适配,从而保留普通 INT8 转换会损失的准确率。
量化感知训练 (QAT) 是一种训练技术,通过在训练期间模拟量化,让模型为低精度推理做好准备。模型通常以 32 位浮点数 (FP32) 进行训练并存储权重;模型量化会将其转换为 8 位整数 (INT8) 等格式以供部署,使权重缩小到原来的四分之一,并让 CPU、GPU 和神经网络处理器 (NPU)能够使用快速整数运算。转换会对每个数值进行舍入并截断离群值,从而损失一部分准确率。QAT 会在模型仍在学习时将舍入操作加入前向传播,让梯度下降找到量化后仍然有效的权重。它通常作为已训练模型的短期微调阶段运行。Google 的仅整数运算推理方案将 INT8 推理与这种训练流程结合起来;此后,QAT 已成为边缘 AI部署的标准工具。
量化感知训练的工作原理#
QAT 会在模型的权重和激活值中添加伪量化操作,也称为量化-反量化 (Q/DQ) 对。每个操作都使用缩放因子和零点将浮点数映射到最接近的 INT8 级别,然后立即再映射回浮点数;因此,网络仍以浮点数进行计算,但看到的数值与 INT8 引擎实际使用的舍入值相同。缩放因子来自校准:校准会记录少量数据批次中每个张量的典型取值范围;某些方法还会在训练期间学习这些缩放因子。
舍入操作几乎处处梯度为零,会阻止学习。QAT 使用直通估计器 (STE),在反向传播期间将舍入步骤视为恒等函数,让梯度传递到基础 FP32 权重:
import torch
# FP32 weights that training keeps and updates
w = torch.tensor([0.3137, -0.7214, 0.0521, 1.1800], requires_grad=True)
# Symmetric INT8 fake quantization: snap each weight to one of 255 levels, then map back to float
scale = w.detach().abs().max().item() / 127
w_q = torch.fake_quantize_per_tensor_affine(w, scale, 0, -127, 127)
print(f"Fake-quantized: {[round(v, 4) for v in w_q.tolist()]}")
# The forward pass sees the rounded weights; the straight-through estimator still delivers gradients to w
x = torch.tensor([1.0, 2.0, 3.0, 4.0])
loss = (w_q * x).sum()
loss.backward()
print(f"Gradient on FP32 weights: {w.grad.tolist()}")前向传播使用舍入后的权重 0.3159、−0.7247、0.0557 和 1.18;每个值与其 FP32 值的差都不超过半个量化步长 (0.0046)。然而,传递到 FP32 权重的梯度恰好等于输入值 1.0、2.0、3.0 和 4.0,仿佛没有发生舍入。经过多次迭代后,优化器会将权重调整到舍入误差影响最小的位置,训练好的模型则会连同学习到的缩放因子一起导出为 INT8。
QAT 与训练后量化对比#
训练后量化 (PTQ)会直接转换已完成训练的 FP32 模型,并使用数百张校准图像设定取值范围。整个过程只需几分钟,也不需要训练流水线,但权重没有机会适应舍入,因此敏感模型的准确率可能会明显下降。QAT 需要使用完整训练数据运行一次微调,但可以弥补大部分准确率损失。团队通常会先尝试 PTQ,只有当 INT8 准确率下降过多时才改用 QAT:
训练时收到 quantize=8 后,Ultralytics YOLO 会运行 QAT:通过 NVIDIA Model Optimizer校准 INT8 伪量化,在训练循环中进行微调,并保存取值范围;导出为 ONNX 和 TensorRT 时,会将这些取值范围写为 Q/DQ 节点,无需单独提供校准数据。在 COCO val2017 上运行的 TensorRT 引擎中,PTQ 将中型 YOLO26 模型的 mAP50-95 从 0.527 降至 0.470,而 QAT 将其保持在 0.514;nano 模型使用 PTQ 仅损失 0.010,因此无需额外进行 QAT。
from ultralytics import YOLO
# 从训练好的 FP32 YOLO26 检查点开始
model = YOLO("yolo26n.pt")
# 在训练循环中加入 INT8 伪量化,以较小的学习率进行微调
model.train(data="coco8.yaml", epochs=5, quantize=8, optimizer="AdamW", lr0=0.00001, cos_lr=True)
# 导出为 ONNX;学习到的 INT8 取值范围会成为 Q/DQ 节点,因此无需校准数据
model.export(format="onnx", quantize=8)QAT 的应用场景#
- 边缘视觉: 在手机、智能摄像头、无人机和 NPU 上运行 INT8 检测器;这些设备的纯整数加速器根本无法运行浮点模型。
- 推理服务器: TensorRT 等 GPU 引擎会运行 INT8 Tensor Core 内核以提高吞吐量,而 QAT 能让准确率接近 FP32。
- 语言模型: QAT 现在已可实现低于 8 位的量化。Google 发布了 Gemma 3 QAT 检查点,采用 4 位 Q4_0 格式,只需少量内存就能将质量保持在接近 bfloat16 的水平。
主流框架都提供 QAT 工具,包括 PyTorch 的 torchao、TensorFlow 的 Model Optimization Toolkit,以及 Intel 为 OpenVINO 提供的 NNCF。










