----目录
|----概念与作用
| |----什么是ONNX
| |----为什么要用ONNX
|----模型转换与验证 (pytorch -> onnx)
| |----环境配置
| |----模型转换
| |----模型简化(onnxsim)
| |----模型加载验证
|----模型调试
|----模型推理
| |----onnxruntime介绍
| |----onnxruntime安装
| |----onnxruntime使用
└─── 名词解释
- 概念与作用
-
什么是ONNX
- ONNX是开放神经网络交换(Open Neural Network Exchange)的简称,创始人是贾扬清,2017年由微软、facebook等几个公司联合推出,它定义了一个与环境和平台无关的中间格式,用以存储训练好的模型,这就使得不同的训练框架可以使用相同的中间格式进行交互。即,无论你使用什么样的训练框架来训练模型(比如TensorFlow/Pytorch/OneFlow/Paddle),你都可以在训练后将这些框架的模型统一转为ONNX存储。简单来说,ONNX就是模型转换的中间人。
- ONNX文件不仅存储了神经网络模型的权重,还存储了模型的结构、网络中各层的输入输出等一些信息。ONNX用有向无环图来描述网络结构,即网络由节点(Node)和边(Tensor)组成
- ONNX使用Protobuf序列化数据结构去存储神经网络的权重信息,所以在安装onnx时还需要安装protobuf
-
为什么要用ONNX
- ONNX的目的为打破开发框架与硬件架构间的依赖关系,让基于不同深度学习框架训练的模型能够互通互用,实现AI模型的可移植性与互操作性。基于ONNX, AI开发人员可以自由灵活的组合使用开发工具,专注于优化模型性能,而硬件供应商能够简化其针对平台的优化。
-
- 模型转换与验证 (pytorch -> onnx)
-
环境配置
- 只需使用命令
pip install onnx
即可完成安装,同时也会检查安装Protobuf
- 只需使用命令
-
模型转换
-
核心函数——torch.onnx.export
torch.onnx.export(model, args, f, export_params=True, verbose=False, input_names=None, output_names=None,do_constant_folding=True,dynamic_axes=None,opset_version=9) 前三个为必选参数 model 要转换的pytorch模型 args 模型的任意一组输入,只要它是正确的类型和大小,其中的值可以是随机的 f 导出的onnx文件名称 其他常用参数 opset_version onnx算子集的版本。深度学习的发展不断诞生新算子,为支持这些新增算子,ONNX会经常发布新的算子集,目前已更新15个版本 input_names 输入tensor名称,如果不设置的话,会自动分配一些简单的名字(如数字)。很多推理引擎在运行ONNX文件时,都需要以“名称-张量值”的数据对来输入数据,并根据输出张量的名称来获取输出数据。在进行跟张量有关的设置(比如添加动态维度)时,也需要知道张量的名字。 output_names 输出tensor名称,同上
-
转换示例
import torch device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = torch.load('test.pth').to(device) # 这里保存的是完整模型 model.eval() dummy_input = torch.randn(1, 3, 96, 96, device=device) input_names = ['data'] output_names = ['fc'] torch.onnx.export(model, dummy_input, 'test.onnx', input_names=input_names, output_names=output_names)
-
转换结果可视化
-
可以使用 Netron (开源的模型可视化工具)来可视化 ONNX 模型
-
点击input或者output,可以查看 ONNX 模型的基本信息,包括模型的版本信息,以及模型输入、输出的名称和数据类型
-
点击某一个算子节点,可以看到算子的具体信息。比如点击第一个 Conv 可以看到:
每个算子记录了算子属性、图结构、权重三类信息-
算子属性信息,即图中 attributes 里的信息,对于卷积来说,算子属性包括了卷积核大小(kernel_shape)、卷积步长(strides)等内容。这些算子属性最终会用来生成一个具体的算子
-
图结构信息, 指算子节点在计算图中的名称、邻边的信息。对于图中的卷积来说,该算子节点叫做 Conv_0,输入数据叫做 images,输出数据叫做146。根据每个算子节点的图结构信息,就能完整地复原出网络的计算图。
-
权重信息, 指的是网络经过训练后,算子存储的权重信息。对于卷积来说,权重信息包括卷积核的权重值和卷积后的偏差值。点击图中 model.2.cv1.conv.weight, model.2.cv1.conv.bias后面的加号即可看到权重信息的具体内容。
-
-
-
-
模型简化(onnxsim)
-
作用
- torch导出的模型有时候参数过多,不利于查看。onnxsim可以简化模型,让显示更加自然
-
使用步骤
-
安装onnxsim包
pip install onnx-simplifier
-
加载onnx文件,simplify处理后重新保存
from onnxsim import simplify onnx_model = onnx.load(output_path) model_simp, check = simplify(onnx_model) assert check, "Simplified ONNX model could not be validated" onnx.save(model_simp, output_path) print('finished exporting onnx')
-
简化前后模型可视化查看
-
-
-
模型加载验证
-
可使用ONNX的API检查ONNX模型,onnx.load加载模型,onnx.checker.check_model验证模型的结构并确认模型具有有效的架构
-
检查示例
import onnx onnx_model = onnx.load("super_resolution.onnx") onnx.checker.check_model(onnx_model) # 若存在异常则抛出错误
-
-
-
模型调试
- 可通过
onnx.utils.extract_model
函数进行子模型提取、添加额外输出、输出中间节点的值等调试操作,可自行了解,在此不再展开
- 可通过
-
模型推理
-
onnxruntime介绍
-
微软开源了onnxruntime, 可以用于加载onnx模型进行推理。此外,其他框架也基本支持onnx格式模型的加载
-
onnxruntime是可以运行在多平台 (Windows,Linux,Mac,Android,iOS) 上的一款推理框架,它接受 ONNX 格式的模型输入,支持 GPU 和 CPU 的推理。兼容性强,只要能导出ONNX格式模型,它基本上都能成功加载,成功推理。唯一不足就是 ONNX 节点粒度较细,推理速度有时候比其他推理框架如 TensorRT 较低
-
-
onnxruntime安装
-
使用cpu
pip install onnxruntime
-
使用gpu
pip install onnxruntime-gpu
-
-
onnxruntime使用
-
整个onnxruntime的运行可以分为三个阶段,Session构造,模型初始化和运行
-
示例
import onnxruntime as ort # Create an inference session using the ONNX model and specify execution providers session = ort.InferenceSession(self.onnx_model, providers=['CUDAExecutionProvider', 'CPUExecutionProvider']) # Get the model inputs model_inputs = session.get_inputs() # Preprocess the image data img_data = self.preprocess() # Run inference using the preprocessed image data outputs = session.run(None, {model_inputs[0].name: img_data})
-
-
-
名词解释
-
训练框架:支持反向传播等训练方法,可以自动调整模型参数,用于算法设计
-
推理框架:单纯只能用于模型推理运算,不能调整模型本身,用于算法部署落地
-
Protobuf:Google Protocol Buffer,谷歌开源的可以跨语言的数据序列化方式,相比于xml、json,它的体量更小,解析速度更快
-