You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch导出GoogLeNet为ONNX后推理结果不一致如何解决

问题根因

两端结果不一致核心是预处理、后处理逻辑不对等导致的,和ONNX导出本身关联不大,具体错点如下:

  • 图像缩放裁剪逻辑不一致:PyTorch端逻辑是先将图像短边等比例缩放到256像素,再从中心裁剪224×224的区域,不会拉伸图像;ONNX端直接将原图强制resize到224×224,会导致图像变形,输入内容本身就存在偏差。
  • 归一化逻辑完全不匹配:PyTorch端transforms.ToTensor()会先把0-255范围的像素值缩放到0-1区间,再执行(像素值 - 均值)/标准差的归一化,使用的是RGB通道顺序的均值和标准差;你之前观察到的“均值除以256近似”只是数值巧合,ONNX端用的是Caffe风格的预处理,像素值保持0-255范围,只做了减均值操作,完全没有除以标准差的步骤,输入数值差了两个量级,结果必然偏差。
  • 通道顺序错误:PyTorch版GoogLeNet训练时输入是RGB通道顺序,ONNX端预处理最后一步把RGB转成了BGR,通道顺序颠倒,输入的颜色信息完全错误。
  • 后处理缺失:PyTorch端对模型输出的原始logits做了softmax运算,得到0-1区间的置信度;ONNX端直接拿原始logits排序计算,没有做softmax,置信度数值和PyTorch端没有可比性。
修复方案

第一步:确认ONNX导出环节无问题

导出前确保模型处于eval()模式(你现有代码已经满足要求),如果担心opset兼容性,可以把opset版本升到13以上(10之后的版本对GoogLeNet的算子支持更完善),导出代码不需要做其他大改。

第二步:替换ONNX端预处理逻辑,和PyTorch端严格对齐

把原有preprocess函数替换为以下实现,1:1复刻PyTorch的transforms处理逻辑:

def preprocess(img_path):
    # 读取图像并转为RGB格式
    img = Image.open(img_path).convert('RGB')
    # 等比例缩放,短边对齐256像素
    w, h = img.size
    if h < w:
        new_h = 256
        new_w = int(256 * w / h)
    else:
        new_w = 256
        new_h = int(256 * h / w)
    img = img.resize((new_w, new_h), Image.BILINEAR)
    # 中心裁剪224x224区域
    left = (new_w - 224)/2
    top = (new_h - 224)/2
    right = left + 224
    bottom = top + 224
    img = img.crop((left, top, right, bottom))
    # 转为numpy数组,将像素值缩放到0-1区间
    img = np.array(img).astype(np.float32) / 255.0
    # 按PyTorch所用的均值、标准差做归一化,保持RGB通道顺序
    mean = np.array([0.485, 0.456, 0.406]).reshape(1,1,3)
    std = np.array([0.229, 0.224, 0.225]).reshape(1,1,3)
    img = (img - mean) / std
    # 转为CHW维度格式,添加batch维度
    img = img.transpose(2,0,1)
    img = np.expand_dims(img, axis=0)
    return img

第三步:补全后处理逻辑

拿到ONNX模型输出后,先做softmax得到置信度,再取Top5结果,和PyTorch端逻辑完全对齐:

def softmax(x, axis=1):
    e_x = np.exp(x - np.max(x, axis=axis, keepdims=True))
    return e_x / e_x.sum(axis=axis, keepdims=True)

def predict(path):
    img_batch = preprocess(path)
    outputs = ort_session.run(None, {"input": img_batch.astype(np.float32)})
    # 对模型原始输出做softmax得到概率值
    probs = softmax(outputs[0], axis=1)[0]
    # 取置信度最高的5个结果
    top5_idx = np.argsort(-probs)[:5]
    results = {}
    for i in top5_idx:
        results[labels[i]] = float(probs[i])
    return results

修改完成后两端推理结果的Top5类别和置信度会基本完全一致,仅存在不同框架浮点计算带来的极小数值误差,不会出现结果偏差较大的问题。

内容的提问来源于stack exchange,提问作者Luis Ramon Ramirez Rodriguez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 18:03:30