【玩转 J6 算法工具链:PTQ 工具篇】hb_verifier
在模型部署过程中,我们经常会遇到这样的问题:
浮点模型结果正常,但经过模型优化、量化或者编译之后,模型输出开始出现差异,这个差异到底是在哪个阶段引入的?
如果只对比原始 ONNX 和最终 HBM,虽然可以知道最终结果“不一致”,但很难进一步判断问题来自模型优化、PTQ 量化,还是 BC 到 HBM 的编译过程。
一、hb_verifier 是什么
J6 PTQ 模型转换过程中会产生多个阶段的模型,例如:
目前主要支持两类比较方式:
1. 余弦相似度比较
主要用于:
ONNX vs ONNX
ONNX vs HBIR(BC)
HBIR vs HBIR
余弦相似度越接近 1,说明两个 Tensor 的结果越接近。
例如:
因此,它很适合用于观察:
模型从哪个阶段、哪个节点开始产生比较明显的数值变化。
2. 输出一致性比较
对于:
Quantized BC vs HBM
HBM vs HBM
主要关注的是模型最终输出是否一致。
输出类似:
其中:
- Consistency:输出是否一致;
- Mismatched Elements:不一致元素数量;
- Max Abs Diff:最大绝对误差;
- Max Rel Diff:最大相对误差。
因此,可以简单理解为:
二、hb_verifier 怎么用
当前工具支持 ONNX、BC 和 HBM 等模型格式。
常用参数
参数 | 作用 | 说明 |
|---|---|---|
-m, --model | 指定待比较模型 | 支持 .onnx、.bc、.hbm,两个模型使用英文逗号分隔 |
-i, --input | 指定输入数据 | 输入为 .npy;多输入模型可使用逗号分隔多个输入 |
-c, --compare_digits | 设置比较精度 | 指定比较到小数点后多少位,默认 5 位 |
--ip | 指定开发板 IP | HBM 可以指定在真实开发板运行;None 表示使用本地模拟环境 |
-u, --username | 开发板用户名 | 默认 root |
-p, --password | 开发板密码 | 无密码时不需要配置 |
--port | SSH 端口 | 默认 22 |
--version | 查看版本 | 显示当前 hb_verifier 版本 |
-h, --help | 查看帮助 | 建议实际使用时结合当前 OE 版本查看 |
参数定义及模型输入方式可参考工具文档。
输入数据怎么传
单输入模型最简单:
对于多输入模型,可以按照模型输入顺序:
也可以显式指定输入名称:
例如原始 ONNX 使用的是模型训练侧输入,而 Quantized BC 已经插入了预处理或者 Layout 转换,这时候两边所需要的数据可能并不相同。
需要特别注意:
hb_verifier 使用的输入数据必须和对应模型实际输入要求一致,包括 input name、shape、dtype、layout 以及前处理方式。
下面看几种最常见的用法。
1. ONNX vs ONNX
ONNX 之间主要用于比较模型转换过程中不同 ONNX 阶段的一致性。
例如比较:
命令:
工具会对两个模型对应节点的输出计算余弦相似度。
这种方式比较适合观察:
Calibration / Fake Quantization 引入之后,各层数值发生了多大变化。
2. ONNX vs BC
这也是 PTQ 精度分析中非常常用的一种方式。
例如比较优化后的浮点模型和最终定点 BC:
这种比较非常适合用来观察:
从浮点模型进入最终定点计算以后,量化带来了多大的数值变化。
3. BC vs BC
如果模型转换是通过 PTQ API 或者其它方式进行的,也可能需要直接比较两个 HBIR 模型。
例如:
可以执行:
这种方式比较适合 PTQ API 或者模型修改场景。
例如修改了:
输入预处理;
Quantization Config;
部分节点计算精度;
HBIR 图结构;
都可以通过 BC vs BC 检查修改前后的模型是否出现了非预期的数值变化。
4. BC vs HBM
这是我认为实际部署中非常值得使用的一种方式。
PTQ 编译完成之后通常会得到:
其中:
这一步理论上不应该引入额外的数值不一致,因此可以使用:
检查两者最终输出。
如果希望 HBM 在真实 J6 板端执行,可以指定开发板 IP,例如:
其中:
表示本地模型不使用开发板,
使用提醒
如果 HBM 推理时不指定开发板 IP,工具会在本地环境通过 BPU 仿真环境执行 HBM 推理。
本地仿真主要适合快速功能验证,在实际使用中部分环境或版本下可能出现结果波动。因此在做最终模型一致性确认时,更建议指定真实 J6 开发板 IP,让 HBM 在真实板端执行推理,再与 Quantized BC 进行比较。
5. HBM vs HBM
一个比较实用的用法就是:
比较同一个 HBM 在本地模拟环境和真实开发板上的输出。
例如:
此时:
然后比较两种执行环境下的最终模型输出。
这种方式非常适合排查:
当前异常究竟来自模型本身,还是 Runtime / 实际执行环境。
三、一个完整的使用例子
最后看一个实际项目中比较常见的场景。
模型部署到 J6 后,发现最终结果和预期存在差异。
这时没必要一开始就直接怀疑 HBM。
首先检查优化前后:
然后检查 Calibration 引入后的变化:
这一阶段已经开始模拟量化行为,因此允许产生一定的量化误差。
如果这里已经出现明显的相似度下降,那么问题更可能集中在:
而不是最终 HBM 编译。
接下来还可以比较:
进一步观察浮点模型到定点模型之间的逐节点数值变化。
最后再验证 Quantized BC 与最终 HBM:
如果结果显示:
那么可以认为:
Quantized BC 编译为 HBM 的过程中没有引入额外的输出一致性问题。
这样原本一个比较模糊的问题:
就可以逐步拆成:
给两个模型、准备好对应输入,然后通过余弦相似度或最终输出一致性比较,验证 J6 模型转换链路中不同阶段的计算结果是否符合预期。
参考资料
本文部分内容参考地平线官方文档: