From 0dc498bde729508cdd7f0e9b8bb71a69e756a3de Mon Sep 17 00:00:00 2001 From: Joe Evans Date: Thu, 17 Dec 2020 21:58:17 +0000 Subject: [PATCH 1/5] Comment out useless backend test for onnx. --- ci/docker/runtime_functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/docker/runtime_functions.sh b/ci/docker/runtime_functions.sh index cabe853323fe..68499443e51c 100755 --- a/ci/docker/runtime_functions.sh +++ b/ci/docker/runtime_functions.sh @@ -1277,7 +1277,7 @@ integrationtest_ubuntu_cpu_onnx() { export PYTHONPATH=./python/ export MXNET_SUBGRAPH_VERBOSE=0 export DMLC_LOG_STACK_TRACE_DEPTH=10 - tests/python-pytest/onnx/backend_test.py + #tests/python-pytest/onnx/backend_test.py COV_ARG="--cov=./ --cov-report=xml --cov-append" pytest $COV_ARG --verbose tests/python-pytest/onnx/mxnet_export_test.py pytest $COV_ARG --verbose tests/python-pytest/onnx/test_models.py From d60367b1c55b581f04994f9be20a1a38d4778406 Mon Sep 17 00:00:00 2001 From: Joe Evans Date: Thu, 17 Dec 2020 21:59:23 +0000 Subject: [PATCH 2/5] Infer the output data type for each graph layer instead of assuming it's the same as input type. --- .../mxnet/contrib/onnx/mx2onnx/export_onnx.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py b/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py index bd2533646df3..b7f8a14896c3 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py +++ b/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py @@ -116,7 +116,7 @@ def split_params(sym, params): return arg_params, aux_params @staticmethod - def get_outputs(sym, params, in_shape, in_label): + def get_outputs(sym, params, in_shape, in_label, in_type): """ Infer output shapes and return dictionary of output name to shape :param :class:`~mxnet.symbol.Symbol` sym: symbol to perform infer shape on @@ -127,6 +127,7 @@ def get_outputs(sym, params, in_shape, in_label): :return: dictionary of output name to shape :rtype: dict of (str, tuple(int, ...)) """ + from onnx import mapping # remove any input listed in params from sym.list_inputs() and bind them to the input shapes provided # by user. Also remove in_label, which is the name of the label symbol that may have been used # as the label for loss during training. @@ -146,8 +147,16 @@ def get_outputs(sym, params, in_shape, in_label): out_names.append(name) assert len(out_shapes) == len(out_names) + + # infer output types + args = {n: mapping.TENSOR_TYPE_TO_NP_TYPE[in_type] for n in sym.list_inputs()} + arg_type, out_type, _ = sym.infer_type(**args) + out_types = [mapping.NP_TYPE_TO_TENSOR_TYPE[o(0).dtype] for o in out_type] + + assert len(out_types) == len(out_names) + # bind output shapes with output names - graph_outputs = {n: s for n, s in zip(out_names, out_shapes)} + graph_outputs = {n: { 'shape': s, 'dtype': d } for n, s, d in zip(out_names, out_shapes, out_types)} return graph_outputs @@ -210,7 +219,7 @@ def create_onnx_graph_proto(self, sym, params, in_shape, in_type, verbose=False, index_lookup = [] # Determine output shape - graph_outputs = MXNetGraph.get_outputs(sym, params, in_shape, output_label) + graph_outputs = MXNetGraph.get_outputs(sym, params, in_shape, output_label, in_type) graph_input_idx = 0 for idx, node in enumerate(mx_graph): @@ -273,8 +282,8 @@ def create_onnx_graph_proto(self, sym, params, in_shape, in_type, verbose=False, onnx_processed_outputs.append( make_tensor_value_info( name=nodename, - elem_type=in_type, - shape=graph_outputs[nodename] + elem_type=graph_outputs[nodename]['dtype'], + shape=graph_outputs[nodename]['shape'] ) ) if verbose: From 8cf8519b50291b04502f33f564293b25bf248c07 Mon Sep 17 00:00:00 2001 From: Joe Evans Date: Thu, 17 Dec 2020 21:59:45 +0000 Subject: [PATCH 3/5] Add unit test for cast onnx export operator. --- tests/python-pytest/onnx/test_operators.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/python-pytest/onnx/test_operators.py b/tests/python-pytest/onnx/test_operators.py index 83b74d73af5a..13b73a455076 100644 --- a/tests/python-pytest/onnx/test_operators.py +++ b/tests/python-pytest/onnx/test_operators.py @@ -253,3 +253,12 @@ def test_onnx_export_dropout(tmp_path, dtype, p): M = def_model('Dropout', p=p) x = mx.nd.array([[3,0.5,-0.5,2,7],[2,-0.4,7,3,0.2]], dtype=dtype) op_export_test('Dropout', M, [x], tmp_path) + + +@pytest.mark.parametrize('src_dtype', ['float16', 'float32', 'float64']) +@pytest.mark.parametrize('dst_dtype', ['bool', 'float16', 'float32', 'float64', 'int32', 'int64', 'int8', 'uint8']) +@pytest.mark.parametrize('shape', [(2,3), (4,5,6)]) +def test_onnx_export_cast(tmp_path, src_dtype, dst_dtype, shape): + M = def_model('Cast', dtype=dst_dtype) + x = mx.nd.ones(shape, dtype=src_dtype) + op_export_test('Cast', M, [x], tmp_path) From 69e7911b59412cfcc6b1e3477bd27178ee7fafda Mon Sep 17 00:00:00 2001 From: Joe Evans Date: Thu, 17 Dec 2020 23:25:54 +0000 Subject: [PATCH 4/5] Fix lint --- python/mxnet/contrib/onnx/mx2onnx/export_onnx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py b/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py index b7f8a14896c3..ba8ce0eb9e27 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py +++ b/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py @@ -156,7 +156,7 @@ def get_outputs(sym, params, in_shape, in_label, in_type): assert len(out_types) == len(out_names) # bind output shapes with output names - graph_outputs = {n: { 'shape': s, 'dtype': d } for n, s, d in zip(out_names, out_shapes, out_types)} + graph_outputs = {n: {'shape': s, 'dtype': d} for n, s, d in zip(out_names, out_shapes, out_types)} return graph_outputs From 18d898d4945f189470887a67378cad3bb3ec9d37 Mon Sep 17 00:00:00 2001 From: Joe Evans Date: Thu, 17 Dec 2020 23:27:25 +0000 Subject: [PATCH 5/5] Fix lint --- python/mxnet/contrib/onnx/mx2onnx/export_onnx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py b/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py index ba8ce0eb9e27..817a019e0c60 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py +++ b/python/mxnet/contrib/onnx/mx2onnx/export_onnx.py @@ -150,7 +150,7 @@ def get_outputs(sym, params, in_shape, in_label, in_type): # infer output types args = {n: mapping.TENSOR_TYPE_TO_NP_TYPE[in_type] for n in sym.list_inputs()} - arg_type, out_type, _ = sym.infer_type(**args) + _, out_type, _ = sym.infer_type(**args) out_types = [mapping.NP_TYPE_TO_TENSOR_TYPE[o(0).dtype] for o in out_type] assert len(out_types) == len(out_names)