ONNX结构及构建抽取子图及编辑onnx 模型
ONNX结构
https://mmdeploy.readthedocs.io/zh-cn/latest/tutorial/05_onnx_model_editing.html
https://blog.csdn.net/u013597931/article/details/84401047
https://zhuanlan.zhihu.com/p/346511883
https://zhuanlan.zhihu.com/p/353613079
https://zhuanlan.zhihu.com/p/350702340
https://zhuanlan.zhihu.com/p/350833729
ONNX抽取子图
https://github.com/onnx/onnx/blob/main/docs/PythonAPIOverview.md
https://blog.csdn.net/u013597931/article/details/84635779
import onnx
input_path = "path/to/the/original/model.onnx"
output_path = "path/to/save/the/extracted/model.onnx"
input_names = ["input_0", "input_1", "input_2"]
output_names = ["output_0", "output_1"]
onnx.utils.extract_model(input_path, output_path, input_names, output_names)
ONNX 获取每层节点名以及每层输入
import os
import glob
import subprocess
import numpy as np
import onnxruntime as ort
import onnx
import sys
import shutil
import copy
import json
from collections import OrderedDict
from utilities.utils import *
if __name__ == "__main__":
model = onnx.load("./tmp/deeplabv3.onnx")
# 模型推理
ori_output = copy.deepcopy(model.graph.output)
# 输出模型每层的输出
for node in model.graph.node:
for output in node.output:
if output not in ori_output:
model.graph.output.extend([onnx.ValueInfoProto(name=output)])
#进行配置
if ort.get_device()=="CPU":
config = ort.SessionOptions()
cpu_num_thread=4
config.intra_op_num_threads = cpu_num_thread
config.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
providers=["CPUExecutionProvider"]
ort_session = ort.InferenceSession(model.SerializeToString(),providers=providers,sess_options=config)
input = np.fromfile("./tmp/inputdata_fp32.bin", dtype='float32').reshape(8,519,519,3)
ort_inputs = {ort_session.get_inputs()[0].name: input}
#获取所有节点输出
outputs = [x.name for x in ort_session.get_outputs()] #ort_session.get_outputs()[0].name是原模型的单一输出
ort_outs = ort_session.run(output_names=outputs, input_feed=ort_inputs)
# 生成字典,便于查找层对应输出
# ort_outs = OrderedDict(zip(outputs, ort_outs))
result_outs = OrderedDict(zip(outputs, ort_outs))
# print("result_outs.keys(): ", result_outs.keys())
for key in result_outs.keys():
if "aspp/conv_1x1_concat/Relu:0" in key:
print("key: ", key)
# print(f'key --> {key} : value --> {result_outs[key]}')
print("value shape: ", result_outs[key].shape)
stc_out = np.fromfile("./tmp/test_dump/stc_cpu/aspp.bin", dtype='float32').reshape(result_outs[key].shape)
# verify_atol_rtol(stc_out, result_outs[key], atol=1e-6, rtol=5e-6)
verify_atol_rtol(stc_out, result_outs[key], atol=1e-2, rtol=5e-2)
# verify_atol_rtol(stc_out, result_outs[key], atol=0, rtol=0)
break
编辑onnx 模型
onnx模型编辑方法有2种:
- onnx-graphsurgeon : 手工编辑onnx模型
- onnx-modifier : 图形化编辑onnx模型
虽然onnx-modifier有图形界面编辑onnx,但是实际用起来问题特别多。onnx-graphsurgeon用起来更加强大,简洁。
onnx-graphsurgeon: onnx改图开源工具,onnx模型导入过程中如果出现问题, 部分场景可通过改图的方式并配合推理引擎来解决。除了支持onnx改图,此工具需要支持推理引擎原生模型结构的直接修改
安装方法如下:
pip install onnx_graphsurgeon --index-url https://pypi.ngc.nvidia.com
也可以源码编译安装:
make build
pip install onnx_graphsurgeon/dist/onnx_graphsurgeon-*-py2.py3-none-any.whl
基本操作
使用ipython命令进行交互式操作
import onnx_graphsurgeon as gs
import onnx
import numpy as np
graph = gs.import_onnx(onnx.load("test.onnx"))
graph #查看所有信息
graph.inputs #查看所有输入信息
graph.nodes #查看所有输出信息
graph.nodes[0] #查看node0的信息
onnx.save(gs.export_onnx(graph), "modified.onnx") # 保存onnx模型
新增节点
# 新增节点,对input做transpose
trans_out = gs.Variable("trans_out",dtype=np.float32, shape=(4,6,5,7))
trans_op=gs.Node(op="Transpose", inputs=[graph.inputs[0]], outputs=[trans_out], attrs={"perm":[0,2,1,3]})
# node0的输入改为trans_out
graph.nodes[0].inputs[0]=trans_out
# 插入到nodes中
graph.nodes.insert(0,trans_op)
# 修改input shape
graph.inputs[0].shape=[4,5,6,7]

浙公网安备 33010602011771号