共计 2597 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点:为什么要做模型量化?
最近在边缘设备(比如 Jetson 系列)上部署 AI 模型时,发现 FP32 精度的模型存在两个明显问题:

- 内存占用高 :一个普通的 ResNet-18 模型就要占用近百 MB 内存,对于嵌入式设备来说压力很大
- 推理延迟大 :在 Jetson Xavier 上跑一个 FP32 的 YOLOv5s,单帧处理要 50ms+,很难满足实时性要求
这让我开始研究模型量化(Quantization)技术——通过降低数值精度来减小模型体积、提升推理速度。经过实测,INT8 量化可以使模型体积缩小 4 倍,推理速度提升 3 倍左右,而且精度损失通常控制在 1% 以内。
技术选型:PTQ 还是 QAT?
量化方案主要有两种,各有适用场景:
1. PTQ(Post-Training Quantization,训练后量化)
- 优点 :
- 无需重新训练,直接对现有模型操作
- 实现简单快速,适合快速部署
- 缺点 :
- 精度损失相对较大
- 对非常规模型结构(如自定义算子)支持有限
2. QAT(Quantization-Aware Training,量化感知训练)
- 优点 :
- 训练时模拟量化过程,最终精度更高
- 支持复杂模型结构
- 缺点 :
- 需要重新训练,时间成本高
- 训练过程需要调整超参数
选择建议 :
– 如果是标准模型(如 ResNet、MobileNet),优先尝试 PTQ
– 如果是自定义模型或对精度要求极高(<0.5% 损失),再考虑 QAT
实战:PyTorch + TensorRT 量化全流程
1. PyTorch 模型准备
首先导出带校准数据的模型:
import torch
from torch.quantization import quantize_dynamic
# 加载预训练模型
model = torch.hub.load('pytorch/vision', 'resnet18', pretrained=True)
model.eval()
# 动态量化(最简单的 PTQ 方式)quantized_model = quantize_dynamic(
model,
{torch.nn.Linear, torch.nn.Conv2d},
dtype=torch.qint8
)
2. TensorRT 引擎构建
关键配置参数说明:
import tensorrt as trt
# 创建 builder 和 config
logger = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(logger)
config = builder.create_builder_config()
# 设置 INT8 量化标志和校准器
config.set_flag(trt.BuilderFlag.INT8)
config.int8_calibrator = MyCalibrator() # 需要实现校准器接口
# 设置优化 profile
profile = builder.create_optimization_profile()
profile.set_shape("input", (1,3,224,224), (8,3,224,224), (32,3,224,224))
config.add_optimization_profile(profile)
3. 完整部署代码示例
# 模型序列化(PyTorch -> ONNX)torch.onnx.export(
quantized_model,
dummy_input,
"resnet18_int8.onnx",
opset_version=13,
input_names=["input"],
output_names=["output"]
)
# TensorRT 引擎生成
with trt.Builder(logger) as builder, \
builder.create_network(1) as network, \
trt.OnnxParser(network, logger) as parser:
# 解析 ONNX 模型
with open("resnet18_int8.onnx", "rb") as f:
parser.parse(f.read())
# 构建引擎
engine = builder.build_serialized_network(network, config)
# 保存引擎文件
with open("resnet18_int8.engine", "wb") as f:
f.write(engine)
性能验证:Jetson Xavier 实测数据
| 指标 | FP32 模型 | INT8 量化模型 | 提升幅度 |
|---|---|---|---|
| 模型大小 | 44.6MB | 11.2MB | 4x |
| 内存占用 | 158MB | 42MB | 3.76x |
| 推理延迟 | 48ms | 15ms | 3.2x |
| Top- 1 精度 | 69.8% | 69.1% | -0.7% |
避坑指南
1. 量化敏感层识别
通过逐层量化分析找出敏感层(精度下降 >3% 的层):
# PyTorch 提供的敏感层分析工具
from torch.quantization.observer import HistogramObserver
for name, module in model.named_modules():
if isinstance(module, torch.nn.Conv2d):
# 添加观察器记录数值分布
module.qconfig = torch.quantization.get_default_qconfig('fbgemm')
module.activation_post_process = HistogramObserver()
2. 动态范围校准常见错误
- 错误做法 :使用测试集的少量样本做校准
- 正确做法 :准备 500-1000 张有代表性的校准图片,覆盖所有可能输入场景
3. 跨平台部署问题
- TensorRT 版本要与 CUDA/cuDNN 严格匹配
- Jetson 设备需要安装 JetPack 对应版本的 TensorRT
- ONNX opset 建议使用 11 或 13 版本
进阶方向
如果还想进一步优化,可以尝试:
1. 混合精度量化 :对敏感层保持 FP16,其他层用 INT8
2. 稀疏化压缩 :结合 Pruning 技术,先剪枝再量化
3. 量化感知训练 :使用 QAT 获得更好的精度
总结
通过这次实践,我总结了量化部署的三个关键点:
1. 校准数据要充足 :至少 500 张有代表性的图片
2. 测试要全面 :不仅要测精度,还要测边缘 case
3. 版本要匹配 :PyTorch/ONNX/TensorRT 的版本链必须兼容
量化技术让我们的模型在边缘设备上跑得更快、更轻量,但也要注意精度与性能的平衡。希望这篇实战笔记对你有帮助!
正文完
