This is an automated email from the ASF dual-hosted git repository.

zhreshold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git


The following commit(s) were added to refs/heads/master by this push:
     new eee72d9  [MXNET-892] ONNX export/import: DepthToSpace, SpaceToDepth 
operators (#12731)
eee72d9 is described below

commit eee72d92294957c7b9ef685767ecdfeba14da85d
Author: Vandana Kannan <[email protected]>
AuthorDate: Tue Oct 16 15:43:46 2018 -0700

    [MXNET-892] ONNX export/import: DepthToSpace, SpaceToDepth operators 
(#12731)
    
    * ONNX export/import: DepthToSpace operator
    
    * ONNX import/export: SpaceToDepth operator
    
    * ONNX import/export: Tests for SpaceToDepth
---
 .../mxnet/contrib/onnx/mx2onnx/_op_translations.py | 50 ++++++++++++++++++++++
 .../mxnet/contrib/onnx/onnx2mx/_import_helper.py   |  6 ++-
 .../mxnet/contrib/onnx/onnx2mx/_op_translations.py | 12 ++++++
 .../python-pytest/onnx/export/mxnet_export_test.py | 40 ++++++++++++++++-
 .../python-pytest/onnx/export/onnx_backend_test.py |  3 +-
 tests/python-pytest/onnx/import/test_cases.py      |  3 +-
 6 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py 
b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
index 204195d..20cfe07 100644
--- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
+++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
@@ -2077,3 +2077,53 @@ def convert_sqrt(node, **kwargs):
         name=name,
     )
     return [node]
+
+@mx_op.register("depth_to_space")
+def convert_depthtospace(node, **kwargs):
+    """Map MXNet's depth_to_space operator attributes to onnx's
+    DepthToSpace operator and return the created node.
+    """
+    onnx = import_onnx_modules()
+    name = node["name"]
+    proc_nodes = kwargs["proc_nodes"]
+    inputs = node["inputs"]
+    attrs = node["attrs"]
+
+    input_node_id = kwargs["index_lookup"][inputs[0][0]]
+    input_node = proc_nodes[input_node_id].name
+
+    blksize = int(attrs.get("block_size", 0))
+
+    node = onnx.helper.make_node(
+        "DepthToSpace",
+        [input_node],
+        [name],
+        blocksize=blksize,
+        name=name,
+    )
+    return [node]
+
+@mx_op.register("space_to_depth")
+def convert_spacetodepth(node, **kwargs):
+    """Map MXNet's space_to_depth operator attributes to onnx's
+    SpaceToDepth operator and return the created node.
+    """
+    onnx = import_onnx_modules()
+    name = node["name"]
+    proc_nodes = kwargs["proc_nodes"]
+    inputs = node["inputs"]
+    attrs = node["attrs"]
+
+    input_node_id = kwargs["index_lookup"][inputs[0][0]]
+    input_node = proc_nodes[input_node_id].name
+
+    blksize = int(attrs.get("block_size", 0))
+
+    node = onnx.helper.make_node(
+        "SpaceToDepth",
+        [input_node],
+        [name],
+        blocksize=blksize,
+        name=name,
+    )
+    return [node]
diff --git a/python/mxnet/contrib/onnx/onnx2mx/_import_helper.py 
b/python/mxnet/contrib/onnx/onnx2mx/_import_helper.py
index c44403d..f5a3d63 100644
--- a/python/mxnet/contrib/onnx/onnx2mx/_import_helper.py
+++ b/python/mxnet/contrib/onnx/onnx2mx/_import_helper.py
@@ -37,7 +37,7 @@ from ._op_translations import clip, reduce_log_sum, 
reduce_log_sum_exp
 from ._op_translations import reduce_sum_square, reduce_l1, reduce_l2, 
max_roi_pooling
 from ._op_translations import log_softmax, softsign, lesser, greater, equal
 from ._op_translations import logical_and, logical_or, logical_xor, logical_not
-from ._op_translations import mean
+from ._op_translations import mean, depthtospace, spacetodepth
 
 # convert_map defines maps of ONNX operator names to converter 
functor(callable)
 # defined in the op_translations module.
@@ -140,5 +140,7 @@ _convert_map = {
     'Shape'             : shape,
     'Gather'            : gather,
     'HardSigmoid'       : hardsigmoid,
-    'LpPool'            : lp_pooling
+    'LpPool'            : lp_pooling,
+    'DepthToSpace'      : depthtospace,
+    'SpaceToDepth'      : spacetodepth
 }
diff --git a/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py 
b/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py
index 5f3b756..7040103 100644
--- a/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py
+++ b/python/mxnet/contrib/onnx/onnx2mx/_op_translations.py
@@ -688,3 +688,15 @@ def max_roi_pooling(attrs, inputs, proto_obj):
                                                         'spatial_scale': 
'spatial_scale'
                                                        })
     return 'ROIPooling', new_attrs, inputs
+
+def depthtospace(attrs, inputs, proto_obj):
+    """Rearranges data from depth into blocks of spatial data."""
+    new_attrs = translation_utils._fix_attribute_names(attrs, 
{'blocksize':'block_size'})
+
+    return "depth_to_space", new_attrs, inputs
+
+def spacetodepth(attrs, inputs, proto_obj):
+    """Rearranges blocks of spatial data into depth."""
+    new_attrs = translation_utils._fix_attribute_names(attrs, 
{'blocksize':'block_size'})
+
+    return "space_to_depth", new_attrs, inputs
diff --git a/tests/python-pytest/onnx/export/mxnet_export_test.py 
b/tests/python-pytest/onnx/export/mxnet_export_test.py
index 7e1df07..7cbc980 100644
--- a/tests/python-pytest/onnx/export/mxnet_export_test.py
+++ b/tests/python-pytest/onnx/export/mxnet_export_test.py
@@ -25,18 +25,22 @@ those PRs merged, this file will get EOL'ed.
 from __future__ import absolute_import
 import sys
 import os
+import unittest
 import logging
 import tarfile
 from collections import namedtuple
 import numpy as np
 import numpy.testing as npt
-from onnx import numpy_helper
+from onnx import numpy_helper, helper
 from onnx import TensorProto
 from mxnet.test_utils import download
 from mxnet.contrib import onnx as onnx_mxnet
 import mxnet as mx
 CURR_PATH = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
-sys.path.insert(0, os.path.join(CURR_PATH, '../../python/unittest'))
+sys.path.insert(0, os.path.join(CURR_PATH, '../../../python/unittest'))
+import backend
+from common import with_seed
+
 logger = logging.getLogger()
 logger.setLevel(logging.DEBUG)
 URLS = {
@@ -179,6 +183,36 @@ def test_model_accuracy(model_name, input_shape):
         npt.assert_equal(expected.shape, actual.shape)
         npt.assert_almost_equal(expected, actual, decimal=3)
 
+@with_seed()
+def test_spacetodepth():
+    n, c, h, w = shape = (1, 1, 4, 6)
+    input1 = np.random.rand(n, c, h, w).astype("float32")
+    blocksize = 2
+    inputs = [helper.make_tensor_value_info("input1", TensorProto.FLOAT, 
shape=shape)]
+
+    outputs = [helper.make_tensor_value_info("output", TensorProto.FLOAT, 
shape=(1, 4, 2, 3))]
+
+    nodes = [helper.make_node("SpaceToDepth", ["input1"], ["output"], 
block_size=blocksize)]
+
+    graph = helper.make_graph(nodes,
+                              "spacetodepth_test",
+                              inputs,
+                              outputs)
+
+    spacetodepth_model = helper.make_model(graph)
+
+    bkd_rep = backend.prepare(spacetodepth_model)
+    output = bkd_rep.run([input1])
+
+    tmp = np.reshape(input1, [n, c,
+                    h // blocksize, blocksize,
+                    w // blocksize, blocksize])
+    tmp = np.transpose(tmp, [0, 3, 5, 1, 2, 4])
+    numpy_op = np.reshape(tmp, [n, c * (blocksize**2),
+                    h // blocksize,
+                    w // blocksize])
+
+    npt.assert_almost_equal(output[0], numpy_op)
 
 if __name__ == '__main__':
     test_models("bvlc_googlenet", (1, 3, 224, 224), (1, 1000))
@@ -189,3 +223,5 @@ if __name__ == '__main__':
     # ONNX expected results due to AveragePool issue github issue(#10194)
     test_model_accuracy("inception_v1", (1, 3, 224, 224))
     test_model_accuracy("inception_v2", (1, 3, 224, 224))
+
+    unittest.main()
\ No newline at end of file
diff --git a/tests/python-pytest/onnx/export/onnx_backend_test.py 
b/tests/python-pytest/onnx/export/onnx_backend_test.py
index 2216a8f..add5e83 100644
--- a/tests/python-pytest/onnx/export/onnx_backend_test.py
+++ b/tests/python-pytest/onnx/export/onnx_backend_test.py
@@ -91,7 +91,8 @@ IMPLEMENTED_OPERATORS_TEST = [
     'test_operator_params',
     'test_operator_permute2',
     'test_clip'
-    'test_cast'
+    'test_cast',
+    'test_depthtospace'
     ]
 
 BASIC_MODEL_TESTS = [
diff --git a/tests/python-pytest/onnx/import/test_cases.py 
b/tests/python-pytest/onnx/import/test_cases.py
index fd57822..fcd01b1 100644
--- a/tests/python-pytest/onnx/import/test_cases.py
+++ b/tests/python-pytest/onnx/import/test_cases.py
@@ -85,7 +85,8 @@ IMPLEMENTED_OPERATORS_TEST = [
     'test_operator_exp',
     'test_operator_maxpool',
     'test_operator_params',
-    'test_operator_permute2'
+    'test_operator_permute2',
+    'test_depthtospace'
     ]
 
 BASIC_MODEL_TESTS = [

Reply via email to