Skip to main content
Version: Current

第二部分:实践篇

3. 快速入门:YOLOv11s 模型转换

本章以 YOLOv11s 模型为例,通过一个完整的端到端示例,带您体验使用 taNNTC 工具链完成模型导入、量化与导出的全过程。

3.1 前期准备

3.2 组织目录结构

在进行模型编译与量化前,建议按如下目录组织文件,便于工具链调用与管理:

project_yolo11s/
├── val2017_1000/ # 量化校准数据集
│ ├── 0000000000.jpg
│ ├── 0000000001.jpg
│ ├── 0000000002.jpg
│ └── ...
├── dataset.txt # 量化数据集列表文件
├── inputs_outputs.txt # 模型输入/输出节点配置文件(可选)
├── yolo11s.onnx # 源 ONNX 模型文件
├── generate_nbg_u8.sh # uint8 量化脚本
├── generate_nbg_float16.sh # fp16 量化脚本
└── export_nbg_unify/ # 编译输出目录(执行完成后生成)

说明:taNNTC 支持通过文本配置文件指定模型的输入和输出节点。如果不进行配置,系统将自动识别模型的 I/O 节点(适用于默认全模型量化)。以 YOLOv11s 为例:

  • 输入节点

    • images
  • 输出节点

    • /model.23/Reshape_output_0
    • /model.23/Reshape_1_output_0
    • /model.23/Reshape_2_output_0

输出说明

YOLO11 的三个输出对应三个不同尺度的特征图(stride = 8、16、32)。 每个预测点都会输出一个 144 维向量,其中包含边界框和分类信息。

  • 144 维向量的组成
    • 前 64 维:边界框回归信息(采用 DFL 分布形式,对 xywh 各 16 个 bin 编码)。
    • 后 80 维:类别置信度(每个通道对应一个类别,已融合 objectness 概念)。
  • 第三维度(6400 / 1600 / 400):表示该尺度下的网格点数
    • [1,144,6400] → 对应 80×80 特征图(小目标)
    • [1,144,1600] → 对应 40×40 特征图(中目标)
    • [1,144,400] → 对应 20×20 特征图(大目标)

量化数据集:工具链支持以文本格式指定量化数据集路径文件(dataset.txt),文件格式如下:

val2017_1000/0000000000.jpg
val2017_1000/0000000001.jpg
val2017_1000/0000000002.jpg
...
  • 每行对应一张图片的相对路径或绝对路径。
  • 建议数据集涵盖多种场景、光照和角度,以提升量化精度。
  • 数据集规模通常建议在 100~1000 张之间,根据模型大小和精度需求调整。

下载的 quantize_scripts 目录下包含一个示例配置文件 dataset.txt,可以直接使用。

3.3 模型编译与量化

进入 project_yolo11s/ 目录,执行示例脚本来生成可在 EA65 系列 NPU 上运行的 .nb 格式模型。

  1. 生成 FP16 模型
./generate_nbg_float16.sh
  1. 生成 uint8 模型
./generate_nbg_u8.sh

执行成功后,最终用于板端部署的文件将位于 export_nbg_unify/ 目录下,名为 network_binary.nb

3.4 脚本解析:从示例到实践

我们提供的 generate_nbg_float16.shgenerate_nbg_u8.sh 脚本是实现模型一键式编译与量化的便捷工具。为了帮助您更好地理解其工作原理,并能根据自身需求进行灵活修改,本节将对 generate_nbg_float16.sh 的核心命令进行分步解析。

因此,您可以将此脚本视为一个最佳实践模板。脚本中的每一条 pegasus 命令都由一系列参数构成,这些参数的具体含义和更多用法,均可在 「TacoAI NN 工具链技术手册」文档的「pegasus 命令参数详解」章节 中查阅。

generate_nbg_float16.sh 的核心流程主要分为三个阶段:模型导入模型量化模型导出

阶段一:模型导入 (Import)

将 ONNX 模型转换为 taNNTC 的中间表示 (IR)。

# 脚本中的命令
cmd="$PEGASUS import onnx
--model yolo11s.onnx \
--output-model yolo11s.json \
--output-data yolo11s.data \
${clean_params}" # clean_params 从 inputs_outputs.txt 读取输入输出节点信息
  • 关键参数说明
    • import onnx:指定当前执行的是 "ONNX 模型导入" 任务。
    • --model:指定输入的源 ONNX 模型文件。
    • --output-model / --output-data:定义转换后输出的 .json.data 文件。
    • ${clean_params}:此变量从 inputs_outputs.txt 文件中读取并传入模型的输入和输出节点名。

阶段二:生成配置文件 (Generate)

此步骤基于导入后的模型结构,生成预处理和后处理的 .yml 配置文件模板。

# 1. 生成输入端预处理配置
cmd="$PEGASUS generate inputmeta \
--model yolo11s.json \
--input-meta-output yolo11s_inputmeta.yml"
eval $cmd

# 2. 生成输出端后处理配置
cmd="$PEGASUS generate postprocess-file \
--model yolo11s.json \
--postprocess-file-output yolo11s_postprocess_file.yml"
eval $cmd

说明:此时生成的 .yml 文件包含默认参数,需要根据模型需求进行修改。

针对 YOLOv11s 这个模型来说,完成了两个关键修改:

function modify_yml()
{
# 将 reverse_channel 从 true 修改为 false
sed -i 's/^\( *reverse_channel:\) true$/\1 false/' yolo11s_inputmeta.yml
# 将 scale 值从 1.0 修改为 1/255 (0.003921569)
sed -i '/scale:/ {n; s/1.0/0.003921569/; ...}' yolo11s_inputmeta.yml
}
modify_yml
  1. 关闭通道反转:因为 YOLOv11s 模型训练时使用的就是 RGB 格式的输入。
  2. 设置归一化系数:将输入图像的像素值从 [0, 255] 范围归一化到 [0, 1] 范围。

对于您自己的模型,您需要根据实际的预处理逻辑,手动或通过脚本修改这一部分。

阶段三:模型量化 (Quantize)

利用校准数据集生成量化参数。

cmd="$PEGASUS quantize \
--model yolo11s.json \
--model-data yolo11s.data \
--batch-size 1 \
--device CPU \
--with-input-meta yolo11s_inputmeta.yml \
--rebuild \
--compute-entropy \
--iterations 5 \
--model-quantize yolo11s_float16.quantize \
--quantizer float16 \
--qtype float16 "
  • 命令解析
    • --model / --model-data:指定上一阶段生成的 .json.data 文件。
    • --quantizer / --qtype:定义量化的核心方案与目标数据类型(例如 asymmetric_affine + uint8)。
    • --with-input-meta:指定包含预处理信息和校准数据集路径的 .yml 配置文件。
    • --model-quantize:指定输出的量化结果文件 (.quantize),该文件记录了所有量化参数。

阶段四:模型导出 (Export)

最后一步,将量化后的模型编译并打包成 NPU 可直接加载执行的二进制文件 (.nb)。

cmd="$PEGASUS export ovxlib \
--model yolo11s.json \
--model-data yolo11s.data \
--dtype quantized \
--model-quantize yolo11s_float16.quantize \
--target-ide-project 'linux64' \
--with-input-meta yolo11s_inputmeta.yml \
--postprocess-file yolo11s_postprocess_file.yml \
--output-path export/yolo11s_float16 \
--pack-nbg-unify \
--viv-sdk '/usr/src/Unified_Driver/cmdtools' \
--optimize VIP9200O_PID0X10000049"
  • 命令解析
    • export ovxlib:指定将模型导出为 OpenVX 库/应用。
    • --model-quantize:指定上一步生成的量化参数文件,这是执行量化导出的关键。
    • --dtype quantized:指明导出模型的运算精度为 "量化模式",工具会依据 .quantize 文件进行编译。如果想导出 FP16 模型,此处应设为 float16
    • --output-path:指定导出文件的生成目录。
    • --pack-nbg-unify核心参数,指示工具将所有必需的组件打包成一个单一的、统一格式的二进制图文件 (.nb)。
    • --viv-sdk--optimize:指定与目标硬件(EA65 系列 NPU)相关的编译工具路径和优化配置。
  • 说明:依据本次脚本导出来的模型为单 core 模型。

通过以上解析,可以看到,一个完整的模型部署流程是如何通过组合 pegasus 的不同命令和参数来实现。当需要处理自己的模型时,可以以此脚本为基础,参考 「TacoAI NN 工具链技术手册」文档的「第三部分:参数篇」章节 的内容,调整各项参数,以满足特定需求。


4. 高级专题:混合量化(Hybrid Quantization)

4.1 概述与原理

混合量化是一种在精度和性能之间取得更优平衡的策略。其核心思想是:对模型中大部分层使用 INT8/UINT8 高性能定点量化,同时对少数对精度非常敏感的层保留 FP16 半精度浮点计算,从而在保持高精度的同时获得显著的性能提升。

  • INT8 量化:将权重和激活映射到 8 位整数,运算效率高,模型体积小,但量化误差可能导致精度下降。
  • FP16 保留:对于量化敏感的层(如首尾卷积层、特征融合层等),直接使用 FP16 存储和计算,减少精度损失。
  • 混合调度:在推理引擎中,INT8 与 FP16 层可以混合执行,由硬件调度自动完成数据格式的转换与传递。

4.2 混合量化流程

步骤 1:搜索敏感层

通过在量化命令中加入特定参数,可以分析每一层在量化过程中的精度损失(熵值)。

pegasus quantize  \
--model yolo11s.json \
--model-data yolo11s.data \
--quantizer asymmetric_affine \
--qtype 'uint8' \
--with-input-meta yolo11s_inputmeta.yml \
--rebuild \
--compute-entropy \
--algorithm auto

--algorithm 参数设置为 auto,即启用基于 KL 散度的自动混合量化算法。此模式下工具会自动判断哪些层采用 16 位量化(默认为 DFPI16 格式)哪些层采用 8 位量化。用户无需手动列出层列表,系统将根据校准数据分布自动决定保留高精度的层。

该命令执行后,会生成模型的量化结果文件 model.quantize(记录每一层的量化参数)以及熵值文件 entropy.txt。熵值取 0~1 之间,数值越接近 1 表示该层量化精度越低,也即损失越大。

步骤 2:手动配置高精度层

根据 entropy.txt 的分析结果,打开 .quantize 配置文件(如 yolo11s_uint8.quantize),找到 customized_quantize_layers 字段,将熵值较高的敏感层(例如 > 0.6)添加进去,并指定其使用高精度格式。这里我们以 yolo11s 为例,手动配置混合量化层:

打开 yolo11s_uint8.quantize 文件,找到 customized_quantize_layers 字段,将 entropy.txt 中熵值大于 0.6 的层添加到该字段中,如:

model.23/cv3.2/cv3.2.0/cv3.2.0.1/conv/Conv_output_0_59:dynamic_fixed_point-i16
model.23/cv3.1/cv3.1.0/cv3.1.0.1/conv/Conv_output_0_63:dynamic_fixed_point-i16
model.2/m.0/cv1/conv/Conv_output_0_230:dynamic_fixed_point-i16
model.0/conv/Conv_output_0_265:dynamic_fixed_point-i16
model.23/cv3.1/cv3.1.1/cv3.1.1.0/conv/Conv_output_0_51:dynamic_fixed_point-i16
model.23/cv2.2/cv2.2.0/conv/Conv_output_0_45:dynamic_fixed_point-i16
model.23/cv2.1/cv2.1.0/conv/Conv_output_0_49:dynamic_fixed_point-i16
model.1/conv/Conv_output_0_259:dynamic_fixed_point-i16
model.23/cv3.0/cv3.0.1/cv3.0.1.0/conv/Conv_output_0_55:dynamic_fixed_point-i16
model.2/cv1/conv/Conv_output_0_247:dynamic_fixed_point-i16
model.23/cv2.0/cv2.0.2/Conv_output_0_13:dynamic_fixed_point-i16
model.23/cv2.1/cv2.1.2/Conv_output_0_11:dynamic_fixed_point-i16
model.23/cv2.0/cv2.0.1/conv/Conv_output_0_29:dynamic_fixed_point-i16
model.10/m/m.0/attn/pe/conv/Conv_output_0_176:dynamic_fixed_point-i16
model.23/cv2.2/cv2.2.2/Conv_output_0_9:dynamic_fixed_point-i16
model.23/cv2.1/cv2.1.1/conv/Conv_output_0_25:dynamic_fixed_point-i16
model.23/cv2.2/cv2.2.1/conv/Conv_output_0_21:dynamic_fixed_point-i16

步骤 3:执行混合量化并导出

首先,使用 --hybrid 标记执行量化,生成混合量化配置。

pegasus quantize  \
--model yolo11s.json \
--model-data yolo11s.data \
--quantizer asymmetric_affine \
--qtype 'uint8' \
--with-input-meta yolo11s_inputmeta.yml \
--model-quantize yolo11s_uint8.quantize \
--hybrid

这会生成一个新的 yolo11s_uint8.quantize.json 文件。然后,使用这个新文件作为 --model 参数来导出最终的混合量化模型。

pegasus export ovxlib \
--model yolo11s_uint8.quantize.json \
--model-data yolo11s.data \
--dtype quantized \
--model-quantize yolo11s_uint8.quantize \
--target-ide-project 'linux64' \
--with-input-meta yolo11s_inputmeta.yml \
--postprocess-file yolo11s_postprocess_file.yml \
--output-path export/yolo11s_hybrid \
--pack-nbg-unify \
--viv-sdk '/usr/src/Unified_Driver/cmdtools' \
--optimize VIP9200O_PID0X10000049

4.3 精度与性能分析

  • 精度测算:可根据 Model Zoo 中提供的标准方式进行精度测试,对比混合量化模型与原模型的差异。

  • 精度问题排查

  • 层级性能分析:在板端使用 vpm_run 命令执行模型时,附加 -cnnprofile_level 2 参数,即可获取每一层的详细性能分析报告。