YOLOv8 → NCNN Int8:完整量化流程与校准数据指南
1. 整体流程概览
- YOLOv8
.pt-> 导出为 ONNX - ONNX -> ncnn(FP32):
onnx2ncnn - 准备校准图片列表
calibration.txt - 使用
ncnn2table生成量化表(.table) - 使用
ncnn2int8生成 int8 模型(.param+.bin) - 在验证集上比较 FP32 vs INT8 的精度与推理速度
2. 前提环境
- 已训练好的 YOLOv8 模型(
.pt)。 - 已安装 ultralytics、onnxruntime(用于验证)、ncnn 工具链(含 onnx2ncnn、ncnn2table、ncnn2int8)。
- 推荐 ncnn 版本 >= 2021(支持完整的 int8 流程)。
3. 从 YOLOv8 导出到 ONNX
# 示例:导出到 onnx(opset=12)
yolo export model=yolov8n.pt format=onnx opset=12 dynamic=False simplify=True
导出的文件:yolov8n.onnx。
4. ONNX → NCNN(FP32)
使用 ncnn 的 onnx2ncnn:
./onnx2ncnn yolov8n.onnx yolov8n.param yolov8n.bin
或者pnnx
pnnx yolov8n.onnx


得到 yolov8n.param 和 yolov8n.bin。
5. 校准数据(calibration)详解
5.1. 核心结论(先看要点)
- 校准数据对 PTQ(post-training int8)至关重要,它决定了各层量化尺度(scale/zero point),直接影响精度。
- 校准图片不需要标签 — 只要与真实推理时的输入分布一致即可。
- 如果校准集不具代表性,量化后模型在某些场景(尤其小目标或稀有场景)上会发生明显精度下降。
5.2. 为什么需要校准数据?
量化需要把浮点激活/权重映射到有限整数表示(如 int8)。校准阶段用代表性图片做一次前向,统计每层激活分布(min/max/直方图),再据此计算量化 scale / zero-point。校准集的分布会直接影响这些统计。
5.3. 校准图可否没有目标?
可以。少量无目标图片没问题。但若校准集系统性地没有你关心的目标场景(例如你要检测远处小车,但校准集全是室内人像),量化尺度不会为这些重要激活做优化,性能会下降。
5.4. 推荐策略(实践建议)
- 数量:通常使用 100–500 张,100 张对大多数情况有效,更多更稳健。
- 多样性:覆盖不同分辨率、光照(白天/夜间)、背景复杂度、目标远近等。
- 方法选择:ncnn 的
ncnn2table支持不同方法(kl、minmax等)。推荐使用method=kl(对 outlier 更鲁棒)。 - 没有真实图片时:尽量用训练/验证集中的原图,无需标签;或从公共数据集中抽样(如 COCO)。
- 替代方案:若可重新训练,量化感知训练(QAT)通常比 PTQ 更稳健。
6. 用 ncnn 工具进行 PTQ(示例)
6.1. 生成 calibration.txt
将代表性图片路径写到 calibration.txt(每行一个绝对或相对路径):
find ./images -name "*.jpg" > calibration.txt
# Windows PowerShell 示例:
# Get-ChildItem -Path images -Filter *.jpg -Recurse | ForEach-Object { $_.FullName } > calibration.txt
6.2. 生成量化表:ncnn2table
# 使用ncnn2table生成量化表
ncnn2table yolov8n.param yolov8n.bin imagelist.txt yolov8n.table mean=[123.675,116.28,103.53] norm=[0.017125,0.017507,0.017429] shape=[640,640,3] pixel=BGR thread=4 method=kl
或者
./ncnn2table yolov8n.param yolov8n.bin calibration.txt yolov8n.table \
mean=[0,0,0] norm=[0.0039215686,0.0039215686,0.0039215686] \
shape=[1,3,640,640] pixel=BGR thread=4 method=kl
说明:
mean与norm应与模型导出时的预处理一致(YOLO 常用 0~1,norm=1/255)。pixel=BGR表示输入是 BGR(OpenCV 默认)。shape是[1,3,H,W]或[H,W,3](ncnn 有时接受不同顺序,按你版本文档填)。method=kl推荐。


6.3. 生成 int8 模型:ncnn2int8
量化命令
ncnn2int8 yolov8n.param yolov8n.bin yolov8n_int8.param yolov8n_int8.bin yolov8n.table
输出:yolov8n-int8.param、yolov8n-int8.bin。


7. 验证与对比建议
- 在同一验证集上分别运行 FP32(ncnn fp32)与 INT8(ncnn int8),比较 mAP / precision / recall。
- 特别关注:小目标、低置信预测、弱对比或极端亮暗场景。
- 可视化若干典型图片,人工检查 FP32 与 INT8 的输出差异。
8. COCO 作为校准集:何时使用与注意事项
官方 YOLOv8 预训练没有提供专门的校准集。如果你只是想量化预训练模型用于 benchmark,COCO val2017(约 5k 张)是常见选择:
- 抽样 100–500 张 COCO val 做校准通常就够。
- 用全部 5k 张可行,但计算成本高且边际收益递减——100–500 张通常性价比最好。
- 如果目标部署场景与 COCO 差异大(例如红外、工业相机或特定视角),优先使用真实部署截图。
实践建议:
- 抽样时做分层抽样(保证不同目标大小、场景都被覆盖),而非完全随机。
- 若使用全部 COCO,务必用
method=kl避免 minmax 被 outlier 拉大范围。
9. 实用脚本:COCO 分层采样(生成 calibration.txt)
下面提供一个便于生成 calibration.txt 的脚本 coco_calibration_sampler.py,它:
- 尝试为每个类别至少采样一张图;
- 每类最多采
--per_category张; - 去重、优先选择覆盖多类别的图片;
- 支持 pycocotools 或直接解析 json。
说明:脚本适用于你想从 COCO 风格的标注中智能抽样 calibration 集合的场景。
#!/usr/bin/env python3
"""
#!/usr/bin/env python3
"""
coco_calibration_sampler.py
Purpose:
Build a representative calibration.txt for ncnn int8 quantization from COCO-style annotations
while trying to cover all categories (or as many as possible


235

被折叠的 条评论
为什么被折叠?



