from IPython.display import Image
ONNX models with Python
This is the code from the onnx documentation.
This notebooks talks about manipulating ONNX models with the Python API.
Creating Model
Linear expression: Y = A * X + B
from onnx import TensorProto
from onnx.helper import (
make_model, make_node, make_graph, make_tensor_value_info,
tensor_dtype_to_np_dtype
)from onnx.checker import check_model
Declearing Variables
We use the make_tensor_value_info
to declare variables.
= make_tensor_value_info(
X ="X", elem_type=TensorProto.FLOAT, shape=[None, None]
name
)
= make_tensor_value_info(
A ="A", elem_type=TensorProto.FLOAT, shape=[None, None]
name
)
= make_tensor_value_info(
B ="B", elem_type=TensorProto.FLOAT, shape=[None, None]
name
)
= make_tensor_value_info(
Y ="Y", elem_type=TensorProto.FLOAT, shape=[None]
name )
Declaring Operators
Operats are the “nodes” in the computation graph of a neural network.
We use the make_node
function to declare nodes.
= make_node(
node_1 ='MatMul', inputs=['X', 'A'], outputs=['XA'],
op_type
)
= make_node(
node_2 ='Add', inputs=['XA', 'B'], outputs=['Y'],
op_type )
Declaring the Graph
We can construct the computational graph with the make_graph
function.
= make_graph(
graph =[node_1, node_2],
nodes="linear regression",
name=[X, A, B],
inputs=[Y],
outputs )
Creating a model
We can convert the computation Graph to ONNX model via make_model
function.
We can use check_model
to ensure our result being legitimate.
= make_model(graph)
model
check_model(model)
Save the Model
We serialise the model with the SerializePartialToString
method.
with open("model_lr.onnx", "wb") as f:
f.write(model.SerializePartialToString())
We can visualise the model with tools such as Netron, yielding an image like this,
"model_lr.png", width=150) Image(
Parsing a Model
Loading the model
We can use the load
function to load a model as the ONNX representation, onnx.onnx_ml_pb2.ModelProto
.
from onnx import load
= load("./model_lr.onnx")
model type(model)
onnx.onnx_ml_pb2.ModelProto
Inspecting the IO details
The following code shows the way to print inputs and outputs of a model.
Notice the helpful fucntions
onnx.helper.tensor_dtype_to_np_dtype
.- our own
get_tensor_shape
def get_tensor_shape(tensor):
= tensor.type.tensor_type.shape
shape return tuple(getattr(d, 'dim_value', 0) for d in shape.dim)
for obj in model.graph.input:
= obj.name
name = tensor_dtype_to_np_dtype(
dtype type.tensor_type.elem_type
obj.
)= get_tensor_shape(obj)
shape print("Input tensor:", name, shape, dtype)
for obj in model.graph.output:
= obj.name
name = tensor_dtype_to_np_dtype(
dtype type.tensor_type.elem_type
obj.
)= get_tensor_shape(obj)
shape print("Output tensor:", name, shape, dtype)
Input tensor: X (0, 0) float32
Input tensor: A (0, 0) float32
Input tensor: B (0, 0) float32
Output tensor: Y (0,) float32
Inspecting Operators
The following code shows how to extract information of computational nodes.
By doing so, we clearly see the flow of computation in the Graph.
for node in model.graph.node:
= node.name
name = node.op_type
op = node.input
tensor_in = node.output
tensor_out print(f"Node {name}:", tensor_in, "->", op, "->", tensor_out)
Node : ['X', 'A'] -> MatMul -> ['XA']
Node : ['XA', 'B'] -> Add -> ['Y']