Fix _mul_handler in TransposeOptimizer (#2088) (#2152)
Should not fuse Conv and Mul if the constant input of Mul is not with shape [N] or [1,..,1,N].
Signed-off-by: cosine cosine_chen@163.com
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802032778号
tf2onnx - Convert TensorFlow, Keras, Tensorflow.js and Tflite models to ONNX.
tf2onnx converts TensorFlow (tf-1.x or tf-2.x), keras, tensorflow.js and tflite models to ONNX via command line or python api.
Note: tensorflow.js support was just added. While we tested it with many tfjs models from tfhub, it should be considered experimental.
TensorFlow has many more ops than ONNX and occasionally mapping a model to ONNX creates issues.
You find a list of supported TensorFlow ops and their mapping to ONNX here.
The common issues we run into we try to document here Troubleshooting Guide.
Supported Versions
ONNX
tf2onnx will use the ONNX version installed on your system and installs the latest ONNX version if none is found.
We support and test ONNX opset-14 to opset-18. opset-6 to opset-13 should work but we don’t test them. By default we use
opset-15for the resulting ONNX graph.If you want the graph to be generated with a specific opset, use
--opsetin the command line, for example--opset 15.TensorFlow
We support
tf-1.x graphsandtf-2.x. To keep our test matrix manageable we test tf2onnx running on top oftf-1.13 or better.When running under tf-2.x tf2onnx will use the tensorflow V2 controlflow.
You can install tf2onnx on top of tf-1.x or tf-2.x.
Python
We support Python
3.7-3.10.Prerequisites
Install TensorFlow
If you don’t have TensorFlow installed already, install the desired TensorFlow build, for example:
pip install tensorflow(Optional) Install runtime
If you want to run tests, install a runtime that can run ONNX models. For example:
ONNX Runtime (available for Linux, Windows, and Mac):
pip install onnxruntimeInstallation
Install from pypi
pip install -U tf2onnxInstall latest from github
pip install git+https://github.com/onnx/tensorflow-onnxBuild and install latest from source (for development)
git clone https://github.com/onnx/tensorflow-onnxOnce dependencies are installed, from the tensorflow-onnx folder call:
python setup.py installor
python setup.py developtensorflow-onnx requires onnx-1.9 or better and will install/upgrade onnx if needed.
To create a wheel for distribution:
python setup.py bdist_wheelGetting started
To get started with
tensorflow-onnx, run thet2onnx.convertcommand, providing:saved modelformat)python -m tf2onnx.convert --saved-model tensorflow-model-path --output model.onnxThe above command uses a default of
15for the ONNX opset. If you need a newer opset, or want to limit your model to use an older opset then you can provide the--opsetargument to the command. If you are unsure about which opset to use, refer to the ONNX operator documentation.python -m tf2onnx.convert --saved-model tensorflow-model-path --opset 18 --output model.onnxIf your TensorFlow model is in a format other than
saved model, then you need to provide the inputs and outputs of the model graph.For
checkpointformat:python -m tf2onnx.convert --checkpoint tensorflow-model-meta-file-path --output model.onnx --inputs input0:0,input1:0 --outputs output0:0For
graphdefformat:python -m tf2onnx.convert --graphdef tensorflow-model-graphdef-file --output model.onnx --inputs input0:0,input1:0 --outputs output0:0If your model is in
checkpointorgraphdefformat and you do not know the input and output nodes of the model, you can use the summarize_graph TensorFlow utility. Thesummarize_graphtool does need to be downloaded and built from source. If you have the option of going to your model provider and obtaining the model insaved modelformat, then we recommend doing so.You find an end-to-end tutorial for ssd-mobilenet here
We recently added support for tflite. You convert
tflitemodels via command line, for example:python -m tf2onnx.convert --opset 16 --tflite tflite--file --output model.onnxCLI reference
Parameters
–saved-model
TensorFlow model as saved_model. We expect the path to the saved_model directory.
–checkpoint
TensorFlow model as checkpoint. We expect the path to the .meta file.
–input or –graphdef
TensorFlow model as graphdef file.
–tfjs
Convert a tensorflow.js model by providing a path to the .tfjs file. Inputs/outputs do not need to be specified.
–tflite
Convert a tflite model by providing a path to the .tflite file. Inputs/outputs do not need to be specified.
–output
The target onnx file path.
–inputs, –outputs
TensorFlow model’s input/output names, which can be found with summarize graph tool. Those names typically end with
:0, for example--inputs input0:0,input1:0. Inputs and outputs are not needed for models in saved-model format. Some models specify placeholders with unknown ranks and dims which can not be mapped to onnx. In those cases one can add the shape after the input name inside[], for example--inputs X:0[1,28,28,3]. Use -1 to indicate unknown dimensions.–inputs-as-nchw
By default we preserve the image format of inputs (
nchwornhwc) as given in the TensorFlow model. If your hosts (for example windows) native format nchw and the model is written for nhwc,--inputs-as-nchwtensorflow-onnx will transpose the input. Doing so is convenient for the application and the converter in many cases can optimize the transpose away. For example--inputs input0:0,input1:0 --inputs-as-nchw input0:0assumes that images are passed intoinput0:0as nchw while the TensorFlow model given uses nhwc.–outputs-as-nchw
Similar usage with
--inputs-as-nchw. By default we preserve the format of outputs (nchwornhwc) as shown in the TensorFlow model. If your hosts native format nchw and the model is written for nhwc,--outputs-as-nchwtensorflow-onnx will transpose the output and optimize the transpose away. For example--outputs output0:0,output1:0 --outputs-as-nchw output0:0will change theoutput0:0as nchw while the TensorFlow model given uses nhwc.–ignore_default, –use_default
ONNX requires default values for graph inputs to be constant, while Tensorflow’s PlaceholderWithDefault op accepts computed defaults. To convert such models, pass a comma-separated list of node names to the ignore_default and/or use_default flags. PlaceholderWithDefault nodes with matching names will be replaced with Placeholder or Identity ops, respectively.
–opset
By default we use the opset 15 to generate the graph. By specifying
--opsetthe user can override the default to generate a graph with the desired opset. For example--opset 17would create a onnx graph that uses only ops available in opset 17. Because older opsets have in most cases fewer ops, some models might not convert on an older opset.–dequantize
(This is experimental, only supported for tflite)
Produces a float32 model from a quantized tflite model. Detects ReLU and ReLU6 ops from quantization bounds.
–tag
Only valid with parameter
--saved_model. Specifies the tag in the saved_model to be used. Typical value is ‘serve’.–signature_def
Only valid with parameter
--saved_model. Specifies which signature to use within the specified –tag value. Typical value is ‘serving_default’.–concrete_function
(This is experimental, valid only for TF2.x models)
Only valid with parameter
--saved_model. If a model contains a list of concrete functions, under the function name__call__(as can be viewed using the commandsaved_model_cli show --all), this parameter is a 0-based integer specifying which function in that list should be converted. This parameter takes priority over--signature_def, which will be ignored.–target
Some models require special handling to run on some runtimes. In particular, the model may use unsupported data types. Workarounds are activated with
--target TARGET. Currently supported values are listed on this wiki. If your model will be run on Windows ML, you should specify the appropriate target value.–extra_opset
If you want to convert a TF model using an existing custom op, this can specify the correspongding domain and version. The format is a comma-separated map of domain and version, for example:
ai.onnx.contrib:1.–custom-ops
If a model contains ops not recognized by onnx runtime, you can tag these ops with a custom op domain so that the runtime can still open the model. The format is a comma-separated map of tf op names to domains in the format OpName:domain. If only an op name is provided (no colon), the default domain of
ai.onnx.converters.tensorflowwill be used.–load_op_libraries
Load the comma-separated list of tensorflow plugin/op libraries before conversion.
–large_model
(Can be used only for TF2.x models)
Only valid with parameter
--saved_model. When set, creates a zip file containing the ONNX protobuf model and large tensor values stored externally. This allows for converting models whose size exceeds the 2 GB.–continue_on_error
Continue to run conversion on error, ignore graph cycles so it can report all missing ops and errors.
–verbose
Verbose detailed output for diagnostic purposes.
–output_frozen_graph
Save the frozen and optimized tensorflow graph to a file for debug.
Tool to get Graph Inputs & Outputs
To find the inputs and outputs for the TensorFlow graph the model developer will know or you can consult TensorFlow’s summarize_graph tool, for example:
Testing
There are 2 types of tests.
Unit test
Validate pre-trained TensorFlow models
run_pretrained_models.pywill run the TensorFlow model, captures the TensorFlow output and runs the same test against the specified ONNX backend after converting the model.If the option
--perf csv-fileis specified, we’ll capture the timing for inference of tensorflow and onnx runtime and write the result into the given csv file.You call it for example with:
Tool to save pre-trained model
We provide an utility to save pre-trained model along with its config. Put
save_pretrained_model(sess, outputs, feed_inputs, save_dir, model_name)in your last testing epoch and the pre-trained model and config will be saved undersave_dir/to_onnx. Please refer to the example in tools/save_pretrained_model.py for more information. Note the minimum required Tensorflow version is r1.6.Python API Reference
With tf2onnx-1.8.4 we updated our API. Our old API still works - you find the documentation here.
from_keras (tf-2.0 and newer)
See tutorials/keras-resnet50.ipynb for an end to end example.
from_function (tf-2.0 and newer)
from_graph_def
from_tflite
Creating custom op mappings from python
For complex custom ops that require graph rewrites or input / attribute rewrites using the python interface to insert a custom op will be the easiest way to accomplish the task. A dictionary of name->custom_op_handler can be passed to tf2onnx.tfonnx.process_tf_graph. If the op name is found in the graph the handler will have access to all internal structures and can rewrite that is needed. For example examples/custom_op_via_python.py:
How tf2onnx works
The converter needs to take care of a few things:
Step 1 - start with a frozen graph
tf2onnx starts with a frozen graph. This is because of item 3 above.
Step 2 - 1:1 conversion of the protobuf from tensorflow to onnx
tf2onnx first does a simple conversion from the TensorFlow protobuf format to the ONNX protobuf format without looking at individual ops. We do this so we can use the ONNX graph as internal representation and write helper functions around it. The code that does the conversion is in tensorflow_to_onnx(). tensorflow_to_onnx() will return the ONNX graph and a dictionary with shape information from TensorFlow. The shape information is helpful in some cases when processing individual ops. The ONNX graph is wrapped in a Graph object and nodes in the graph are wrapped in a Node object to allow easier graph manipulations on the graph. All code that deals with nodes and graphs is in graph.py.
Step 3 - rewrite subgraphs
In the next step we apply graph matching code on the graph to re-write subgraphs for ops like transpose and lstm. For an example looks at rewrite_transpose().
Step 4 - process individual ops
In the fourth step we look at individual ops that need attention. The dictionary _OPS_MAPPING will map tensorflow op types to a method that is used to process the op. The simplest case is direct_op() where the op can be taken as is. Whenever possible we try to group ops into common processing, for example all ops that require dealing with broadcasting are mapped to broadcast_op(). For an op that composes the tensorflow op from multiple onnx ops, see relu6_op().
Step 5 - optimize the functional ONNX graph
We than try to optimize the functional ONNX graph. For example we remove ops that are not needed, remove transposes as much as possible, de-dupe constants, fuse ops whenever possible, …
Step 6 - final processing
Once all ops are converted and optimize, we need to do a topological sort since ONNX requires it. process_tf_graph() is the method that takes care of all above steps.
Extending tf2onnx
If you like to contribute and add new conversions to tf2onnx, the process is something like:
License
Apache License v2.0