博客算法工具链【玩转 J6 算法工具链:PTQ 工具篇】用 `hb_verifier` 追踪 YOLOv5x 从浮点 ONNX 到 J6E HBM 的输出变化

【玩转 J6 算法工具链:PTQ 工具篇】用 `hb_verifier` 追踪 YOLOv5x 从浮点 ONNX 到 J6E HBM 的输出变化

金属货机2026-10-30
11
0
前面的文章已经完成 YOLOv5x 的 HBM 编译、板端推理,以及 hb_analyzer 性能分析。这次换一个问题:如果部署后的检测结果与浮点模型不同,差异从哪一个模型阶段开始出现?
OpenExplorer 的 hb_compile 不会只留下一个 HBM。它还会保存原始浮点模型、优化后的浮点模型、校准模型、PTQ 模型和量化 BC。hb_verifier 可以在这些阶段之间比较节点输出;对 BC 与 HBM,则比较模型最终输出。官方 PTQ 部署一致性指南给出了各阶段产物的含义,hb_verifier 工具手册列出了支持的模型组合与输入要求。

本文沿用同一份 YOLOv5x 编译产物,不重新量化或编译。实验依次核对浮点图优化、伪量化、定点 BC,以及 J6E 板上的 HBM。本文中的余弦相似度和一致性数字都来自实际运行日志。

1. 先分清两种比较

hb_verifier 的输出分成两类,不能混用:

模型组合

工具给出的内容

用来回答的问题

ONNX ↔ ONNX、ONNX ↔ BC

逐节点余弦相似度,包括最终输出节点

数值变化主要出现在哪个模型阶段、哪些节点附近?

定点 BC ↔ HBM

最终输出的一致性、不一致元素数量、最大绝对误差和最大相对误差

已量化模型编译并在目标环境运行后,最终输出是否与 BC 对齐?

余弦相似度接近 1 表示对应张量的方向接近,不表示所有元素相等。HBM 只支持最终输出一致性比较,不能靠这项工具直接得到 HBM 的逐层余弦表。工具手册:输出内容说明

本文的对照路径是:

这条路径省略了中间的 ptq_model.onnx。

2. 实验环境和模型接口

项目

本次实验

OpenExplorer 发布包

horizon_j6_open_explorer_v3.8.1-py310_20260326

hb_verifier

3.5.11

HBM 运行时日志中的 HBRT4

4.9.7

目标板

Horizon Robotics J6E MatrixB Development Board

编译架构

nash-e

原始图片

COCO_val2014_000000181007.jpg,原图尺寸 446×640

HBM

yolov5x_640x640_nv12.hbm

工程位于容器内:

本次比较使用同一条 hb_compile PTQ 链路中的模型文件。编译配置里,训练输入为 rgb、NCHW、1×3×640×640,运行时输入为 nv12,separate_batch: false,HBM 的 max_l2m_size 为 0。工具手册:支持范围

模型接口也有明显差别:

模型

输入名称

形状与数据类型

优化后的浮点 ONNX

images

(1, 3, 640, 640),FP32

最终 HBM

images_y

(1, 640, 640, 1),U8

最终 HBM

images_uv

(1, 320, 320, 2),U8
HBM 的三个原始检测头分别为 output、729、741,形状依次是 (1,3,80,80,85)、(1,3,40,40,85) 和 (1,3,20,20,85)。

3. 输入数据:浮点 .npy 与 NV12 双平面不能混传

ONNX 对照使用已有校准样本:

该样本由原图先做 letterbox,再做 BGR→RGB、HWC→CHW 和 /255。在本次环境中,用工程的 preprocess_one() 重新处理原图,得到的数组与现有 .npy 逐元素相等。
HBM 的运行时输入必须是 NV12 的两个 U8 平面。工程原有的 y_data.npy、uv_data.npy 虽然来自同一张图片,却使用直接拉伸到 640×640,与校准样本的 letterbox 几何处理不同。为了让本文各段实验尽量沿用同一张 letterbox 图,重新生成一组 NV12 输入,保存到独立实验目录,不覆盖工程原文件:
生成结果分别是 (1,640,640,1) uint8 和 (1,320,320,2) uint8。同源图片和同样的 letterbox 几何处理,不代表浮点 RGB 数组与 NV12 数组在数值上相同:色彩空间、色度采样和量化范围不同。本文的余弦值只比较各自命令指定的两个模型;BC↔HBM 的一致性也只针对传给它们的同一组 NV12 平面。

4. 依次运行四组分段比较

以下命令在 OpenExplorer 容器内执行。每组使用独立目录,避免 hb_verifier.log 相互覆盖。运行脚本会把标准输出保存为 run.log,并把真实进程退出码保存为 exit_code.txt。run_case 函数本身会继续执行下一组;判断工具是否正常退出时,须看各目录的 exit_code.txt。
最后一组 OPTIMIZED ↔ QBC 是跨阶段对照,不用相邻阶段的余弦相似度相乘来推算。以上命令采用同一份 FP32 .npy;这是 hb_compile 产出的 ONNX 与量化 BC 组合在官方手册中的用法。工具手册:ONNX 与 HBIR 比较示例

接着在 J6E 板上运行 HBM,与定点 BC 比较最终输出:

这里 None 对应本地运行的 BC,板卡 IP 对应 HBM;--remote-root 的两个值与模型位置一一对应。

5. 实测结果:变化从哪一段开始?

下表只摘取三个最终检测头的余弦相似度。原始日志还保存了逐节点结果,可以按节点名称继续追踪。

比较阶段

output:80×80
729:40×40
741:20×20

工具退出码

原始浮点 ONNX → 优化浮点 ONNX

1.000000

1.000000

1.000000

0

优化浮点 ONNX → 校准 ONNX

0.996401

0.995874

0.995633

0

校准 ONNX → 量化 BC

0.997702

0.997328

0.997706

139

优化浮点 ONNX → 量化 BC

0.995399

0.994687

0.994519

139

第一组的三个 1.000000 是工具按六位小数打印的结果。官方指南把“原始浮点 → 优化浮点”视为等价图优化,给出的最终输出预期是余弦相似度不低于 99.9%;本次样本满足这个预期。官方 PTQ 部署一致性指南
第二组从优化浮点模型进入校准模型,三个输出头降到约 0.996。官方文档将校准模型描述为引入伪量化行为的模型;因此,本次样本中可观察的输出差异首先出现在这一阶段。第三组进一步到定点 BC,三个头为 0.997328~0.997706。余弦相似度不是检测框召回率,也不存在“所有节点必须高于某个统一阈值”的结论。
逐节点表还提供了继续排查的入口。例如在“优化浮点 → 校准 ONNX”中,/model.20/m/m.3/cv1/act/LeakyRelu 的余弦相似度为 0.831278;在“优化浮点 → 量化 BC”中,同名节点为 0.797768。最终三个头的相似度明显高于该节点,不能只凭一个局部最小值判定模型精度不合格。
alt text
alt text

6. 定点 BC 与 J6E HBM:三个检测头均一致

使用第 3 节生成的 letterbox 后 NV12 双平面,hb_verifier 在 J6E 板上完成 HBM 推理,并打印:

输出名

工具显示的一致性

不一致元素

最大绝对误差

最大相对误差

output

True

0/1,632,000

0.0

0.0

729

True

0/408,000

0.0

0.0

741

True

0/102,000

0.0

0.0

日志原文还包含 The model output consistency comparison was successful.。这里的判断采用 hb_verifier 默认比较精度;官方文档说明默认按小数点后五位比较。表中为 0 个不一致元素,表示这一次输入在工具的比较规则下,BC 与板端 HBM 的三个最终输出一致。工具手册:--compare_digits 与一致性表
这组结果与前面的余弦表回答的问题不同:浮点到定点 BC 的输出已经产生数值差异;对本次 NV12 输入,BC 到 J6E HBM 没有在最终输出比较中观察到新的差异。因此,如果业务图片上的检测框数量或类别异常,下一步还要检查图片前处理、输出解码与 NMS,并用多图标注集验证检测指标。
alt text

7. 这次验证能够说明什么

在同一份 YOLOv5x PTQ 模型链、同一张源图片下,浮点图优化阶段的三个检测头相似度均打印为 1.000000;引入校准模型后,三个检测头出现可观察的数值变化;量化 BC 与 J6E 板端 HBM 在一次 NV12 输入上得到三个最终输出一致的比较表。hb_verifier 让“结果不同”能够按模型阶段拆开观察,而不只停留在 HBM 能否运行。

本次仅使用一张图片。本文没有计算精度、召回率或 mAP,也没有证明整个业务预处理和 YOLOv5 后处理已经对齐。需要判断量化是否满足产品指标,应继续用真实评估集跑完整检测流程;若发现掉点,再按本篇方法选取异常图片做分段、逐节点比较。

算法工具链
官方教程征程6
评论0
0/600