From 0c9c10d67e259333dd0d396acd77ac76a429ef01 Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Fri, 8 Jan 2021 10:44:19 -0800 Subject: [PATCH 1/8] convert adaptiveAveragePooling2D --- .../contrib/onnx/mx2onnx/_op_translations.py | 18 ++++++++++++++++++ tests/python-pytest/onnx/test_operators.py | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index 1c50abe7dc90..c1c403f3b1ce 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -3023,3 +3023,21 @@ def convert_contrib_box_decode(node, **kwargs): ] return nodes + +@mx_op.register("_contrib_AdaptiveAvgPooling2D") +def convert_contrib_AdaptiveAvgPooling2D(node, **kwargs): + """Map MXNet's _contrib_BilinearResize2D operator attributes to onnx's operator. + """ + from onnx.helper import make_node + name, input_nodes, attrs = get_inputs(node, kwargs) + + output_size = attrs.get('output_size', '1') + output_size = convert_string_to_list(output_size) + + if len(output_size) <= 2: + if output_size[0] != 1 or (len(output_size) == 2 and output_size[1] != 1): + raise NotImplementedError("_contrib_AdaptiveAvgPooling2D operator with output_size != 1 not yet implemented.") + nodes = [ + make_node("GlobalAveragePool", [input_nodes[0]], [name]) + ] + return nodes diff --git a/tests/python-pytest/onnx/test_operators.py b/tests/python-pytest/onnx/test_operators.py index 4882321e39a6..0363dbcf2fa8 100644 --- a/tests/python-pytest/onnx/test_operators.py +++ b/tests/python-pytest/onnx/test_operators.py @@ -421,3 +421,15 @@ def test_onnx_export_contrib_box_decode(tmp_path, dtype, fmt, clip): op_export_test('contrib_box_decode', M1, [data, anchors], tmp_path) M2 = def_model('contrib.box_decode', format=fmt, clip=clip, std0=0.3, std1=1.4, std2=0.5, std3=1.6) op_export_test('contrib_box_decode', M1, [data, anchors], tmp_path) + +@pytest.mark.parametrize('dtype', ['float16', 'float32']) +def test_onnx_export_contrib_AdaptiveAvgPooling2D(tmp_path, dtype): + x = mx.nd.random.uniform(0, 1, (1, 2, 3, 4), dtype=dtype) + M1 = def_model('contrib.AdaptiveAvgPooling2D') + op_export_test('contrib_AdaptiveAvgPooling2D', M1, [x], tmp_path) + M2 = def_model('contrib.AdaptiveAvgPooling2D', output_size=1) + op_export_test('contrib_AdaptiveAvgPooling2D', M2, [x], tmp_path) + M3 = def_model('contrib.AdaptiveAvgPooling2D', output_size=[1]) + op_export_test('contrib_AdaptiveAvgPooling2D', M3, [x], tmp_path) + M4 = def_model('contrib.AdaptiveAvgPooling2D', output_size=[1,1]) + op_export_test('contrib_AdaptiveAvgPooling2D', M4, [x], tmp_path) From a37dc331a0b9e1aa5e0f09ec41ddd18d0789e288 Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Fri, 8 Jan 2021 13:04:44 -0800 Subject: [PATCH 2/8] fix line too long --- python/mxnet/contrib/onnx/mx2onnx/_op_translations.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index c1c403f3b1ce..360d2e0e3541 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -3036,7 +3036,8 @@ def convert_contrib_AdaptiveAvgPooling2D(node, **kwargs): if len(output_size) <= 2: if output_size[0] != 1 or (len(output_size) == 2 and output_size[1] != 1): - raise NotImplementedError("_contrib_AdaptiveAvgPooling2D operator with output_size != 1 not yet implemented.") + raise NotImplementedError("_contrib_AdaptiveAvgPooling2D operator with output_size != 1 \ + not yet implemented.") nodes = [ make_node("GlobalAveragePool", [input_nodes[0]], [name]) ] From 0f3a62d50cd9409145d9b6573afedb78bdc0ae5b Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Fri, 8 Jan 2021 15:19:16 -0800 Subject: [PATCH 3/8] add name to last node --- python/mxnet/contrib/onnx/mx2onnx/_op_translations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index 360d2e0e3541..b8e6951d3fed 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -3039,6 +3039,6 @@ def convert_contrib_AdaptiveAvgPooling2D(node, **kwargs): raise NotImplementedError("_contrib_AdaptiveAvgPooling2D operator with output_size != 1 \ not yet implemented.") nodes = [ - make_node("GlobalAveragePool", [input_nodes[0]], [name]) + make_node("GlobalAveragePool", [input_nodes[0]], [name], name=name) ] return nodes From f40b1a5eec1fbc0a6abb275fb74780be5385aee7 Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Thu, 14 Jan 2021 14:39:58 -0800 Subject: [PATCH 4/8] support temperature for softmax --- .../contrib/onnx/mx2onnx/_op_translations.py | 16 +++++++++++----- tests/python-pytest/onnx/test_operators.py | 11 ++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index b8e6951d3fed..7807dbff11f5 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -859,15 +859,21 @@ def convert_softmax(node, **kwargs): name, input_nodes, attrs = get_inputs(node, kwargs) axis = int(attrs.get("axis", -1)) - temperature = attrs.get("temperature", None) - if temperature and float(temperature) != 1.0: - raise NotImplementedError("Temperature is not supported for now.") - use_length = attrs.get("use_length", None) + temperature = str(attrs.get("temperature", 'None')) + if temperature == 'None': + temperature = 1. + else: + temperature = float(temperature) + + use_length = str(attrs.get("use_length", 'None')) input_type = kwargs["in_type"] + dtype = onnx.mapping.TENSOR_TYPE_TO_NP_TYPE[input_type] data = input_nodes[0] nodes = [ - make_node("Exp", [data], [name+"_exp_out"]), + create_tensor([temperature], name+"_tmp", kwargs["initializer"], dtype=dtype), + make_node("Div", [data, name+"_tmp"], [name+'_data']), + make_node("Exp", [name+'_data'], [name+"_exp_out"]), make_node("ReduceSum", [name+"_exp_out"], [name+"_rsum_out"], axes=[axis], keepdims=1) ] if len(input_nodes) == 1: diff --git a/tests/python-pytest/onnx/test_operators.py b/tests/python-pytest/onnx/test_operators.py index 0363dbcf2fa8..946a19b2a3ef 100644 --- a/tests/python-pytest/onnx/test_operators.py +++ b/tests/python-pytest/onnx/test_operators.py @@ -338,17 +338,18 @@ def test_onnx_export_cast(tmp_path, src_dtype, dst_dtype, shape): @pytest.mark.parametrize('dtype', ['float16', 'float32']) -def test_onnx_export_softmax(tmp_path, dtype): +@pytest.mark.parametrize('temperature', [.1, 1., 10.]) +def test_onnx_export_softmax(tmp_path, dtype, temperature): x = mx.nd.random.uniform(0, 1, (2, 3, 4), dtype=dtype) - M1 = def_model('softmax') + M1 = def_model('softmax', temperature=temperature) op_export_test('softmax_1', M1, [x], tmp_path) - M2 = def_model('softmax', use_length=True, axis=0) + M2 = def_model('softmax', use_length=True, axis=0, temperature=temperature) l2 = mx.nd.array([[2,0,2,1],[1,1,2,1], [0,0,0,1]], dtype=int) op_export_test('softmax_2', M2, [x, l2], tmp_path) - M3 = def_model('softmax', use_length=True, axis=-1) + M3 = def_model('softmax', use_length=True, axis=-1, temperature=temperature) l3 = mx.nd.array([[2,0,4],[0,0,0]], dtype=int) op_export_test('softmax_3', M3, [x, l3], tmp_path) - M4 = def_model('softmax', use_length=True, axis=1) + M4 = def_model('softmax', use_length=True, axis=1, temperature=temperature) l4 = mx.nd.array([[2,0,3,1],[0,1,0,0]], dtype=int) op_export_test('softmax_4', M4, [x, l4], tmp_path) From c30e31dc97d5567c646758e905c302d3dcada074 Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Thu, 14 Jan 2021 16:36:09 -0800 Subject: [PATCH 5/8] handle fp16 in create_tensor --- python/mxnet/contrib/onnx/mx2onnx/_op_translations.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index 7807dbff11f5..0e2ae65e0880 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -186,6 +186,8 @@ def create_tensor(shape_list, shape_name, initializer, dtype='int64'): data_type = onnx.mapping.NP_TYPE_TO_TENSOR_TYPE[shape_np.dtype] dims = np.shape(shape_np) tensor_node = onnx.helper.make_tensor_value_info(shape_name, data_type, dims) + if dtype==np.float16: + shape_list = shape_np.view(dtype=np.uint16).flatten().tolist() initializer.append( onnx.helper.make_tensor( name=shape_name, From 0f450ae91be8a50f02bdf545dfe2db79343209b1 Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Thu, 14 Jan 2021 17:09:15 -0800 Subject: [PATCH 6/8] fallback to nbformat5.0.8 --- docs/python_docs/environment.yml | 1 + python/mxnet/contrib/onnx/mx2onnx/_op_translations.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/python_docs/environment.yml b/docs/python_docs/environment.yml index 7856a076889b..95c14f6c42f8 100644 --- a/docs/python_docs/environment.yml +++ b/docs/python_docs/environment.yml @@ -27,6 +27,7 @@ dependencies: - matplotlib - notebook - pip: + - nbformat==5.0.8 - nbconvert==5.6.1 - nbsphinx==0.4.3 - recommonmark==0.6.0 diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index 0e2ae65e0880..1a5d3ed1eb79 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -186,7 +186,7 @@ def create_tensor(shape_list, shape_name, initializer, dtype='int64'): data_type = onnx.mapping.NP_TYPE_TO_TENSOR_TYPE[shape_np.dtype] dims = np.shape(shape_np) tensor_node = onnx.helper.make_tensor_value_info(shape_name, data_type, dims) - if dtype==np.float16: + if dtype == np.float16: shape_list = shape_np.view(dtype=np.uint16).flatten().tolist() initializer.append( onnx.helper.make_tensor( From 96cee2e96bea423f251d2e457c8600d274aa86b6 Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Fri, 15 Jan 2021 10:58:20 -0800 Subject: [PATCH 7/8] revert nbformat --- docs/python_docs/environment.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/python_docs/environment.yml b/docs/python_docs/environment.yml index 95c14f6c42f8..7856a076889b 100644 --- a/docs/python_docs/environment.yml +++ b/docs/python_docs/environment.yml @@ -27,7 +27,6 @@ dependencies: - matplotlib - notebook - pip: - - nbformat==5.0.8 - nbconvert==5.6.1 - nbsphinx==0.4.3 - recommonmark==0.6.0 From a1b9f37ae4326acf36e911f4270e0648d690950f Mon Sep 17 00:00:00 2001 From: Wei Chu Date: Fri, 15 Jan 2021 19:28:44 -0800 Subject: [PATCH 8/8] test softmax with default temp --- tests/python-pytest/onnx/test_operators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python-pytest/onnx/test_operators.py b/tests/python-pytest/onnx/test_operators.py index 946a19b2a3ef..66c0454c8d0a 100644 --- a/tests/python-pytest/onnx/test_operators.py +++ b/tests/python-pytest/onnx/test_operators.py @@ -341,7 +341,7 @@ def test_onnx_export_cast(tmp_path, src_dtype, dst_dtype, shape): @pytest.mark.parametrize('temperature', [.1, 1., 10.]) def test_onnx_export_softmax(tmp_path, dtype, temperature): x = mx.nd.random.uniform(0, 1, (2, 3, 4), dtype=dtype) - M1 = def_model('softmax', temperature=temperature) + M1 = def_model('softmax') op_export_test('softmax_1', M1, [x], tmp_path) M2 = def_model('softmax', use_length=True, axis=0, temperature=temperature) l2 = mx.nd.array([[2,0,2,1],[1,1,2,1], [0,0,0,1]], dtype=int)