From 99aed810515523d7fe452120f69e935dcc822de0 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 14 May 2019 10:49:57 -0700 Subject: [PATCH 1/7] ONNX export: Slice op - Handle None value for ends --- .../mxnet/contrib/onnx/mx2onnx/_op_translations.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index b92797563b1d..9501e8649216 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -56,7 +56,7 @@ from __future__ import print_function from __future__ import unicode_literals -import re +import re, sys import logging import numpy as np from .export_onnx import MXNetGraph as mx_op @@ -1499,9 +1499,11 @@ def convert_slice_axis(node, **kwargs): axes = int(attrs.get("axis")) starts = int(attrs.get("begin")) - ends = int(attrs.get("end", None)) - if not ends: - raise ValueError("Slice: ONNX doesnt't support 'None' in 'end' attribute") + ends = attrs.get("end", None) + if not ends or ends == 'None': + # ONNX doesn't support None for ends. Since ends=None depicts + # length of dimension, passing INT_MAX in this case. + ends = sys.maxsize node = onnx.helper.make_node( "Slice", @@ -1509,7 +1511,7 @@ def convert_slice_axis(node, **kwargs): [name], axes=[axes], starts=[starts], - ends=[ends], + ends=[int(ends)], name=name, ) return [node] From 04fb2df1b7291bf4fcf9470ef561f502e797d93c Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 14 May 2019 11:16:24 -0700 Subject: [PATCH 2/7] Fix lint errors --- 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 9501e8649216..def7e4ac22af 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -56,7 +56,8 @@ from __future__ import print_function from __future__ import unicode_literals -import re, sys +import re +import sys import logging import numpy as np from .export_onnx import MXNetGraph as mx_op From 2c4d5fcd86c117c0bcb8de09d362394d605f50f8 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 9 Jul 2019 16:22:06 -0700 Subject: [PATCH 3/7] ONNX import: slice_axis --- python/mxnet/contrib/onnx/onnx2mx/_op_translations.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py b/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py index 627181d6ae21..311fd86ef623 100644 --- a/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py +++ b/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py @@ -499,6 +499,8 @@ def split(attrs, inputs, proto_obj): def _slice(attrs, inputs, proto_obj): """Returns a slice of the input tensor along multiple axes.""" + input_tensor_data = proto_obj.model_metadata.get('input_tensor_data')[0] + input_shape = input_tensor_data[1] new_attrs = translation_utils._fix_attribute_names(attrs, {'axes' : 'axis', 'ends' : 'end', @@ -506,8 +508,10 @@ def _slice(attrs, inputs, proto_obj): # onnx slice provides slicing on multiple axis. Adding multiple slice_axis operator # for multiple axes from mxnet begin = new_attrs.get('begin') - end = new_attrs.get('end') + end = list(new_attrs.get('end')) axes = new_attrs.get('axis', tuple(range(len(begin)))) + for i, axis in enumerate(axes): + end[i] = None if end[i] >= input_shape[axis] else end[i] slice_op = symbol.slice_axis(inputs[0], axis=axes[0], begin=begin[0], end=end[0]) if len(axes) > 1: for i, axis in enumerate(axes): From 6bcf587731d6997d689ac002798d3585a895a21f Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Tue, 9 Jul 2019 16:22:29 -0700 Subject: [PATCH 4/7] Add a test for ends=None --- tests/python-pytest/onnx/test_node.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/python-pytest/onnx/test_node.py b/tests/python-pytest/onnx/test_node.py index 96045516c69e..18cf69b9bb91 100644 --- a/tests/python-pytest/onnx/test_node.py +++ b/tests/python-pytest/onnx/test_node.py @@ -274,7 +274,11 @@ def test_exports(self): ("test_random_normal", mx.sym.random_normal, "RandomNormal", [], {'shape': (2, 2), 'loc': 0, 'scale': 1}, False, {'modify': {'loc': 'mean'}}, False, True), ("test_random_uniform", mx.sym.random_uniform, "RandomUniform", [], - {'shape': (2, 2), 'low': 0.5, 'high': 1.0}, False, {}, False, True) + {'shape': (2, 2), 'low': 0.5, 'high': 1.0}, False, {}, False, True), + ("test_slice_axis", mx.sym.slice_axis, "Slice", [get_rnd((2, 3, 20, 20))], + {'axis': 0, 'begin': 0, 'end': None}, False, + {'remove': ['axis', 'begin', 'end'], + 'add': {'axes': [0], 'starts': [0], 'ends': [sys.maxsize]}}, True, False) ] test_scalar_ops = ['Add', 'Sub', 'rSub' 'Mul', 'Div', 'Pow'] From a28da92733d8ce697ab659b37febc20842079213 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Fri, 30 Aug 2019 15:52:01 -0700 Subject: [PATCH 5/7] Add slice test, address review comments --- python/mxnet/contrib/onnx/mx2onnx/_op_translations.py | 4 ++-- tests/python-pytest/onnx/test_cases.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py index def7e4ac22af..40131b42f562 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -57,7 +57,6 @@ from __future__ import unicode_literals import re -import sys import logging import numpy as np from .export_onnx import MXNetGraph as mx_op @@ -1504,7 +1503,8 @@ def convert_slice_axis(node, **kwargs): if not ends or ends == 'None': # ONNX doesn't support None for ends. Since ends=None depicts # length of dimension, passing INT_MAX in this case. - ends = sys.maxsize + in_shape = kwargs['in_shape'][0] + ends = in_shape[axes] node = onnx.helper.make_node( "Slice", diff --git a/tests/python-pytest/onnx/test_cases.py b/tests/python-pytest/onnx/test_cases.py index 0f822d3b240f..9a72d58e0490 100644 --- a/tests/python-pytest/onnx/test_cases.py +++ b/tests/python-pytest/onnx/test_cases.py @@ -41,6 +41,7 @@ 'test_globalaveragepool', 'test_slice_cpu', 'test_slice_neg', + 'test_slice_end', 'test_reciprocal', 'test_sqrt', 'test_pow', From ce1dbca20210b9037ecda46650f2e0991cb2f4de Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Fri, 30 Aug 2019 15:52:13 -0700 Subject: [PATCH 6/7] Revert "Add a test for ends=None" This reverts commit 3e1b6c35b11a4f965d0dbde5a3c63cba4b576e4b. --- tests/python-pytest/onnx/test_node.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/python-pytest/onnx/test_node.py b/tests/python-pytest/onnx/test_node.py index 18cf69b9bb91..96045516c69e 100644 --- a/tests/python-pytest/onnx/test_node.py +++ b/tests/python-pytest/onnx/test_node.py @@ -274,11 +274,7 @@ def test_exports(self): ("test_random_normal", mx.sym.random_normal, "RandomNormal", [], {'shape': (2, 2), 'loc': 0, 'scale': 1}, False, {'modify': {'loc': 'mean'}}, False, True), ("test_random_uniform", mx.sym.random_uniform, "RandomUniform", [], - {'shape': (2, 2), 'low': 0.5, 'high': 1.0}, False, {}, False, True), - ("test_slice_axis", mx.sym.slice_axis, "Slice", [get_rnd((2, 3, 20, 20))], - {'axis': 0, 'begin': 0, 'end': None}, False, - {'remove': ['axis', 'begin', 'end'], - 'add': {'axes': [0], 'starts': [0], 'ends': [sys.maxsize]}}, True, False) + {'shape': (2, 2), 'low': 0.5, 'high': 1.0}, False, {}, False, True) ] test_scalar_ops = ['Add', 'Sub', 'rSub' 'Mul', 'Div', 'Pow'] From dae8abe341fd9dd86a9029222f9ee4f176b901fa Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Fri, 30 Aug 2019 15:54:53 -0700 Subject: [PATCH 7/7] Correct comment --- 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 40131b42f562..aeaf4a1b9497 100644 --- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py +++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py @@ -1502,7 +1502,7 @@ def convert_slice_axis(node, **kwargs): ends = attrs.get("end", None) if not ends or ends == 'None': # ONNX doesn't support None for ends. Since ends=None depicts - # length of dimension, passing INT_MAX in this case. + # length of dimension, passing dimension in this case. in_shape = kwargs['in_shape'][0] ends = in_shape[axes]