最近在搞一个部署项目,把训练好的YOLOv5模型转成ONNX,用onnxruntime跑了一下,发现输出的检测框置信度整体偏低,有些原本能检出的目标直接丢了。对比了torch和onnx的输入输出,数据预处理都是一样的,也关掉了amp。查了日志,提示有些算子(比如Focus和SiLU)被拆成了多个小算子,不确定是不是这个原因。有没有大佬遇到过类似情况?是算子兼容性问题,还是转换时需要设置opset版本或者dynamic_axes?另外,用onnx-simplifier简化后会不会有改善?希望有经验的朋友指点一下,实在不想从头用TensorRT重写。
楼主
20天前
PyTorch转ONNX后推理结果和原模型差很多,是量化问题还是算子不支持?
请 登录 后发表回复
全部回复
共 64 条
2楼
1天前
遇到过类似的,Focus和SiLU被拆开一般不影响精度,但如果你用了amp训练,转ONNX时权重里可能有half精度残留,建议先确认下导出的模型权重是不是fp32。另外opset版本建议至少设到12以上,dynamic_axes最好把batch和wh维度都标上,不然推理时shape变化可能导致数值异常。onnx-simplifier可以试试,但主要作用是去掉冗余节点,对精度损失帮助有限,更可能是预处理细节(比如归一化方式或letterbox的padding值)在前后端没完全对齐。如果实在查不出来,可以逐层对比torch和onnx的中间输出,定位到第一个出现偏差的节点。
3楼
1天前
大概率是算子拆解后精度丢失,先试下opset=12+dynamic_axes,simplifier对Focus帮助不大。
4楼
1天前
八成是opset版本太低导致Focus展开时精度丢了,试试opset=12以上顺便开下dynamic_axes。
5楼
1天前
我之前也踩过这个坑,YOLOv5转ONNX后置信度掉一截大概率不是量化问题,你关了amp就排除了这个。Focus和SiLU被拆小算子确实会影响数值精度,但更常见的是opset版本太低导致某些算子走的是旧版实现,建议试试opset=12或13,同时把dynamic_axes设上。onnx-simplifier可以跑一下,主要是把那些冗余的reshape和concat合并掉,对精度恢复有点帮助,但别指望完全一致。另外你对比下torch和onnx的输出特征图,看看是哪个层开始偏差变大的,这样定位更快。