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 = [