ONNX作为一个方便在各大主流深度学习框架中迁移转换的中间表达式,在工业界使用越加频繁。关于ONNXgithub上有部分相关文档参考链接https://github.com/onnx/onnx,对相关接口的详细说明尚且不够。本文针对onnx的前向过程说明下常见的调试操作。
一、自建网络
ONNX提供onnx.helper接口,方便搭建节点以及网络,具体demo如下:
import onnx
from onnx import helper
from onnx import AttributeProto, TensorProto, GraphProto
# Create inputs (ValueInfoProto)
X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [1, 2])
# Create initializer with static pads and constant value
pads = helper.make_tensor('pads', TensorProto.INT64, [4], [0, 1, 0, 1])
value = helper.make_tensor('pad_value', TensorProto.FLOAT, [1], [1.5])
# Create one output (ValueInfoProto)
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1, 4])
# Create a node (NodeProto)
node_def = helper.make_node(
'Pad', # node name
['X', 'pads', 'pad_value'], # inputs
['Y'], # outputs
mode='constant' # attributes
)
# Create the graph (GraphProto)
graph_def = helper.make_graph(
[node_def], # nodes
'test-model', # graph name
[X], # graph inputs
[Y], # graph outputs
[pads, value] # initializers
)
# Create the model (ModelProto)
model_def = helper.make_model(graph_def, producer_name='onnx-example')
print('The model is:\n{}'.format(model_def))
onnx.checker.check_model(model_def)
print('The model is checked!')
二、前向Inference使用
关于onnx的前向推理,onnx使用了onnxruntime计算引擎,onnxruntime是一个以性能为中心的完整的评分引擎,详细介绍可参考链接:https://github.com/microsoft/onnxruntime
onnxruntime接口使用脚本如下demo:run()接口第一个参数可设置为None,此时将保存所有的输出。
import numpy as np
import onnx
import onnxruntime as rt
#create input data
input_data = np.ones((1, 3, 299, 299), dtype=np.float32)
#create runtime session
sess = rt.InferenceSession("inception_v3.onnx")
# get output name
input_name = sess.get_inputs()[0].name
print("input name", input_name)
output_name= sess.get_outputs()[0].name
print("output name", output_name)
output_shape = sess.get_outputs()[0].shape
print("output shape", output_shape)
#forward model
res = sess.run([output_name], {input_name: input_data})
out = np.array(res)
print(out)
三、中间层结果输出
ONNX模型主要保存了五个结构,通过load网络模型,打印graph结构,可以清晰的查看存储的内容。
node:网络节点列表,
initializer:所有常量输入数据列表
,input:网络中存在的feature map输入列表,
output:整个模型的输出列表。
ONNX支持对原有模型的修改,使用graph.node.remove可以删除中间层节点,graph.node.insert可以增加一个中间层,最后希望获得中间层结果只需要将中间层节点加入output列表。具体脚本如下:
import onnx
import numpy as np
import onnx.helper as helper
#load model
onnx_model = onnx.load("inception_v3.onnx")
graph = onnx_model.graph
#print graph info
print(graph)
print(graph.output)
#print intermediate node info
print(graph.node[37])
print(graph.node[37].input[0])
#create value_info for the output list
prob_info = helper.make_tensor_value_info('603', onnx.TensorProto.FLOAT, [1, 192, 35, 35])
graph.output.insert(0, prob_info)
print("after change:\n")
print(graph.output)