python关于onnx模型的⼀些基本操作
onnx的基本操作
最近在对模型进⾏量化时候,模型格式转变为onnx模型了,因此需要对onnx进⾏加载、运⾏以及量化(权重/输⼊/输出)。故,对onnx 模型的相关操作进⾏简单的学习,并写下了这边博客,若有错误请指出,谢谢。
⼀、onnx的配置环境
onnx的环境主要包含两个包onnx和onnxruntime,我们可以通过pip安装这两个依赖包。
pip install onnxruntime
pip install onnx
⼆、获取onnx模型的输出层
import onnx
# 加载模型
model = onnx.load('')
# 检查模型格式是否完整及正确
onnx.checker.check_model(model)
# 获取输出层,包含层名称、维度信息
版本英文output = aph.output
print(output)
三、获取中节点输出数据
onnx模型通常只能拿到最后输出节点的输出数据,若想拿到中间节点的输出数据,需要我们⾃⼰添加相应的输出节点信息;⾸先需要构建指定的节点(层名称、数据类型、维度信息);然后再通过inrt的⽅式将节点插⼊到模型中。
import onnx
from onnx import helper
# 加载模型
model = onnx.load('')
mermaid# 创建中间节点:层名称、数据类型、维度信息
爸爸去哪儿英文版主题曲prob_info = helper.make_tensor_value_info('layer1',onnx.TensorProto.FLOAT,[1,3,320,280])
# 将构建完成的中间节点插⼊到模型中
# 保存新的模型
onnx.save(model,'onnx_')
# 扩展:
# 删除指定的节点⽅法: item为需要删除的节点
# ve(item)
四、onnx前向InferenceSession的使⽤
关于onnx的前向推理,onnx使⽤了onnxruntime计算引擎。
onnx runtime是⼀个⽤于onnx模型的推理引擎。微软联合Facebook等在2017年搞了个深度学习以及机器学习模型的格式标准–ONNX,顺路提供了⼀个专门⽤于ONNX模型推理的引擎(onnxruntime)。
import onnxruntime
大家好的英文
# 创建⼀个InferenceSession的实例,并将模型的地址传递给该实例
ss = onnxruntime.InferenceSession('')
# 调⽤实例ss的润⽅法进⾏推理
outputs = ss.run(output_layers_name,{input_layers_name: x})
1. 创建实例,源码分析
class InferenceSession(Session):
"""
This is the main class ud to run a model.
"""
def__init__(lf, path_or_bytes, ss_options=None, providers=[]):
"""
:param path_or_bytes: filename or rialized model in a byte string
:param ss_options: ssion options
:param providers: providers to u for ssion. If empty, will u
all available providers.
"""
lf._path_or_bytes = path_or_bytes
lf._ss_options = ss_options
lf._load_model(providers)
lf._enable_fallback =True
Session.__init__(lf, lf._ss)
def_load_model(lf, providers=[]):
if isinstance(lf._path_or_bytes,str):
lf._ss = C.InferenceSession(
lf._ss_options if lf._ss_options _default_ssion_options(), lf._path_or_bytes,
True)
elif isinstance(lf._path_or_bytes,bytes):
lf._ss = C.InferenceSession(
lf._ss_options if lf._ss_options _default_ssion_options(), lf._path_or_bytes,
Fal)
# elif isinstance(lf._path_or_bytes, tuple):
# to remove, hidden trick
# lf._ss.load_model_no_init(lf._path_or_bytes[0], providers)
el:
rai TypeError("Unable to load from type '{0}'".format(type(lf._path_or_bytes)))
lf._ss.load_model(providers)
lf._ss_options = lf._ss.ssion_options
lf._inputs_meta = lf._ss.inputs_meta
lf._outputs_meta = lf._ss.outputs_meta
lf._overridable_initializers = lf._ss.overridable_initializers
lf._model_meta = lf._ss.model_meta
lf._providers = lf._ss.get_providers()
# Tensorrt can fall back to CUDA. All others fall back to CPU.
if'TensorrtExecutionProvider'_available_providers():
lf._fallback_providers =['CUDAExecutionProvider','CPUExecutionProvider']
el:
lf._fallback_providers =['CPUExecutionProvider']
在_load_model函数,可以发现在load模型的时候是通过C.InferenceSession,并且将相关的操作也委托给该类。从导⼊语句from onnxruntime.capi import _pybind_state as C可知其实就是⼀个c++实现的Python接⼝,其源码在
onnxruntime\onnxruntime\python\onnxruntime_中。
2. 模型推理run,源码分析
def run(lf, output_names, input_feed, run_options=None):
"""
Compute the predictions.
:param output_names: name of the outputs
:param input_feed: dictionary ``{ input_name: input_value }``
:param run_options: See :class:`onnxruntime.RunOptions`.sweetbox
::
ss.run([output_name], {input_name: x})
"""
stocknum_required_inputs =len(lf._inputs_meta)
num_inputs =len(input_feed)
# the graph may have optional inputs ud to override initializers. allow for that.
if num_inputs < num_required_inputs:
rai ValueError("Model requires {} inputs. Input Feed contains {}".format(num_required_inputs, num_inputs))
if not output_names:
output_names =[output.name for output in lf._outputs_meta]
try:
return lf._ss.run(output_names, input_feed, run_options)
except C.EPFail as err:
if lf._enable_fallback:
print("EP Error: {} using {}".format(str(err), lf._providers))
print("Falling back to {} and retrying.".format(lf._fallback_providers))
lf.t_providers(lf._fallback_providers)
# Fallback only once.
lf.disable_fallback()
return lf._ss.run(output_names, input_feed, run_options)
先生英文el:
rai
英语绕口令带翻译 在run函数中,数据的推理是通过调⽤lf._ss.run来进⾏前向推理的。同理该函数的具体实现实在c++的InferenceSession类中实现的。
五、遇到的⼀些问题
1. 输⼊数据维度或类型不正确
4月英文在这⾥插⼊图⽚描述
fortminor
从上图可以看出,该模型的输⼊数据的维度信息为[1, 3, 480, 640],输⼊数据类型为float32;所以在构建输⼊数据时,⼀定要按照该信息去构建,否则代码将会报错。
注: python调⽤c++代码是通过pybind11实现。