技术标签: 深度学习 pytorch 模型转换 感知算法学习 ONNX
本文主要介绍如何将PyTorch模型转换为ONNX模型,为后面的模型部署做准备。转换后的xxx.onnx模型,进行加载和测试。最后介绍使用Netron,可视化ONNX模型,看一下网络结构;查看使用了那些算子,以便开发部署。
目录
将PyTorch模型转换为ONNX模型,通常是使用torch.onnx.export( )函数来转换的,基本的思路是:
下面有一个简单的例子:
import torch
import torch.onnx
# 加载 PyTorch 模型
model = ...
# 设置模型输入,包括:通道数,分辨率等
dummy_input = torch.randn(1, 3, 224, 224, device='cpu')
# 转换为ONNX模型
torch.onnx.export(model, dummy_input, "model.onnx", export_params=True)
这里举一个resnet18的例子,基本思路是:
torch.randn()
函数生成了一个随机张量。onnx.export()
函数将 PyTorch 模型转换为 ONNX 格式,并将其保存到指定的输出文件中。程序如下:
import torch
import torchvision.models as models
# 加载预训练的 ResNet18 模型
model = models.resnet18(pretrained=True)
# 将模型设置为评估模式
model.eval()
# 定义输入张量,需要与模型的输入张量形状相同
input_shape = (1, 3, 224, 224)
x = torch.randn(input_shape)
# 需要指定输入张量,输出文件路径和运行设备
# 默认情况下,输出张量的名称将基于模型中的名称自动分配
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 将 PyTorch 模型转换为 ONNX 格式
output_file = "resnet18.onnx"
torch.onnx.export(model, x.to(device), output_file, export_params=True)
举一个resnet18的例子:基本思路是:
onnx.export()
函数将 PyTorch 模型转换为 ONNX 格式;指定参数do_constant_folding=False,不加载模型的权重。import torch
import torchvision.models as models
# 加载 PyTorch 模型
model = models.resnet18()
# 将模型转换为 ONNX 格式但不加载权重
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(model, dummy_input, "resnet18.onnx", do_constant_folding=False)
下面构建一个简单网络结构,并转换为ONNX
import torch
import torchvision
import numpy as np
# 定义一个简单的PyTorch 模型
class MyModel(torch.nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.conv1 = torch.nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.relu = torch.nn.ReLU()
self.maxpool = torch.nn.MaxPool2d(kernel_size=2, stride=2)
self.conv2 = torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.flatten = torch.nn.Flatten()
self.fc1 = torch.nn.Linear(64 * 8 * 8, 10)
def forward(self, x):
x = self.conv1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.conv2(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.flatten(x)
x = self.fc1(x)
return x
# 创建模型实例
model = MyModel()
# 指定模型输入尺寸
dummy_input = torch.randn(1, 3, 32, 32)
# 将PyTorch模型转为ONNX模型
torch.onnx.export(model, dummy_input, 'mymodel.onnx', do_constant_folding=False)
看一下这个函数的参数
torch.onnx.export(
model,
args,
f,
export_params=True,
opset_version=10,
do_constant_folding=True,
input_names=['input'],
output_names=['output'],
dynamic_axes=None,
verbose=False,
example_outputs=None,
keep_initializers_as_inputs=None)
model
:需要导出的 PyTorch 模型args
:PyTorch模型输入数据的尺寸,指定通道数、长和宽。可以是单个 Tensor 或元组,也可以是元组列表。f
:导出的 ONNX 文件路径和名称,mymodel.onnx。export_params
:是否导出模型参数。如果设置为 False,则不导出模型参数。opset_version
:导出的 ONNX 版本。默认值为 10。do_constant_folding
:是否对模型进行常量折叠。如果设置为 True,不加载模型的权重。input_names
:模型输入数据的名称。默认为 'input'。output_names
:模型输出数据的名称。默认为 'output'。dynamic_axes
:动态轴的列表,允许在导出的 ONNX 模型中创建变化的维度。verbose
:是否输出详细的导出信息。example_outputs
:用于确定导出 ONNX 模型输出形状的样本输出。keep_initializers_as_inputs
:是否将模型的初始化器作为输入导出。如果设置为 True,则模型初始化器将被作为输入的一部分导出。
下面是只是一个常用的模板
import torch.onnx
# 转为ONNX
def Convert_ONNX(model):
# 设置模型为推理模式
model.eval()
# 设置模型输入的尺寸
dummy_input = torch.randn(1, input_size, requires_grad=True)
# 导出ONNX模型
torch.onnx.export(model, # model being run
dummy_input, # model input (or a tuple for multiple inputs)
"xxx.onnx", # where to save the model
export_params=True, # store the trained parameter weights inside the model file
opset_version=10, # the ONNX version to export the model to
do_constant_folding=True, # whether to execute constant folding for optimization
input_names = ['modelInput'], # the model's input names
output_names = ['modelOutput'], # the model's output names
dynamic_axes={'modelInput' : {0 : 'batch_size'}, # variable length axes
'modelOutput' : {0 : 'batch_size'}})
print(" ")
print('Model has been converted to ONNX')
if __name__ == "__main__":
# 构建模型并训练
# xxxxxxxxxxxx
# 测试模型精度
#testAccuracy()
# 加载模型结构与权重
model = Network()
path = "myFirstModel.pth"
model.load_state_dict(torch.load(path))
# 转换为ONNX
Convert_ONNX(model)
加载ONNX模型,通常需要用到ONNX、ONNX Runtime,所以需要先安装。
pip install onnx
pip install onnxruntime
加载ONNX模型可以使用ONNX Runtime库,以下是一个加载ONNX模型的示例代码:
import onnxruntime as ort
# 加载 ONNX 模型
ort_session = ort.InferenceSession("model.onnx")
# 准备输入信息
input_info = ort_session.get_inputs()[0]
input_name = input_info.name
input_shape = input_info.shape
input_type = input_info.type
# 运行ONNX模型
outputs = ort_session.run(input_name, input_data)
# 获取输出信息
output_info = ort_session.get_outputs()[0]
output_name = output_info.name
output_shape = output_info.shape
output_data = outputs[0]
print("outputs:", outputs)
print("output_info :", output_info )
print("output_name :", output_name )
print("output_shape :", output_shape )
print("output_data :", output_data )
以下是一个示例程序,将 resnet18 模型从 PyTorch 转换为 ONNX 格式,然后加载和测试 ONNX 模型的过程:
import torch
import torchvision.models as models
import onnx
import onnxruntime
# 加载 PyTorch 模型
model = models.resnet18(pretrained=True)
model.eval()
# 定义输入和输出张量的名称和形状
input_names = ["input"]
output_names = ["output"]
batch_size = 1
input_shape = (batch_size, 3, 224, 224)
output_shape = (batch_size, 1000)
# 将 PyTorch 模型转换为 ONNX 格式
torch.onnx.export(
model, # 要转换的 PyTorch 模型
torch.randn(input_shape), # 模型输入的随机张量
"resnet18.onnx", # 保存的 ONNX 模型的文件名
input_names=input_names, # 输入张量的名称
output_names=output_names, # 输出张量的名称
dynamic_axes={input_names[0]: {0: "batch_size"}, output_names[0]: {0: "batch_size"}} # 动态轴,即输入和输出张量可以具有不同的批次大小
)
# 加载 ONNX 模型
onnx_model = onnx.load("resnet18.onnx")
onnx_model_graph = onnx_model.graph
onnx_session = onnxruntime.InferenceSession(onnx_model.SerializeToString())
# 使用随机张量测试 ONNX 模型
x = torch.randn(input_shape).numpy()
onnx_output = onnx_session.run(output_names, {input_names[0]: x})[0]
print(f"PyTorch output: {model(torch.from_numpy(x)).detach().numpy()[0, :5]}")
print(f"ONNX output: {onnx_output[0, :5]}")
上述代码中,首先加载预训练的 resnet18 模型,并定义了输入和输出张量的名称和形状。
然后,使用 torch.onnx.export() 函数将模型转换为 ONNX 格式,并保存为 resnet18.onnx 文件。
接着,使用 onnxruntime.InferenceSession() 函数加载 ONNX 模型,并使用随机张量进行测试。
最后,将 PyTorch 模型和 ONNX 模型的输出进行比较,以确保它们具有相似的输出。
使用Netron,可视化ONNX模型,看一下网络结构;查看使用了那些算子,以便开发部署。
这里简单介绍一下
Netron是一个轻量级、跨平台的模型可视化工具,支持多种深度学习框架的模型可视化,包括TensorFlow、PyTorch、ONNX、Keras、Caffe等等。它提供了可视化网络结构、层次关系、输出尺寸、权重等信息,并且可以通过鼠标移动和缩放来浏览模型。Netron还支持模型的导出和导入,方便模型的分享和交流。
Netron的网页在线版本,直接在网页中打开和查看ONNX模型Netron
支持多种操作系统:
macOS: Download
Linux: Download
Windows: Download
Browser: Start
Python Server: Run pip install netron
and netron [FILE]
or netron.start('[FILE]')
.
下面是可视化模型截图:
还能查看某个节点(运算操作)的信息,比如下面MaxPool,点击一下,能看到使用的3x3的池化核,是否有填充pads,步长strides等参数。
分享完毕~
文章浏览阅读226次。服务器上先加载torch再加载pandas,出现如下报错:ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /root/miniconda3/lib/python3.8/site-packages/pandas/_libs/window/aggregations.cpython-38-x86_64-linux-gnu.so)_pandas version `glibcxx_3.4.29' not found
文章浏览阅读1.2k次,点赞6次,收藏25次。物业管理系统顾名思义就是管理物业的系统啦,虽然每年毕业设计都会爆出大量的XX管理系统,会让人觉得很low,但不可否认,使用管理系统作为毕业设计是上手最快,并且最容易通过的计算机专业的毕业设计。该项目是本人动手实操的一个毕业设计,从理解到具体实现简单易操作,并成功通过学校严格的毕业设计考核。该项目用到的主要技术框架为SpringBoot,不想以java为主要编程语言的同学可以跳过啦。在数据库上主要使用MySQL数据库与Mybatis进行数据管理,用户登录管理方面使用的shiro安全框架。_物业管理系统java
文章浏览阅读169次。华中科技大学硕士研究生入学考试《微型计算机原理及应用》考试大纲科目代码(886)第一部分 考 试 说 明一、考试性质《微型计算机原理及应用》是报考我校软件学院硕士生选考的专业基础课之一。考试的评价标准为高等学校的优秀本科毕业生能达到的水平,以保证被录取的考生具有较好的微型计算机理论基础和应用能力。考试对象为报考我校硕士研究生入学考试的准考考生。二、考试形式与试卷结构(一) 答卷方式:闭卷,笔试(二..._test al,81h
文章浏览阅读207次。ls -l命令查看的时间是文件最后的修改时间。改变时间:ctime:文件属性,比如权限。删除时间:dtime:文件被删除的时间。访问时间:atime:查看内容。修改时间:mtime:修改内容。_linux mtime
文章浏览阅读2.3k次。直接用白书上的翻译吧例题1 勇者斗恶龙(The Dragon of Loowater, UVa 11292)你的王国里有一条n个头的恶龙,你希望雇一些骑士把它杀死(即砍掉所有头)。村里有m个骑士可以雇佣,一个能力值为x的骑士可以砍掉恶龙一个直径不超过x的头,且需要支付x个金币。如何雇佣骑士才能砍掉恶龙的所有头,且需要支付的金币最少?注意,一个骑士只能砍一个头(且不能被雇佣两次)。_勇者斗恶龙csdn
文章浏览阅读2.5k次。In-Sight Explorer 仿真器无法正常启动与连接问题解决过程一、问题出现经过在某天突然报错查不到问题所在偶然间发现这个二、问题解决过程1.首先查看下自己的端口占用情况2. 再查看下自己默认动态的端口区段3. 修改端口区段中动态端口配置5. 重启电脑后生效并检查6. 重新打开In-Sight软件的仿真器OK三、总结一、问题出现经过在某天突然报错一段时间没打开In-Sight IDE软件了,突然有天打开发现这个IDE软件启动报错:服务端口1096端口…查不到问题所在显然是端口占用问题,但通_in-sight explorer
文章浏览阅读6k次,点赞18次,收藏89次。经典马里奥小游戏新年好!祝各位朋友新年快乐!!健康平安!!!代码有部分删减,不影响理解。演示视频.具体过程:按下十字按键的中央按键开始游戏。碰到柱子边界游戏结束。累计平安通过一定数量的柱子障碍,获得积分奖励,可选择继续游戏,失败则成绩全部清零;或直接结束游戏,并存档游戏进度。具体代码片段:`timescale 1ns / 1psmodule project_..._verilog 小游戏
文章浏览阅读173次。软件设计模式一、软件设计模式的产生背景1、设计模式出处设计模式”这个术语最初并不是出现在软件设计中,而是被用于建筑领域的设计中。1977 年,美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫·亚历山大(Christopher Alexander)在他的著作《建筑模式语言:城镇、建筑、构造》(A Pattern Language: Towns Building Construction)中描述了一些常见的建筑设计问题,并提出了 253 种关于对城镇、邻里、住宅、花园和房间等进行_对软件设计模式的认识
文章浏览阅读176次。梅贻琦对吴岭澜说:“人把自己置身于忙碌当中,有一种麻木的踏实,但丧失了真实,你的青春也不过只有这些日子。 什么是真实? 你看到什么,听到什么,做什么,和谁在一起 有一种,从心灵深处,满溢出来的不懊悔,也不羞耻的平和与喜悦。”1分24秒旋律的突变,配合电影中一群来路不明战机的出现,看的时候心立即就揪起来了,以为光耀遇到了敌机埋伏,旋律再次回归正常,看到了光耀队友们战机向贫民窟的孩子们投..._粗布衣茅草房 铁骨铮铮
文章浏览阅读1.5k次,点赞2次,收藏10次。一、Mapreduce 计算整数的最大值和最小值【实验目的】1)理解mapreduce执行原理2)理解map,reduce阶段3)函数的使用【实验原理】需求描述:对输入文件中数据进行计算找出这一组数据中的最大值和最小值。原始数据:1021039109200..._mapreduce使用
文章浏览阅读1.7k次,点赞4次,收藏17次。本次实战项目素材来自尚硅谷的React全展现全栈,项目内容是使用react + antd的方式开发后台管理系统,本文在这里记录一下开发时踩到的小坑以及解决方案,希望能对你有帮助!_bundle.js:305982 warning: react does not recognize the `eventkey` prop on a
文章浏览阅读4.5w次,点赞42次,收藏286次。请参见图示。 管理员必须向路由器 A 网络中的所有成员发送一条消息。 那么网络 172.16.16.0/22 的广播地址是什么?172.16.23.255172.16.255.255172.16.16.255172.16.20.255 172.16.19.255请参见图示。 思考一下 10.16.10.0/24 网络范围内已经使用了的地址和必须保留的地址,下列哪个子网地址可以分配给包含 25 台主机的网络?10.16.10.240/2810.16.10.12..._哪一项是 ipv6 地址 2002:0420:00c4:1008:0025:0190:0000:0990 的简写格式?