使用onnx2pytorch转换ONNX模型至PyTorch后预测结果差异过大求助
ONNX转PyTorch模型后瞳孔识别预测结果差异问题
我有一个训练完成、表现出色的眼部图像瞳孔识别ONNX模型,想将其转为PyTorch模型使用,于是用onnx2pytorch库的ConvertModel函数进行转换,代码如下:
from onnx2pytorch import ConvertModel onnx_model = onnx.load("onnx_model.onnx") pytorch_model = ConvertModel(onnx_model)
之后我用同一张输入图像分别运行两个模型,预处理及推理代码如下:
# 加载输入图像并做预处理 img = cv2.cvtColor(cv2.imread("images/eye_frame_00494.png"), cv2.COLOR_BGR2GRAY) img = cv2.resize(img, (320, 240), interpolation=cv2.INTER_LINEAR) clahe = cv2.createCLAHE(clipLimit=2) img = clahe.apply(img) img2 = img.reshape(1, 240, 320, 1) img2 = img2 / 255 test_img_input = np.zeros((1, 240, 320, 3), dtype=np.float32) test_img_input[:, :, :, :] = img2 # 转为PyTorch张量 input_img = torch.tensor(test_img_input) # 预测 result = session.run([output_name], {input_name: test_img_input}) # 上方有代码已正确定义output_name和input_name output = pytorch_model(input_img)
但绘制关注通道的结果时,两个模型的预测存在明显差异(如图所示)。我测试了多张图像,差异时大时小,希望有人帮忙解释差异来源及修正或降低差异的方法。

差异可能的来源
- 维度顺序不匹配:ONNX常用
(N, H, W, C)的张量维度顺序,而PyTorch默认是(N, C, H, W),输入维度不一致会导致模型推理逻辑错位。 - 算子转换兼容性问题:onnx2pytorch对部分ONNX算子的实现细节和原模型存在差异,比如池化层的边界处理、激活函数的数值精度,或者自定义算子未被正确转换。
- 模型运行模式不一致:PyTorch模型默认处于训练模式,Dropout、BatchNorm等层的行为和ONNX的推理模式不同,会导致输出偏差。
- 权重精度损失:转换过程中可能出现权重参数的精度丢失,比如浮点数类型转换时的微小误差,累积后导致结果差异。
修正/降低差异的方法
- 调整输入张量维度顺序:将PyTorch输入从
(N, H, W, C)转为(N, C, H, W),修改代码如下:input_img = torch.tensor(test_img_input).permute(0, 3, 1, 2) - 切换PyTorch到评估模式:推理前强制模型进入评估状态,避免训练层干扰:
pytorch_model.eval() - 验证权重一致性:提取ONNX模型的权重,和转换后的PyTorch模型权重逐一比对,排查是否存在明显偏差。可以用
onnx.numpy_helper提取ONNX权重,再对比PyTorch的state_dict()。 - 替换转换工具:如果onnx2pytorch效果不佳,可尝试其他方式,比如手动复现模型结构后直接加载ONNX权重,或逐层对比ONNX Runtime和PyTorch的输出定位问题。
- 严格对齐预处理流程:确保两个模型的输入预处理完全一致,包括数据类型、归一化数值、插值方式等,避免预处理阶段引入差异。
- 算子级定位问题:逐层对比ONNX和PyTorch模型的输出,找到差异出现的第一层,针对性修复该算子的转换逻辑或替换为PyTorch原生实现。
内容的提问来源于stack exchange,提问作者G_FAVE
相关产品推荐
相关产品推荐

