不能只用quantize_dynamic,因其仅量化权重而不量化激活,无法触发INT8算子融合,在ARM CPU上不提速且不被移动端框架支持;必须采用PTQ+QAT预备流程,并严格完成校准、convert、freeze及optimize_for_mobile等步骤才能获得可部署的真正加速模型。

PyTorch 的 torch.quantization 支持 INT8 量化,但直接调用 quantize_dynamic 或 quantize_static 很可能得不到可部署的、真正加速的模型——尤其在移动端,必须走 **后训练静态量化(PTQ) + 量化感知训练(QAT)预备流程**,否则精度掉太多、推理反而变慢。
为什么不能只用 quantize_dynamic?
动态量化只量化权重(weight),不量化激活(activation),所以实际运行时仍需 float 运算路径,ARM CPU 上基本不提速;而且它不生成真正的 INT8 tensor,无法被 NCNN、TNN 或 PyTorch Mobile 的 Lite Interpreter 正确加载。
常见错误现象:torch.jit.save(model, "q.pt") 后在 Android 上用 torch::jit::load() 加载失败,报错 Unsupported op: aten::quantize_per_tensor —— 这说明模型里混着未适配的量化算子。
- 仅适用于纯 CPU 推理且对延迟不敏感的场景(如小模型离线分析)
- 不支持 Conv/Linear 后接 ReLU 的融合(即无法触发
QuantizedConv2d + QuantizedReLU) - 导出为 TorchScript 后,
torch.jit.freeze()必须在量化后、保存前调用,否则量化信息丢失
静态量化必须做校准(calibration),且输入数据要有代表性
静态量化依赖统计激活值的分布(min/max 或 histogram),校准数据必须覆盖真实推理时的典型 range。用全零或随机噪声输入跑 model(x),会导致 scale 偏差极大,精度崩塌。
立即学习“Python免费学习笔记(深入)”;
实操建议:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 从真实验证集抽 100–500 张图(别用训练集,避免过拟合校准统计量)
- 预处理方式必须和训练/部署完全一致(包括归一化参数、尺寸缩放、channel order)
- 调用
torch.quantization.prepare(model, inplace=True)后,一定要执行完整前向(至少一次完整 batch),否则observer没收集到数据 - 校准结束后必须显式调用
torch.quantization.convert(model, inplace=True),否则仍是 float 模型,只是挂了 observer
导出为 TorchScript 时必须 freeze + optimize_for_mobile
未 freeze 的量化模型包含 Python 控制流和未绑定的 observer,无法跨平台加载;而 optimize_for_mobile 不仅做图优化,还会把 quantized::conv2d_relu 等算子映射到移动端友好的内核。
关键步骤顺序不能错:
model.eval() torch.quantization.prepare(model, inplace=True) # run calibration forward torch.quantization.convert(model, inplace=True) scripted = torch.jit.script(model) scripted_opt = torch.jit.freeze(scripted) # 必须 freeze 再 optimize mobile_model = torch.utils.mobile_optimizer.optimize_for_mobile(scripted_opt)
漏掉 freeze() 会导致 mobile_optimizer 报错 Cannot optimize a non-frozen ScriptModule;漏掉 optimize_for_mobile() 则模型体积大、ARM NEON 指令没启用,实测推理慢 2–3 倍。
移动端部署前务必验证量化后输出与 FP32 的误差
INT8 量化必然引入误差,但误差应集中在低敏感区域(如背景、纹理)。不能只看 top-1 accuracy,要对比相同输入下 float 模型和量化模型的输出 tensor 差异:
- 用
torch.nn.functional.cosine_similarity算 logits 相似度,低于 0.95 就要警惕 - 对检测/分割模型,重点看 bbox 坐标偏移是否超过 2 像素、mask IOU 是否下降 >3%
- 如果误差大,优先尝试更换 observer:把默认的
MinMaxObserver换成PerChannelMinMaxObserver(对 weight)+HistogramObserver(对 activation) - 某些层(如最后的 classifier)可单独设
skip_quant:用qconfig_dict = {"module_name": [("layer.name", None)]}
量化不是“开关一开就完事”,校准数据质量、observer 选择、freeze 时机、移动端优化链路,任意一环断掉,得到的都不是能落地的 INT8 模型。


















