1. PyTorch模型转换为ONNX格式
任务说明
本案例将一个训练好的PyTorch图像分类模型(ResNet18)转换为ONNX格式,并通过对比转换前后模型在相同输入下的输出,验证转换一致性。转换后的ONNX文件将作为后续量化、推理部署的基础。
环境依赖
需要安装:torch、torchvision、onnx、onnxruntime。建议使用Python 3.8+。
完整实现代码
import torch
import torchvision.models as models
import onnx
import onnxruntime as ort
import numpy as np
# 1. 加载预训练模型并设为评估模式
model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)
model.eval()
# 2. 构造示例输入(1个batch,3通道,224x224)
dummy_input = torch.randn(1, 3, 224, 224)
# 3. 导出为ONNX格式
onnx_path = "resnet18.onnx"
torch.onnx.export(
model, # 待转换模型
dummy_input, # 示例输入
onnx_path, # 输出文件路径
export_params=True, # 保存模型权重
opset_version=13, # ONNX算子集版本
input_names=["input"], # 输入节点名
output_names=["output"], # 输出节点名
dynamic_axes={ # 动态batch维度
"input": {0: "batch_size"},
"output": {0: "batch_size"}
}
)
print(f"ONNX模型已保存至: {onnx_path}")
# 4. 验证ONNX模型结构完整性
onnx_model = onnx.load(onnx_path)
onnx.checker.check_model(onnx_model)
print("ONNX模型结构检查通过")
# 5. 使用ONNX Runtime进行推理,对比输出一致性
# 准备相同输入
test_input = torch.randn(1, 3, 224, 224)
# PyTorch模型推理
with torch.no_grad():
torch_output = model(test_input).numpy()
# ONNX Runtime推理
ort_session = ort.InferenceSession(onnx_path)
ort_input = {ort_session.get_inputs()[0].name: test_input.numpy()}
ort_output = ort_session.run(None, ort_input)[0]
# 6. 计算最大误差
max_diff = np.max(np.abs(torch_output - ort_output))
print(f"PyTorch与ONNX输出最大误差: {max_diff:.6e}")
# 7. 验证通过条件:误差小于1e-4
assert max_diff < 1e-4, "输出一致性验证失败"
print("输出一致性验证通过")
运行方式
将上述代码保存为 convert_onnx.py,在终端执行:
python convert_onnx.py
验证方法与判定标准
- 结构验证:程序执行到“ONNX模型结构检查通过”且无异常,说明ONNX文件格式正确。
- 一致性验证:程序输出“输出一致性验证通过”,且最大误差小于
1e-4,即认为转换成功。 - 预期输出示例(数值因随机输入而异):
ONNX模型已保存至: resnet18.onnx
ONNX模型结构检查通过
PyTorch与ONNX输出最大误差: 2.384186e-07
输出一致性验证通过
常见问题
- 算子不支持:若导出时报算子不支持错误,可尝试降低
opset_version(如改为11)。 - 动态维度失效:若后续推理需要固定batch,可移除
dynamic_axes参数。 - 误差过大:检查模型是否处于
eval()模式,且输入预处理方式与训练时一致。