系列编排日期为 2026 年 8 月;技术基线核对与教学代码 CPU 验证日期为 2026-10-12。适用 Hi3516CV610 与本系列注明的 SDK/工具版本,实测范围见第 12 章。
返回系列目录 · 本篇属于 12 章与 4 份附录。
导出 ONNX 的目标是保存推理语义,并让目标工具链看到稳定的计算图。固定尺寸、改写算子、折叠常量和裁剪输出都是模型变更,需要有变更前后的数值对照。
导出前固定推理条件
设置模型为 evaluation 模式,关闭梯度,固定 batch、输入名称和输出名称,并保存原始框架的输出。Dropout、BatchNorm 或训练分支没有切到推理状态,会使导出基准本身不稳定。
对于多分支网络,要明确导出原始 head 还是解码后的结果。保留原始 head 通常更方便在 CPU 和板端之间逐张量比较,但会增加 CPU 后处理;后处理硬化可以减少部分 CPU 工作,却改变输出约定。两条路线都必须写清楚。
导出代码只作为模型专用入口
以下展示 PyTorch 导出的基本组织形式,model、输入分辨率及输出名必须来自实际模型定义:
|
这段代码采用项目旧版 PyTorch 导出思路,不能替代所有版本的模型导出脚本;多输出模型必须逐一命名。opset 11 是示例选择,依据应当是所用算子和 ATC 规格,而不是“越低越兼容”。使用新导出器时,还应记录导出器模式和是否发生回退。
静态化不能只改输入标签
把 [1,3,640,640] 改成 [1,3,320,320] 后,图中的固定 reshape、grid、anchor、位置编码和输出维度可能仍然依赖 640。可靠做法是优先从原框架以目标尺寸重新导出,再检查整图维度和实际执行。
YuNet 2023mar 的教学脚本针对已知结构固定 320 输入,同时清除旧中间 shape 注释并更新 12 个输出的维度,再执行 checker 和 ORT。这个处理仅对指定结构成立;脚本会核对输入名和输出名,不应作为通用 ONNX 改尺寸工具使用。
320 输入下 stride 8、16、32 对应的位置数为 1600、400、100。cls 和 obj 的最后一维为 1,bbox 为 4,kps 为 10。维度数量变化必须同步到后处理,不能仍遍历 640 输入的 8400 个位置。
输入缩放的等价变换
原始 YuNet 首层计算可写为:
|
实数运算下两者等价,浮点实现允许存在舍入误差。该变换使外部 UINT8 图像经 AIPP 除以 255 后,仍对应原图接收 0~255 FLOAT 的语义。首层 bias 保持不变。
成立条件包括:缩放位置与首层一致、所有受影响输入路径都被处理、没有额外重复归一化。存在其他输入分支、非线性预处理或输入被多个不同首层消费时,不能只修改碰到的第一个 Conv。教学脚本限定到该 YuNet 文件结构,并做所有输出的 CPU 比较。
简化与算子替换的验证
若使用简化工具,保留 export.onnx 与 simplified.onnx 两个文件及工具版本。先比较输出集合和 shape,再用真实图逐输出检查 MAE、最大绝对误差和解码结果。单次随机输入通过不代表边界尺寸、极暗图和饱和值都等价。
不支持的算子优先从导出配置和等价图变换解决。例如将能离线计算的常量移出运行时、固定可以确定的 shape,或在有证明的条件下替换成已支持表达。把不认识的节点直接删除通常会改变计算语义。
本阶段交付
保留原始权重、导出脚本、导出模型、每次改图后的模型、CPU 基准、改动说明和误差报告。文件名能描述用途即可,真正的身份由哈希确定。ATC 编译使用哪一个文件,应在命令和 manifest 中明确,避免调试的模型与实际转换的模型不是同一份。
