YOLOv8 → NCNN Int8:完整量化流程与校准数据指南


1. 整体流程概览

  1. YOLOv8 .pt -> 导出为 ONNX
  2. ONNX -> ncnn(FP32):onnx2ncnn
  3. 准备校准图片列表 calibration.txt
  4. 使用 ncnn2table 生成量化表(.table
  5. 使用 ncnn2int8 生成 int8 模型(.param + .bin
  6. 在验证集上比较 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.paramyolov8n.bin


5. 校准数据(calibration)详解

5.1. 核心结论(先看要点)

  • 校准数据对 PTQ(post-training int8)至关重要,它决定了各层量化尺度(scale/zero point),直接影响精度。
  • 校准图片不需要标签 — 只要与真实推理时的输入分布一致即可。
  • 如果校准集不具代表性,量化后模型在某些场景(尤其小目标或稀有场景)上会发生明显精度下降。

5.2. 为什么需要校准数据?

量化需要把浮点激活/权重映射到有限整数表示(如 int8)。校准阶段用代表性图片做一次前向,统计每层激活分布(min/max/直方图),再据此计算量化 scale / zero-point。校准集的分布会直接影响这些统计。

5.3. 校准图可否没有目标?

可以。少量无目标图片没问题。但若校准集系统性地没有你关心的目标场景(例如你要检测远处小车,但校准集全是室内人像),量化尺度不会为这些重要激活做优化,性能会下降。

5.4. 推荐策略(实践建议)

  1. 数量:通常使用 100–500 张,100 张对大多数情况有效,更多更稳健。
  2. 多样性:覆盖不同分辨率、光照(白天/夜间)、背景复杂度、目标远近等。
  3. 方法选择:ncnn 的 ncnn2table 支持不同方法(klminmax 等)。推荐使用 method=kl(对 outlier 更鲁棒)。
  4. 没有真实图片时:尽量用训练/验证集中的原图,无需标签;或从公共数据集中抽样(如 COCO)。
  5. 替代方案:若可重新训练,量化感知训练(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

说明:

  • meannorm 应与模型导出时的预处理一致(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.paramyolov8n-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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值