浏览器访问:Netron
点击 “Open Model” 按钮,选择要可视化的模型文件即可
终端进行安装:?pip install netron
安装完成后,在脚本中 调用包?import netron
运行程序?netron.start("model.onnx")
, 会自动打开浏览器进行可视化 (最后有例子)
我习惯用 pytorch,但是 netron 对 pytorch 的?.pt
?和?.pth
?文件不是很友好,所以,我都是先转换为 onnx 格式,再进行可视化,下面举例。
训练的归训练,部署的归部署。 onnx的存在极大地降低了部署的难度。
!pip3 install torch torchvision --extra-index-url https://download.pytorch.org/whl/cu113
!pip install onnx -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install onnxruntime -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install numpy pandas matplotlib tqdm opencv-python pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
import torch
print('PyTorch 版本', torch.__version__)
import onnx
print('ONNX 版本', onnx.__version__)
import onnxruntime as ort
print('ONNX Runtime 版本', ort.__version__)
import torch
from torchvision import models
# 有 GPU 就用 GPU,没有就用 CPU
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('device', device)
model = models.resnet18(pretrained=True)
model = model.eval().to(device)
x = torch.randn(1, 3, 256, 256).to(device)
output = model(x)
output.shape
with torch.no_grad():
torch.onnx.export(
model, # 要转换的模型
x, # 模型的任意一组输入
'resnet18_imagenet.onnx', # 导出的 ONNX 文件名
opset_version=11, # ONNX 算子集版本
input_names=['input'], # 输入 Tensor 的名称(自己起名字)
output_names=['output'] # 输出 Tensor 的名称(自己起名字)
)
我只修改了自己代码的这个地方↓
# '''pth模型文件转为onnx格式'''
with torch.no_grad():
torch.onnx.export(
model, # 要转换的模型
img, # 模型的任意一组输入
'resnet34_classification.onnx', # 导出的 ONNX 文件名
opset_version=11, # ONNX 算子集版本
input_names=['input'], # 输入 Tensor 的名称(自己起名字)
output_names=['output'] # 输出 Tensor 的名称(自己起名字)
)
import onnx
# 读取 ONNX 模型
onnx_model = onnx.load('resnet18_imagenet.onnx')
# 检查模型格式是否正确
onnx.checker.check_model(onnx_model)
print('无报错,onnx模型载入成功')
import onnxruntime
import numpy as np
import torch
import torch.nn.functional as F
import pandas as pd
ort_session = onnxruntime.InferenceSession('resnet18_imagenet.onnx')
x = torch.randn(1, 3, 256, 256).numpy()
x.shape # (1, 3, 256, 256)
# onnx runtime 输入
ort_inputs = {'input': x}
# onnx runtime 输出
ort_output = ort_session.run(['output'], ort_inputs)[0]
注意,输入输出张量的名称需要和 torch.onnx.export 中设置的输入输出名对应
ort_output.shape # (1, 1000)
img_path = 'banana1.jpg'
# 用 pillow 载入
from PIL import Image
img_pil = Image.open(img_path)
from torchvision import transforms
# 测试集图像预处理-RCTN:缩放裁剪、转 Tensor、归一化
test_transform = transforms.Compose([transforms.Resize(256),
transforms.CenterCrop(256),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
input_img = test_transform(img_pil)
input_img.shape # torch.Size([3, 256, 256])
input_tensor = input_img.unsqueeze(0).numpy()
input_tensor.shape # (1, 3, 256, 256)
# ONNX Runtime 输入
ort_inputs = {'input': input_tensor}
# ONNX Runtime 输出
pred_logits = ort_session.run(['output'], ort_inputs)[0]
pred_logits = torch.tensor(pred_logits)
pred_logits.shape # torch.Size([1, 1000]) 因为ImageNet有1000类
# 对 logit 分数做 softmax 运算,得到置信度概率
pred_softmax = F.softmax(pred_logits, dim=1)
pred_softmax.shape # torch.Size([1, 1000])
# 取置信度最高的前 n 个结果
n = 3
top_n = torch.topk(pred_softmax, n)
top_n
'''torch.return_types.topk(
values=tensor([[9.9669e-01, 2.6005e-03, 3.0254e-04]]),
indices=tensor([[954, 939, 941]]))'''
# 预测类别
pred_ids = top_n.indices.numpy()[0]
pred_ids
'''array([954, 939, 941])'''
# 加载ONNX模型
onnx_model_path = 'resnet34_classification.onnx'
onnx_model = onnx.load(onnx_model_path)
# 创建ONNX Runtime会话
ort_session = onnxruntime.InferenceSession(onnx_model_path)
# 将PyTorch Tensor转换为NumPy数组
input_data = img.numpy()
# 运行预测
ort_inputs = {ort_session.get_inputs()[0].name: input_data}
ort_outputs = ort_session.run(['output'], ort_inputs)
# 获取预测结果
output = ort_outputs[0]
predict = torch.from_numpy(output)
predict_cla = torch.argmax(predict).item()
grading_result = int(class_indict[str(predict_cla)])
end_time = time.time()
# 打印预测时间
prediction_time = end_time - start_time
print("模型预测时间:{:.4f}秒".format(prediction_time))
return grading_result
注意:相比于直接用pt文件预测图片,输入的图像转成numpy的数据格式
# 将PyTorch Tensor转换为NumPy数组
input_data = img.numpy()