端侧模型 INT8 量化实战:从 PyTorch 到 ONNX 的部署压缩全流程
模型训练完只是一个 FP32 的"大胖子"——一个 8 bit 的比特、32 位浮点权重,参数动不动几 MB。手机、树莓派、边缘盒子内存有限,直接部署往往力不从心。量化就是把这段"高清视频压成 MP4"的过程:用更少的 bit 存权重(INT8 只用 8 bit),换更小的体积和更快的推理,代价是少量精度损失。今天我们用 onnxruntime 走一遍端侧模型 INT8 静态量化的完整套路:导出 → 校准 → 量化 → 移动端推理。
为什么量化能省这么多
FP32 每个数占 4 字节,INT8 只占 1 字节。参数直接除以 4,内存占用和最终安装包体积都能砍掉约 75%。同时 INT8 运算在支持 SIMD 加速的 CPU、以及各家 NPU/GPU 上通常更快(读内存少、带宽省了)。
以一个小型的 MobileNetV2 分类模型为例(约 3.4M 参数):
- FP32:约 14 MB
- FP16:约 7 MB(精度几乎无损失,带宽减半)
- INT8:约 3.5 MB(体积再砍一半,精度可能会掉 0.5%-2%)
量化位宽与精度: FP16 对多数任务几乎没有可感知损失;INT8 适合分类、检测、语音等对精度不太敏感的任务;INT4 压得最狠但只推荐给 LLM(配合 GGUF 格式),普通 CNN 用 INT4 精度掉得偏多。检查每种模型时第一件事是确认它的输入模态——量化流程对所有模态通用,但校准数据要选对(音频模型喂音频,图像模型喂图像)。
第一步:把 PyTorch 模型导出成 ONNX
端侧部署前,先把 PyTorch 模型转成通用格式 ONNX(.onnx),这样无论后面接 onnxruntime、TFLite 还是 Core ML 都方便。
|
|
第二步:静态量化(PTQ)——离线玩转校准集
静态量化(Post-Training Quantization,PTQ)是端侧最常用的路子:不需要重新训练,只需提供一小批校准数据,让工具统计每层的激活值范围,从而定出最合适的量化缩放系数。对比 QAT(量化感知训练,需重训,精度更高但成本高),PTQ 是"开箱即用"的最优性价比。
|
|
关键细节:
- 校准集几百张图或几十秒音频就够,不需要太多。
per_channel=True按每个输出通道单独定缩放系数,精度比 per-tensor 更高,几乎可媲美 FP32。- 量化后务必用测试集验证精度:
top1掉了超过 2 个点就要回退用 FP16 或改用 QAT。
第三步:端侧推理(onnxruntime-mobile)
量化完就能扔到手机/边缘设备上跑。onnxruntime 有专门为移动端裁剪的 onnxruntime-mobile(Android/iOS 通用),直接用同一个 .onnx 文件,不用二次转换。
|
|
Android 上通过 Gradle 集成 com.microsoft.onnxruntime:onnxruntime-android 后,用 C API 或 JNI 调用即可,推理代码和桌面端完全一致。量化模型的优势在这里显现:不仅体积小,CPU 推理在这种支持 int8 指令集(ARMv8.1 及以上的 NEON)的芯片上往往能快 30%-70%。
开源方案怎么选
| 方案 | 项目 | 适用场景 |
|---|---|---|
| ONNX Runtime | github.com/microsoft/onnxruntime |
跨平台、PTQ/QAT 都支持,最通用 |
| TensorFlow Lite | github.com/tensorflow/tflite |
Android/嵌入式,生态成熟 |
| llama.cpp + GGUF | github.com/ggml-org/llama.cpp |
LLM 的量化(INT4 等),桌面到移动全平台 |
| MLC-LLM | github.com/mlc-ai/mlc-llm |
手机上跑量化大模型,NPU 加速最好 |
怎么选:传统 CNN/检测/语音模型用 ONNX Runtime 或 TFLite,INT8 足够;如果目标是端侧跑 LLM,那就走 llama.cpp/MLC-LLM 的 GGUF INT4 路线。
小结
量化是端侧模型的"刚需操作",尤其 INT8 静态量化路径最短、收益最直接:torch.onnx.export 导出 → quantize_static 配校准集量化 → onnxruntime-mobile 推理,三步打通。记住三个原则:校准数据必须真实、per_channel 精度更高、做完必验证。下次你的模型塞不进手机时,先量化,别急着换网络结构。