1. 基于ResNet18的钢材表面缺陷分类模型移植
任务目标
将训练好的ResNet18钢材表面缺陷分类模型(PyTorch训练)移植到ONNX Runtime环境进行推理部署,实现单张图像的缺陷类别预测,并验证移植前后模型输出的一致性。
环境与依赖
- Python 3.8+,安装:
torch、torchvision、onnx、onnxruntime、numpy、Pillow - 预训练权重:使用torchvision自带的ResNet18预训练权重(非钢材数据微调),演示完整移植流程
核心实现
以下代码完成:模型定义与权重加载 → 导出ONNX → ONNX Runtime加载推理 → 输出一致性比对。使用一张随机生成的模拟图像作为输入,避免外部数据依赖。
import torch
import torchvision.models as models
import torch.onnx
import onnxruntime as ort
import numpy as np
from PIL import Image
# 1. 定义模型并加载预训练权重(此处用ImageNet权重演示流程)
model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)
model.eval()
# 2. 构造模拟输入(3x224x224,归一化到[0,1])
dummy_input = torch.rand(1, 3, 224, 224)
# 3. 导出ONNX
onnx_path = "resnet18_steel.onnx"
torch.onnx.export(
model, dummy_input, onnx_path,
input_names=["input"], output_names=["output"],
opset_version=17,
dynamic_axes={"input": {0: "batch"}, "output": {0: "batch"}}
)
# 4. ONNX Runtime推理
ort_session = ort.InferenceSession(onnx_path, providers=["CPUExecutionProvider"])
ort_input = {ort_session.get_inputs()[0].name: dummy_input.numpy()}
ort_output = ort_session.run(None, ort_input)[0]
# 5. PyTorch推理(用于一致性比对)
with torch.no_grad():
torch_output = model(dummy_input).numpy()
# 6. 验证:比较输出差异
max_diff = np.max(np.abs(ort_output - torch_output))
print(f"ONNX与PyTorch输出最大误差: {max_diff:.6f}")
# 7. 模拟单张图像推理(实际使用时替换为真实图像路径)
def predict_image(image_path):
img = Image.open(image_path).convert("RGB").resize((224, 224))
img_array = np.array(img).astype(np.float32) / 255.0
img_tensor = torch.from_numpy(img_array).permute(2, 0, 1).unsqueeze(0)
# 使用ImageNet标准化参数
mean = torch.tensor([0.485, 0.456, 0.406]).view(1, 3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(1, 3, 1, 1)
img_tensor = (img_tensor - mean) / std
ort_input = {ort_session.get_inputs()[0].name: img_tensor.numpy()}
result = ort_session.run(None, ort_input)[0]
pred_class = int(np.argmax(result[0]))
return pred_class, result[0]
# 示例:使用随机噪声图验证推理流程可运行
sample_img = Image.fromarray(np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8))
sample_img.save("sample_test.png")
pred, scores = predict_image("sample_test.png")
print(f"预测类别索引: {pred}, 置信度分数shape: {scores.shape}")
运行与验证
- 将上述代码保存为
migrate_resnet18.py,直接运行:python migrate_resnet18.py - 观察输出:
max_diff应小于1e-4(浮点精度范围内),证明ONNX Runtime与PyTorch推理结果一致 - 程序会生成
resnet18_steel.onnx模型文件和sample_test.png测试图,并打印预测类别索引
通过条件:程序无报错退出,且打印的最大误差小于1e-4。若误差过大,检查onnxruntime版本与opset兼容性。
常见问题
- 导出失败:升级torch版本至2.0+,或降低opset_version至11
- 推理速度慢:确认使用
CPUExecutionProvider,或改用CUDAExecutionProvider(需GPU环境) - 真实钢材数据替换:将
predict_image中的图像预处理改为训练时的标准化参数,并将模型权重替换为微调后的.pth文件