microsoft/onnxruntime-extensions

Public

mirrored from https://github.com/microsoft/onnxruntime-extensionsAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
natke-patch-1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

onnxruntime_extensions/tools/pre_post_processing/utils.py

139lines · modeblame

1cab9711Scott McKay3 years ago1# Copyright (c) Microsoft Corporation. All rights reserved.
2# Licensed under the MIT License.
3
4import onnx
5
6from dataclasses import dataclass
440a3ca9Scott McKay3 years ago7from typing import List, Union
1cab9711Scott McKay3 years ago8
9
10def create_named_value(name: str, data_type: int, shape: List[Union[str, int]]):
11"""
12Helper to create a new model input.
13
14Args:
15name: Name for input. Must not already be in use in the model being updated.
16data_type: onnx.TensorProto data type. e.g. onnx.TensorProto.FLOAT, onnx.TensorProto.UINT8
17shape: Input shape. Use int for dimensions with known values and strings for symbolic dimensions.
18e.g. ['batch_size', 256, 256] would be a rank 3 tensor with a symbolic first dimension named 'batch_size'
19
20
21Returns:
22An onnx.ValueInfoProto that can be used as a new model input.
23"""
b375cb57JiCheng3 years ago24tensor_type = onnx.helper.make_tensor_type_proto(
25elem_type=data_type, shape=shape)
1cab9711Scott McKay3 years ago26return onnx.helper.make_value_info(name, tensor_type)
27
28
29# Create an onnx checker context that includes the ort-ext domain so that custom ops don't cause failure
cd5ea11aScott McKay3 years ago30def create_custom_op_checker_context(onnx_opset: int):
1cab9711Scott McKay3 years ago31"""
32Create an ONNX checker context that includes the ort-extensions custom op domains so that custom ops don't
33cause failure when running onnx.checker.check_graph.
34
cd5ea11aScott McKay3 years ago35Args:
36onnx_opset: ONNX opset to use in the checker context.
37
38Returns:
39ONNX checker context.
1cab9711Scott McKay3 years ago40"""
41context = onnx.checker.C.CheckerContext()
42context.ir_version = onnx.checker.DEFAULT_CONTEXT.ir_version
cd5ea11aScott McKay3 years ago43context.opset_imports = {"": onnx_opset, "com.microsoft.extensions": 1}
1cab9711Scott McKay3 years ago44
45return context
46
47
48# The ONNX graph parser has it's own map of names just to be special
49# https://github.com/onnx/onnx/blob/604af9cb28f63a6b9924237dcb91530649233db9/onnx/defs/parser.h#L72
50TENSOR_TYPE_TO_ONNX_TYPE = {
51int(onnx.TensorProto.FLOAT): "float",
52int(onnx.TensorProto.UINT8): "uint8",
53int(onnx.TensorProto.INT8): "int8",
54int(onnx.TensorProto.UINT16): "uint16",
55int(onnx.TensorProto.INT16): "int16",
56int(onnx.TensorProto.INT32): "int32",
57int(onnx.TensorProto.INT64): "int64",
58int(onnx.TensorProto.STRING): "string",
59int(onnx.TensorProto.BOOL): "bool",
60int(onnx.TensorProto.FLOAT16): "float16",
61int(onnx.TensorProto.DOUBLE): "double",
62int(onnx.TensorProto.UINT32): "uint32",
63int(onnx.TensorProto.UINT64): "uint64",
64int(onnx.TensorProto.COMPLEX64): "complex64",
65int(onnx.TensorProto.COMPLEX128): "complex128",
66int(onnx.TensorProto.BFLOAT16): "bfloat16",
67}
68
69
70@dataclass
71class IoMapEntry:
72"""Entry to map the output index from a producer step to the input index of a consumer step."""
73
74# optional producer
75# Uses Step if provided.
76# If a str with a previous Step name is provided the PrePostProcessor will find the relevant Step
77# If neither are provided the producer is inferred to be the immediately previous Step in the pipeline
78producer: Union["Step", str] = None
79# output index from the producer step
80producer_idx: int = 0
81# input index of the consumer step
82consumer_idx: int = 0
83
84
b375cb57JiCheng3 years ago85@dataclass
86class IOEntryValuePreserver:
87"""
88used to allow an output value to have multiple consumers,
89which is only possible when IoMapEntry is used to create those additional connections.
90
91Generally, a connection consumes an output and an input, then the output is removed from the graph.
92This class enabled one-to-many connections by making the other consumers share the same output.
93
94How this class works:
951. when the IoMapEntry is created, this class will be created simultaneously.
962. It records the producer and consumer steps, and the output index of the producer step.
97when producer step is running, this IOEntryValuePreserver will be activated and start to preserve the output.
983. when graph merge happens, this class will check if the output is still in the graph, if not,
99it will add the output
1004. when consumer step is running, this class will be deactivated and remove output from preserved_list.
101"""
102
103producer: Union["Step", str] = None
104consumer: Union["Step", str] = None
105# output index from the producer step
106producer_idx: int = 0
107is_active: bool = False
108output: str = None
109
110
1cab9711Scott McKay3 years ago111def sanitize_output_names(graph: onnx.GraphProto):
112"""
113Convert any usage of invalid characters like '/' and ';' in value names to '_'
114This is common in models exported from TensorFlow [Lite].
115
116ONNX parse_graph does not allow for that in a value name, and technically it's a violation of the ONNX spec as per
117https://github.com/onnx/onnx/blob/main/docs/IR.md#names-within-a-graph
118
119We do this for the original graph outputs only. The invalid naming has not been seen in model inputs, and we can
120leave the internals of the graph intact to minimize changes.
121
122Args:
123graph: Graph to check and update any invalid names
124"""
125
126bad_output_names = [o.name for o in graph.output if "/" in o.name or ";" in o.name]
127if not bad_output_names:
128return graph
129
130renames = {}
131for n in bad_output_names:
132renames[n] = n.replace("/", "_").replace(";", "_")
133
134for o in graph.output:
135if o.name in bad_output_names:
136# Add Identity node to rename the output, and update the name in graph.output
137rename = onnx.helper.make_node("Identity", [o.name], [renames[o.name]], f"Rename {o.name}")
138graph.node.append(rename)
139o.name = renames[o.name]