Skip to content

Commit 848a2ca

Browse files
Merge pull request #1 from onnx/master
Merge base branch changes
2 parents 10e6ec5 + e853156 commit 848a2ca

File tree

226 files changed

+16483
-1760
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

226 files changed

+16483
-1760
lines changed

README.md

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,24 @@
22

33
| Build Type | OS | Python | Tensorflow | Onnx opset | Status |
44
| --- | --- | --- | --- | --- | --- |
5-
| Unit Test - Basic | Linux, MacOS<sup>\*</sup>, Windows<sup>\*</sup> | 3.6, 3.7 | 1.12-1.15, 2.1-2.2 | 7-12 | [![Build Status](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_apis/build/status/unit_test?branchName=master)](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_build/latest?definitionId=16&branchName=master) |
6-
| Unit Test - Full | Linux, MacOS, Windows | 3.6, 3.7 | 1.12-1.15, 2.1-2.2 | 7-12 | [![Build Status](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_apis/build/status/unit_test-matrix?branchName=master)](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_build/latest?definitionId=18&branchName=master) | |
5+
| Unit Test - Basic | Linux, MacOS<sup>\*</sup>, Windows<sup>\*</sup> | 3.6, 3.7, 3.8 | 1.12-1.15, 2.1-2.4 | 7-12 | [![Build Status](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_apis/build/status/unit_test?branchName=master)](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_build/latest?definitionId=16&branchName=master) |
6+
| Unit Test - Full | Linux, MacOS, Windows | 3.6, 3.7, 3.8 | 1.12-1.15, 2.1-2.3 | 7-12 | [![Build Status](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_apis/build/status/unit_test-matrix?branchName=master)](https://dev.azure.com/tensorflow-onnx/tensorflow-onnx/_build/latest?definitionId=18&branchName=master) | |
77

88
## Supported Versions
99

1010
### ONNX
1111

1212
tensorflow-onnx will use the ONNX version installed on your system and installs the latest ONNX version if none is found.
1313

14-
We support ONNX opset-6 to opset-12. By default we use opset-8 for the resulting ONNX graph since most runtimes will support opset-8.
14+
We support ONNX opset-6 to opset-12. By default we use opset-9 for the resulting ONNX graph since most runtimes will support opset-9.
1515
Support for future opsets add added as they are released.
1616

17-
If you want the graph to be generated with a specific opset, use ```--opset``` in the command line, for example ```--opset 11```.
17+
If you want the graph to be generated with a specific opset, use ```--opset``` in the command line, for example ```--opset 12```.
1818

1919
### TensorFlow
2020

2121
We support all ```tf-1.x graphs```. To keep our test matrix manageable we test tf2onnx running on top of ```tf-1.12 and up```. tf2onnx-1.5.4 was the last version that was tested all the way back to tf-1.4.
2222

23-
There is now ```experimental support for tf-2.x```.
24-
With the exception of LSTM unit tests, all unit tests are enabled and passing.
25-
Unit tests that we still need to fix are marked with ```@skip_tf2```.
26-
GRU/LSTM's are converting but not runnable due to type/shape inference issues at runtime (working on that one).
27-
All unit tests are running in eager mode. After execution we take the python function, make it a graph and convert it to ONNX.
2823
When running under tf-2.x tf2onnx will use the tensorflow V2 controlflow.
2924

3025
You can install tf2onnx on top of tf-1.x or tf-2.x.
@@ -139,11 +134,16 @@ python -m tf2onnx.convert
139134
[--outputs GRAPH_OUTPUS]
140135
[--inputs-as-nchw inputs_provided_as_nchw]
141136
[--opset OPSET]
137+
[--tag TAG]
138+
[--signature_def SIGNATURE_DEF]
139+
[--concrete_function CONCRETE_FUNCTION]
142140
[--target TARGET]
143141
[--custom-ops list-of-custom-ops]
144142
[--fold_const]
143+
[--large_model]
145144
[--continue_on_error]
146145
[--verbose]
146+
[--output_frozen_graph]
147147
```
148148

149149
### Parameters
@@ -176,13 +176,44 @@ By default we preserve the image format of inputs (`nchw` or `nhwc`) as given in
176176

177177
By default we use the opset 8 to generate the graph. By specifying ```--opset``` the user can override the default to generate a graph with the desired opset. For example ```--opset 5``` would create a onnx graph that uses only ops available in opset 5. Because older opsets have in most cases fewer ops, some models might not convert on a older opset.
178178

179+
#### --tag
180+
181+
Only valid with parameter `--saved_model`. Specifies the tag in the saved_model to be used. Typical value is 'serve'.
182+
183+
#### --signature_def
184+
185+
Only valid with parameter `--saved_model`. Specifies which signature to use within the specified --tag value. Typical value is 'serving_default'.
186+
187+
#### --concrete_function
188+
189+
(This is experimental, valid only for TF2.x models)
190+
191+
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 command `saved_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.
192+
193+
#### --large_model
194+
195+
(This is experimental, valid only for TF2.x models)
196+
197+
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 that exceed the 2 GB protobuf limit.
198+
199+
#### --output_frozen_graph
200+
201+
Saves the frozen tensorflow graph to file.
202+
203+
#### --custom-ops
204+
205+
If a model contains ops not recognized by onnx runtime, you can tag these ops with a custom op domain so that the
206+
runtime can still open the model. The format is a comma-separated map of tf op names to domains in the format
207+
OpName:domain. If only an op name is provided (no colon), the default domain of `ai.onnx.converters.tensorflow`
208+
will be used.
209+
179210
#### --target
180211

181212
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](https://github.com/onnx/tensorflow-onnx/wiki/target). If your model will be run on Windows ML, you should specify the appropriate target value.
182213

183214
#### --fold_const
184215

185-
When set, TensorFlow fold_constants transformation is applied before conversion. This benefits features including Transpose optimization (e.g. Transpose operations introduced during tf-graph-to-onnx-graph conversion will be removed), and RNN unit conversion (for example LSTM). Older TensorFlow version might run into issues with this option depending on the model.
216+
Deprecated. Constant folding is always enabled.
186217

187218
### <a name="summarize_graph"></a>Tool to get Graph Inputs & Outputs
188219

@@ -257,7 +288,8 @@ tf2onnx.tfonnx.process_tf_graph(tf_graph,
257288
opset=None, custom_op_handlers=None,
258289
custom_rewriter=None, extra_opset=None,
259290
shape_override=None, inputs_as_nchw=None,
260-
input_names=None, output_names=None):
291+
input_names=None, output_names=None,
292+
const_node_values=None):
261293
"""Convert tensorflow graph to onnx graph.
262294
Args:
263295
tf_graph: tensorflow graph
@@ -272,11 +304,12 @@ tf2onnx.tfonnx.process_tf_graph(tf_graph,
272304
inputs_as_nchw: transpose inputs in list from nchw to nchw
273305
input_names: list of input node names in graph, input name format as node_name:port_id
274306
output_names: list of output node names in graph, output name format as node_name:port_id
307+
const_node_values: an optional dict mapping node names to tensor values
275308
Return:
276309
onnx graph
277310
"""
278311
```
279-
For example in [examples/call_coverter_via_python.py]():
312+
For example in [examples/call_converter_via_python.py]():
280313
```
281314
import tensorflow as tf
282315
import tf2onnx

VERSION_NUMBER

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.7.0
1+
1.8.0

ci_build/azure_pipelines/pretrained_model_test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ jobs:
44
- template: 'templates/job_generator.yml'
55
parameters:
66
python_versions: ['3.7']
7-
tf_versions: ['1.15.2','2.1.0']
7+
tf_versions: ['1.15.2','2.3.0']
88
job:
99
steps:
1010
- template: 'pretrained_model_test.yml'
@@ -24,3 +24,4 @@ jobs:
2424
job:
2525
steps:
2626
- template: 'pretrained_model_test.yml'
27+

ci_build/azure_pipelines/pylint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ jobs:
1212
pip freeze
1313
pylint --rcfile=tools/pylintrc --ignore=version.py --disable=cyclic-import tf2onnx tests/*.py tools -j 0
1414
displayName: 'Pylint'
15+

ci_build/azure_pipelines/templates/job_generator.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ parameters:
55
python_versions: ['3.7']
66
tf_versions: ['']
77
onnx_versions: ['']
8-
onnx_opsets: ['12', '11', '10', '9', '8', '7']
9-
onnx_backends: {onnxruntime: ['1.3.0']}
8+
onnx_opsets: ['13', '12', '11', '10', '9', '8', '7']
9+
onnx_backends: {onnxruntime: ['1.6.0']}
1010
job: {}
1111
run_setup: 'True'
1212
report_coverage: 'False'

ci_build/azure_pipelines/templates/unit_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Run unit test
22

33
parameters:
4-
onnx_opsets: ['12', '11', '10', '9', '8', '7']
4+
onnx_opsets: ['13', '12', '11', '10', '9', '8', '7']
55

66
steps:
77
- ${{ each onnx_opset in parameters.onnx_opsets }}:

ci_build/azure_pipelines/unit_test.yml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,26 @@
33
stages:
44
- stage:
55
jobs:
6+
- template: 'templates/job_generator.yml'
7+
parameters:
8+
python_versions: ['3.8']
9+
tf_versions: ['2.4.0']
10+
onnx_opsets: ['']
11+
job:
12+
steps:
13+
- template: 'unit_test.yml'
14+
report_coverage: 'True'
15+
616
- template: 'templates/job_generator.yml'
717
parameters:
818
python_versions: ['3.7']
9-
tf_versions: ['1.14.0','1.15.2','2.1.0','2.2.0']
19+
tf_versions: ['1.14.0','1.15.2','2.2.0','2.3.0']
1020
onnx_opsets: ['']
1121
job:
1222
steps:
1323
- template: 'unit_test.yml'
1424
report_coverage: 'True'
15-
25+
1626
- template: 'templates/job_generator.yml'
1727
parameters:
1828
python_versions: [3.6']
@@ -34,3 +44,4 @@ stages:
3444
report_coverage: 'True'
3545

3646
- template: 'templates/combine_test_coverage.yml'
47+

examples/benchmark_tfmodel_ort.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
The following code compares the speed of tensorflow against onnxruntime
3+
with a model downloaded from Tensorflow Hub.
4+
"""
5+
import time
6+
import numpy
7+
from tqdm import tqdm
8+
import tensorflow_hub as hub
9+
import onnxruntime as ort
10+
11+
12+
def generate_random_images(shape=(100, 100), n=10):
13+
imgs = []
14+
for i in range(n):
15+
sh = (1,) + shape + (3,)
16+
img = numpy.clip(numpy.abs(numpy.random.randn(*sh)), 0, 1) * 255
17+
img = img.astype(numpy.float32)
18+
imgs.append(img)
19+
return imgs
20+
21+
22+
def measure_time(fct, imgs):
23+
results = []
24+
times = []
25+
for img in tqdm(imgs):
26+
begin = time.perf_counter()
27+
result = fct(img)
28+
end = time.perf_counter()
29+
results.append(result)
30+
times.append(end - begin)
31+
return results, times
32+
33+
34+
imgs = generate_random_images()
35+
36+
# Download model from https://tfhub.dev/captain-pool/esrgan-tf2/1
37+
# python -m tf2onnx.convert --saved-model esrgan --output "esrgan-tf2.onnx" --opset 12
38+
ort = ort.InferenceSession('esrgan-tf2.onnx')
39+
fct_ort = lambda img: ort.run(None, {'input_0:0': img})
40+
results_ort, duration_ort = measure_time(fct_ort, imgs)
41+
print(len(imgs), duration_ort)
42+
43+
model = hub.load("https://tfhub.dev/captain-pool/esrgan-tf2/1")
44+
results_tf, duration_tf = measure_time(model, imgs)
45+
print(len(imgs), duration_tf)
46+
47+
print("ratio ORT / TF", sum(duration_ort) / sum(duration_tf))
File renamed without changes.

examples/end2end_tfhub.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
This example retrieves a model from tensorflowhub.
3+
It is converted into ONNX. Predictions are compared to
4+
the predictions from tensorflow to check there is no
5+
discrepencies. Inferencing time is also compared between
6+
*onnxruntime*, *tensorflow* and *tensorflow.lite*.
7+
"""
8+
from onnxruntime import InferenceSession
9+
import os
10+
import sys
11+
import subprocess
12+
import timeit
13+
import numpy as np
14+
import tensorflow as tf
15+
from tensorflow import keras
16+
from tensorflow.keras import Input
17+
try:
18+
import tensorflow_hub as tfhub
19+
except ImportError:
20+
# no tensorflow_hub
21+
print("tensorflow_hub not installed.")
22+
sys.exit(0)
23+
24+
########################################
25+
# Downloads the model.
26+
hub_layer = tfhub.KerasLayer(
27+
"https://tfhub.dev/google/efficientnet/b0/classification/1")
28+
model = keras.Sequential()
29+
model.add(Input(shape=(224, 224, 3), dtype=tf.float32))
30+
model.add(hub_layer)
31+
print(model.summary())
32+
33+
########################################
34+
# Saves the model.
35+
if not os.path.exists("efficientnetb0clas"):
36+
os.mkdir("efficientnetb0clas")
37+
tf.keras.models.save_model(model, "efficientnetb0clas")
38+
39+
input_names = [n.name for n in model.inputs]
40+
output_names = [n.name for n in model.outputs]
41+
print('inputs:', input_names)
42+
print('outputs:', output_names)
43+
44+
########################################
45+
# Testing the model.
46+
input = np.random.randn(2, 224, 224, 3).astype(np.float32)
47+
expected = model.predict(input)
48+
print(expected)
49+
50+
########################################
51+
# Run the command line.
52+
proc = subprocess.run(
53+
'python -m tf2onnx.convert --saved-model efficientnetb0clas '
54+
'--output efficientnetb0clas.onnx --opset 12'.split(),
55+
capture_output=True)
56+
print(proc.returncode)
57+
print(proc.stdout.decode('ascii'))
58+
print(proc.stderr.decode('ascii'))
59+
60+
########################################
61+
# Runs onnxruntime.
62+
session = InferenceSession("efficientnetb0clas.onnx")
63+
got = session.run(None, {'input_1:0': input})
64+
print(got[0])
65+
66+
########################################
67+
# Measures the differences.
68+
print(np.abs(got[0] - expected).max())
69+
70+
########################################
71+
# Measures processing time.
72+
print('tf:', timeit.timeit('model.predict(input)',
73+
number=10, globals=globals()))
74+
print('ort:', timeit.timeit("session.run(None, {'input_1:0': input})",
75+
number=10, globals=globals()))

0 commit comments

Comments
 (0)