ONNX自定义算子与文件导出流程再梳理

news/2025/2/12 3:46:54/

一、ONNX的结构

        ONNX作为一种文件存储格式,使用的是Protobuf这个序列化数据结构去存储神经网络的权重信息。Protobuf是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

        加载了一个深度学习系列的onnx 模型文件之后,我们获得的就是一个ModelProto,它包含了一些版本信息,生产者信息和一个GraphProto。在GraphProto里面又包含了四个repeated数组,它们分别是node,input,output,initializer。其中node中存放了模型中所有的计算节点,input存放了模型的输入节点,output存放了模型中所有的输出节点,initializer存放了模型的所有权重参数。每个计算节点(NodeProto)除了必须的参数(input, output, op_type)外,可能还有一些和op_type相关的参数,这里会用AttributeProto存储。比如conv的属性:group, pad, strides。 Transpose 属性:perm。

        其中模型中每一层算子的信息使用NodeProto表示,保存在node的列表中,每个node节点都会有input和output两个数组,这两个数组是string类型,通过input和output的指向关系,就可以利用上述信息快速构建出一个深度学习模型的拓扑图。

  • ModelProto

    • GraphProto

      • node (NodeProto)

        • (AttributeProto)

      • input (ValueInfoProto)

      • output (ValueInfoProto)

      • initializer (TensorProto)

二、读取或者导出ONNX

        定义好一个onnx格式的模型后,通过onnx.load, onnx.save即可读取和保存模型文件。

import onnx
model = onnx.load(load_onnx_path)  #读取模型onnx.save(model, save_onnx_path)  #保存模型

三、手动构建模型拓扑结构

        通过onnx.help库的函数封装,构建上述的GraphProto, NodeProto, TensorProto, ValueinfoProto类型数据 ,之后保存文件。主要涉及onnx.helper.make_node, onnx.helper.make_tensor_value_info, onnx.helper.make_tensor, onnx.helper.make_graph, 这些函数具体的参数接口可以看onnx.helper文档。

        其中,make_node时候,op_type很关键,要和onnx的opset对应上,具体支持的类型和构建示例见官方文档:https://github.com/onnx/onnx/blob/main/docs/Operators.md

        下面是构建一个只有一层matmul算子的model的示例:

import onnx
import numpy as npM=10
N=20
K=16
A_data=np.random.random([M,K])
B_data=np.random.random([K,N])
output_C=np.matmul(A_data,B_data)nodes = [onnx.helper.make_node(op_type="MatMul",inputs=['input_A', 'input_B'],outputs=['output_C'],name=name)]init_tensor = [onnx.helper.make_tensor('input_B', onnx.TensorProto.FLOAT, B_data.shape, B_data.flatten().tolist())]inputs= [onnx.helper.make_tensor_value_info(name=net_info[lname]['name'], elem_type=onnx.TensorProto.FLOAT, shape=A_data.shape]outputs = [onnx.helper.make_tensor_value_info(name='output_C', elem_type=onnx.TensorProto.FLOAT, shape=output_C.shape)]graph = onnx.helper.make_graph(nodes=nodes, name="onnx_test", inputs=inputs, outputs=outputs,initializer=init_tensor)onnx_model = onnx.helper.make_model(graph, opset_imports=[make_opsetid(domain="", version=18)])onnx.save(onnx_model, onnx_fpath)

四、导出模型检查

        如下代码可以对手动构建或者修改后的onnx模型进行拓扑结构检查。检查模型格式是否正确,图结构是否完整,节点是否正确等。

        该步骤主要帮助发现一些不合理的连接关系,比如按nodes列表顺序构建到节点b时候,b节点依赖a节点,但是b节点前面没有出现过a节点,这就是一个错误的graph拓扑关系。

onnx.checker.check_model(onnx_model)

        如果上面的检查通过了,那么可以试着对保存的onnx执行一次推理,如果正常执行结束,则说明我们的构建保存的onnx模型是正确的。

        这一步可以检查出一些不合理的数据类型。比如对于reshape节点来说有两个输入,一个是要reshape的数据数组(假设是A),另一个是reshape的形状数组(假设是B),B的数据类型必须是整数类型,这在导出onnx模型的check_model是检查不出来的。

import onnx
import onnxruntimedef get_in_out_name(op, onnx_session):node_name = []if op =='inputs':for node in onnx_session.get_inputs():node_name.append(node.name)else:for node in onnx_session.get_outputs():node_name.append(node.name)return node_nameonnx_path = '../model.onnx'
xdata = np.random.random((1, 1, 1, 384, 1024))onnx_session = onnxruntime.InferenceSession(onnx_path)
input_name = get_in_out_name('inputs', onnx_session) #得到所有的输入节点名字dummy_input = {input_name[0]: np.float32(xdata),  #假设这里只有一个输入节点
}
result = onnx_session.run(None, input_feed=dummy_input)
print('output shape is:', result[0].shape)#其中一个输出的形状

五、从ini算子到onnx模型的处理逻辑

1, 从generate_model_file.py获取算子的信息

  包括:

  name, 层名字

  op_type, 算子类型

  input_shape, 输入尺寸

  output_shape, 输出尺寸

  in_layer_name,该层的输入来自哪些层

  out_layer_name,该层的输出会去向哪些层

  data: [ifmap, ifmap2, weights, bias, output_compile], 具体的map数据和权重数据

  head,attention模块的head

  scale,attention模块score的除数数据

  a_transpose, 当matmul算子相关时候参数

  b_transpose, 当matmul算子相关时候参数

2, 构建onnx模型的node节点。

        根据上一步的算子信息,逐层构建节点。需要输入,输出,初始化超参数的节点都构建好。这个过程也对应着处理好模型的拓扑结构。

        目前benchmark模型可以支持的onnx node算子如下,后面可以根据https://github.com/onnx/onnx/blob/main/docs/Operators.md增加更多需要的算子。

“MatMul”, “Add”, “Softmax”, “LayerNormalization”, “Reshape”, “Transpose”,“Constant”,“Div”

3,保存onnx模型

        使用了onnx.checker.check_model(onnx_model)来检查构建的模型拓扑结构是否正确,如果不对会程序报错退出,但是前一步也会保存出一个onnx模型文件,可以用netron可视化看到哪里的连接关系不对。


http://www.ppmy.cn/news/1203932.html

相关文章

python selenium 点击表格中的一系列按钮并输出弹窗内容到csv

一个python selenium的实用实例,比demo重,但也不算太复杂。 trick总结如下: 最新chromedriver的地址,https://googlechromelabs.github.io/chrome-for-testing,这很重要,不然就要处理chrome自动更新之类的…

算法通过村第十八关-回溯|白银笔记|经典问题

文章目录 前言组合总和问题分割回文串子集问题排序问题字母大小写全排列单词搜索总结 前言 提示:我不愿再给你写信了。因为我终于感到,我们的全部通信知识一个大大的幻影,我们每个人知识再给自己写信。 --安德烈纪德 回溯主要解决一些暴力枚举…

解决kubernetes node节点flannel网卡始终不能添加成功的问题

因为kubernetes证书过期,续签证书以后就出现了这问题: node节点报错日志如下: 该节点上flannel网络始终不能初始化成功,始终报错:CrashLoopBackOff。 查了很多资料,尝试过很多方法,包括&#x…

阿里云大模型环境依赖安装

安装遇到这个报错 ERROR: Could not build wheels for healpy, which is required to install pyproject.toml-based projects 解决方法: 执行命令: pip3 install setuptools wheel

【JS进阶】纯函数 + 高阶函数 + 函数柯里化

纯函数 高阶函数 函数柯里化 1.纯函数 纯函数 (Pure Function) 是函数式编程中一个非常重要的概念。 纯函数是一个定义,对于一个纯函数,执行它不会产生不可预料的行为,也不会对外部产生影响。 如果一个函数是纯函数,其必须符…

南昌大学漏洞报送证书

获取来源:edusrc(教育漏洞报告平台) url:https://src.sjtu.edu.cn/ 兑换价格:20金币 获取条件:南昌大学任意中危或以上级别漏洞

华为李鹏:到 2025 年智能算力需求将达到目前水平的 100 倍

在第十四届全球移动宽带论坛上,华为高级副总裁、运营商 BG 总裁李鹏表示,大模型为代表的 AI 应用发展带来对智能算力的爆发式需求。 李鹏在题为《加速 5G 商业正循环,拥抱更繁荣的 5.5G》的讲话中表示,「5G 已经走在商业成功的正确…

如何开始使用RACE模型?

覆盖、行动、转化和参与 (RACE) 框架是关键方法之一,可帮助您在数字营销活动(例如 Google 每次点击付费广告)中获得天文数字回报。 为什么? 该模型可以帮助您在成为客户和品牌传播者之前跟踪在线用户的旅程。 RACE 营销模型的每…