模型量化对比实验:INT8、FP16、混合精度到底差多少

前言
量化不是无脑转 INT8 就完事了。不同模型、不同精度策略,结果差距很大。下面是实际跑的一组对比实验,覆盖 ResNet50、YOLOv5、BERT-base 三个模型。
一、实验环境
| 项目 | 配置 |
|---|---|
| 硬件 | 昇腾 910 × 1 |
| CANN 版本 | 7.0.RC1 |
| 量化工具 | AMCT |
| 校准集 | 训练集随机采样 500 张/条 |
| 评估集 | 标准验证集 |
二、ResNet50:量化效果最好
ResNet50 是最「量化友好」的模型。卷积层的权重分布比较集中,激活值的动态范围也不大,INT8 量化精度损失很小。
精度对比
| 精度策略 | Top-1 准确率 | 相对 FP32 损失 | 推理速度 | 显存占用 |
|---|---|---|---|---|
| FP32 | 76.13% | - | 12ms | 4.2GB |
| FP16 | 76.10% | -0.03% | 8ms | 2.1GB |
| INT8(全量化) | 75.81% | -0.32% | 5ms | 1.1GB |
| INT8(跳过 conv1+fc) | 75.96% | -0.17% | 5.5ms | 1.3GB |
INT8 全量化的精度损失只有 0.32%,可以忽略。跳过首尾层之后损失更小(0.17%),但速度慢了 10%(少了两个融合算子)。ResNet50 的建议:直接全量化 INT8,不用跳过任何层。
校准集大小的影响
| 校准集大小 | INT8 Top-1 | 与 FP32 差值 |
|---|---|---|
| 50 张 | 74.82% | -1.31% |
| 200 张 | 75.64% | -0.49% |
| 500 张 | 75.81% | -0.32% |
| 1000 张 | 75.84% | -0.29% |
500 张以后收益递减。校准集不需要太大,500 张够用。
三、YOLOv5:检测头很敏感
YOLOv5 的骨干网络(CSPDarknet)量化效果不错,但检测头(PANet + Detect)对量化比较敏感。
精度对比
| 精度策略 | mAP@0.5 | 相对 FP32 损失 | 推理速度 |
|---|---|---|---|
| FP32 | 0.674 | - | 18ms |
| FP16 | 0.673 | -0.001 | 11ms |
| INT8(全量化) | 0.641 | -0.033 | 7ms |
| INT8(跳过检测头) | 0.668 | -0.006 | 8.5ms |
全量化 INT8,mAP 掉了 3.3 个点,小目标的检测精度损失尤其大(小目标的激活值小,量化后信噪比低)。跳过检测头之后,精度只掉 0.6 个点,速度仍然比 FP16 快 23%。
YOLOv5 的建议:骨干网络量化 INT8,检测头保留 FP16。这就是「混合精度量化」——不是所有层都用同一种精度。
AMCT 混合精度配置
import amct
# 指定检测头用 FP16
config = amct.create_quant_config(
model,
skip_layers=["model.24.m", "model.24.cv2"], # Detect 层
activation_quant_method="min_max"
)
quant_model = amct.quantize_model(model, config)
四、BERT-base:Embedding 层不能量化
BERT 的 Embedding 层(Token + Position + Segment)是查找表结构,量化之后精度损失严重——查找表的索引是离散的,量化会改变索引的相对位置。
精度对比
| 精度策略 | MNLI 准确率 | 相对 FP32 损失 | 推理速度 |
|---|---|---|---|
| FP32 | 84.6% | - | 95ms |
| FP16 | 84.5% | -0.1% | 62ms |
| INT8(全量化) | 81.2% | -3.4% | 38ms |
| INT8(跳过 Embedding) | 84.1% | -0.5% | 42ms |
| INT8(跳过 Embedding + 首尾层) | 84.3% | -0.3% | 44ms |
全量化 INT8,MNLI 准确率掉了 3.4 个点——不可接受。跳过 Embedding 层之后,损失降到 0.5%。再跳过首尾 Transformer 层,损失降到 0.3%。
逐层量化误差分析
用 AMCT 的逐层分析工具,统计每层的余弦相似度:
amct analyze --model=bert_base.onnx --calibration_data=500
结果:Embedding 层的余弦相似度只有 0.87(远低于其他层的 0.98+),是量化误差的主要来源。中间 Transformer 层的相似度都在 0.96 以上,量化安全。
BERT 的建议:Embedding 层保留 FP16,中间 Transformer 层量化 INT8,首尾层看情况跳过。
五、三个模型的量化策略总结
| 模型 | 推荐策略 | 精度损失 | 速度提升 | 显存节省 |
|---|---|---|---|---|
| ResNet50 | 全量化 INT8 | -0.32% | 2.4x | 74% |
| YOLOv5 | 骨干 INT8 + 检测头 FP16 | -0.6% | 2.1x | 55% |
| BERT-base | Transformer INT8 + Embedding FP16 | -0.5% | 2.3x | 60% |
三个模型有一个共同规律:网络两端(输入侧和输出侧)的层对量化更敏感。输入侧的层(Embedding、第一层卷积)处理的是原始数据,动态范围大;输出侧的层(全连接、检测头)处理的是精细特征,量化容易丢信息。中间层反而是最安全的量化区域。
参考资源
- AMCT 量化工具文档:https://www.hiascend.com/document/detail/zh/CANN/
- 量化最佳实践:https://www.hiascend.com/document/detail/zh/CANN/
- 昇腾模型量化样例:https://atomgit.com/cann/models
总结
量化的核心不是「转 INT8」,而是「哪些层能转、哪些不能」。ResNet50 几乎可以全量化,YOLOv5 要保护检测头,BERT 要保护 Embedding 层。校准集 500 条够用,不需要太多。混合精度量化的精度损失能控制在 0.5% 以内,速度提升 2 倍以上。拿到一个新模型,先跑逐层分析,再决定哪些层量化、哪些跳过,比无脑全量化靠谱得多。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)