You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by sk...@apache.org on 2018/12/01 07:06:05 UTC
[incubator-mxnet] branch master updated: ONNX export: Instance
normalization, Shape (#12920)
This is an automated email from the ASF dual-hosted git repository.
skm 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 77510d7 ONNX export: Instance normalization, Shape (#12920)
77510d7 is described below
commit 77510d7b37a5da80bd43b3f1c21a39a52163dae8
Author: Vandana Kannan <va...@users.noreply.github.com>
AuthorDate: Fri Nov 30 23:05:51 2018 -0800
ONNX export: Instance normalization, Shape (#12920)
* ONNX import/export: Make backend_rep common
* ONNX export: Instance Normalization
* ONNX export: Shape operator
---
.../mxnet/contrib/onnx/mx2onnx/_op_translations.py | 26 ++++++
.../python-pytest/onnx/{export => }/backend_rep.py | 32 +++----
tests/python-pytest/onnx/export/backend.py | 4 +
.../python-pytest/onnx/export/onnx_backend_test.py | 4 +-
tests/python-pytest/onnx/import/mxnet_backend.py | 6 +-
.../python-pytest/onnx/import/mxnet_backend_rep.py | 98 ----------------------
6 files changed, 54 insertions(+), 116 deletions(-)
diff --git a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
index e2aab6b..facdcfe 100644
--- a/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
+++ b/python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
@@ -623,6 +623,23 @@ def convert_identity(node, **kwargs):
"""
return create_basic_op_node('Identity', node, kwargs)
+@mx_op.register("InstanceNorm")
+def convert_instancenorm(node, **kwargs):
+ """Map MXNet's InstanceNorm operator attributes to onnx's InstanceNormalization operator
+ based on the input node's attributes and return the created node.
+ """
+ name, input_nodes, attrs = get_inputs(node, kwargs)
+
+ eps = float(attrs.get("eps", 0.001))
+
+ node = onnx.helper.make_node(
+ 'InstanceNormalization',
+ inputs=input_nodes,
+ outputs=[name],
+ name=name,
+ epsilon=eps)
+
+ return [node]
@mx_op.register("LeakyReLU")
def convert_leakyrelu(node, **kwargs):
@@ -1546,6 +1563,15 @@ def convert_sum(node, **kwargs):
)
return [node]
+
+@mx_op.register("shape_array")
+def convert_shape(node, **kwargs):
+ """Map MXNet's shape_array operator attributes to onnx's Shape operator
+ and return the created node.
+ """
+ return create_basic_op_node('Shape', node, kwargs)
+
+
@mx_op.register("hard_sigmoid")
def convert_hardsigmoid(node, **kwargs):
"""Map MXNet's hard_sigmoid operator attributes to onnx's HardSigmoid operator
diff --git a/tests/python-pytest/onnx/export/backend_rep.py b/tests/python-pytest/onnx/backend_rep.py
similarity index 78%
rename from tests/python-pytest/onnx/export/backend_rep.py
rename to tests/python-pytest/onnx/backend_rep.py
index 8729eaf..63836ac 100644
--- a/tests/python-pytest/onnx/export/backend_rep.py
+++ b/tests/python-pytest/onnx/backend_rep.py
@@ -16,16 +16,17 @@
# under the License.
# coding: utf-8
-"""backend rep for onnx test infrastructure"""
+"""MXNet backend rep for onnx test infrastructure"""
try:
from onnx.backend.base import BackendRep
except ImportError:
- raise ImportError("Onnx and protobuf need to be installed")
+ raise ImportError("Onnx and protobuf need to be installed. Instructions to"
+ + " install - https://github.com/onnx/onnx#installation")
import mxnet as mx
# Using these functions for onnx test infrastructure.
# Implemented by following onnx docs guide:
-# https://github.com/onnx/onnx/blob/master/docs/Implementing%20an%20ONNX%20backend.md
+# https://github.com/onnx/onnx/blob/master/docs/ImplementingAnOnnxBackend.md
# MXNetBackendRep object will be returned by MXNetBackend's prepare method which is used to
# execute a model repeatedly.
# Inputs will be passed to the run method of MXNetBackendRep class, it will perform computation and
@@ -54,9 +55,6 @@ class MXNetBackendRep(BackendRep):
params : numpy array
result obtained after running the inference on mxnet
"""
- data_forward = []
- for val in inputs:
- data_forward.append(mx.nd.array(val))
# create module, passing cpu context
if self.device == 'CPU':
ctx = mx.cpu()
@@ -68,17 +66,19 @@ class MXNetBackendRep(BackendRep):
data_names = [graph_input for graph_input in self.symbol.list_inputs()
if graph_input not in self.arg_params and graph_input not in self.aux_params]
- data_shapes = []
+ data_forward = []
for idx, input_name in enumerate(data_names):
- data_shapes.append((input_name, inputs[idx].shape))
+ val = inputs[idx]
+ data_forward.append(mx.nd.array(val))
- mod = mx.mod.Module(symbol=self.symbol, data_names=data_names, context=ctx,
- label_names=None)
- mod.bind(for_training=False, data_shapes=data_shapes,
- label_shapes=None)
- mod.set_params(arg_params=self.arg_params, aux_params=self.aux_params)
+ if self.arg_params:
+ for idx, input_name in enumerate(self.arg_params):
+ val = self.arg_params[input_name]
+ data_names.append(input_name)
+ data_forward.append(mx.nd.array(val))
- # run inference
- mod.forward(mx.io.DataBatch(data_forward))
- result = mod.get_outputs()[0].asnumpy()
+ args = dict(zip(data_names, data_forward))
+ exe = self.symbol.bind(ctx, args=args, aux_states=self.aux_params)
+ exe.forward(is_train=False)
+ result = exe.outputs[0].asnumpy()
return [result]
diff --git a/tests/python-pytest/onnx/export/backend.py b/tests/python-pytest/onnx/export/backend.py
index e23cc01..3ea1daf 100644
--- a/tests/python-pytest/onnx/export/backend.py
+++ b/tests/python-pytest/onnx/export/backend.py
@@ -17,6 +17,8 @@
# coding: utf-8
"""backend wrapper for onnx test infrastructure"""
+import os
+import sys
import numpy as np
from mxnet.contrib.onnx.onnx2mx.import_onnx import GraphProto
from mxnet.contrib.onnx.mx2onnx.export_onnx import MXNetGraph
@@ -25,6 +27,8 @@ try:
from onnx.backend.base import Backend
except ImportError:
raise ImportError("Onnx and protobuf need to be installed")
+CURR_PATH = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
+sys.path.insert(0, os.path.join(CURR_PATH, '../'))
from backend_rep import MXNetBackendRep
# Using these functions for onnx test infrastructure.
diff --git a/tests/python-pytest/onnx/export/onnx_backend_test.py b/tests/python-pytest/onnx/export/onnx_backend_test.py
index ec9ddf2..be9273e 100644
--- a/tests/python-pytest/onnx/export/onnx_backend_test.py
+++ b/tests/python-pytest/onnx/export/onnx_backend_test.py
@@ -95,7 +95,9 @@ IMPLEMENTED_OPERATORS_TEST = [
'test_clip'
'test_cast',
'test_depthtospace',
- 'test_hardsigmoid'
+ 'test_hardsigmoid',
+ 'test_instancenorm',
+ 'test_shape'
]
BASIC_MODEL_TESTS = [
diff --git a/tests/python-pytest/onnx/import/mxnet_backend.py b/tests/python-pytest/onnx/import/mxnet_backend.py
index 10f89ec..bd4910b 100644
--- a/tests/python-pytest/onnx/import/mxnet_backend.py
+++ b/tests/python-pytest/onnx/import/mxnet_backend.py
@@ -17,6 +17,8 @@
# coding: utf-8
"""MXNet backend wrapper for onnx test infrastructure"""
+import os
+import sys
from mxnet.contrib.onnx.onnx2mx.import_onnx import GraphProto
try:
from onnx import helper, TensorProto
@@ -24,7 +26,9 @@ try:
except ImportError:
raise ImportError("Onnx and protobuf need to be installed. Instructions to"
+ " install - https://github.com/onnx/onnx#installation")
-from mxnet_backend_rep import MXNetBackendRep
+CURR_PATH = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
+sys.path.insert(0, os.path.join(CURR_PATH, '../'))
+from backend_rep import MXNetBackendRep
# MXNetBackend class will take an ONNX model with inputs, perform a computation,
# and then return the output.
diff --git a/tests/python-pytest/onnx/import/mxnet_backend_rep.py b/tests/python-pytest/onnx/import/mxnet_backend_rep.py
deleted file mode 100644
index 938f25d..0000000
--- a/tests/python-pytest/onnx/import/mxnet_backend_rep.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# coding: utf-8
-"""MXNet backend rep for onnx test infrastructure"""
-try:
- from onnx.backend.base import BackendRep
-except ImportError:
- raise ImportError("Onnx and protobuf need to be installed. Instructions to"
- + " install - https://github.com/onnx/onnx#installation")
-import mxnet as mx
-
-# Using these functions for onnx test infrastructure.
-# Implemented by following onnx docs guide:
-# https://github.com/onnx/onnx/blob/master/docs/ImplementingAnOnnxBackend.md
-# MXNetBackendRep object will be returned by MXNetBackend's prepare method which is used to
-# execute a model repeatedly.
-# Inputs will be passed to the run method of MXNetBackendRep class, it will perform computation and
-# retrieve the corresponding results for comparison to the onnx backend.
-# https://github.com/onnx/onnx/blob/master/onnx/backend/test/runner/__init__.py.
-
-class MXNetBackendRep(BackendRep):
- """Running model inference on mxnet engine and return the result
- to onnx test infrastructure for comparison."""
- def __init__(self, symbol, arg_params, aux_params, device):
- self.symbol = symbol
- self.arg_params = arg_params
- self.aux_params = aux_params
- self.device = device
-
- def run(self, inputs, **kwargs):
- """Run model inference and return the result
-
- Parameters
- ----------
- inputs : numpy array
- input to run a layer on
-
- Returns
- -------
- params : numpy array
- result obtained after running the inference on mxnet
- """
- data_forward = []
- for val in inputs:
- data_forward.append(mx.nd.array(val))
- # create module, passing cpu context
- if self.device == 'CPU':
- ctx = mx.cpu()
- else:
- raise NotImplementedError("ONNX tests are run only for CPU context.")
-
- # To fetch the data names of the input to the model we list the inputs of the symbol graph
- # and exclude the argument and auxiliary parameters from the list
- data_names = [graph_input for graph_input in self.symbol.list_inputs()
- if graph_input not in self.arg_params and graph_input not in self.aux_params]
-
- data_shapes = []
- for idx, input_name in enumerate(data_names):
- data_shapes.append((input_name, inputs[idx].shape))
-
- # module bind method requires all data to have same batch size,
- # using module if all data have same batch size
- if len(set([data_shape[1][0] for data_shape in data_shapes])) == 1:
- mod = mx.mod.Module(symbol=self.symbol, data_names=data_names, context=ctx,
- label_names=None)
- mod.bind(for_training=False, data_shapes=data_shapes,
- label_shapes=None)
- mod.set_params(arg_params=self.arg_params, aux_params=self.aux_params)
-
- # run inference
- mod.forward(mx.io.DataBatch(data_forward))
- result = mod.get_outputs()[0].asnumpy()
- # split operator inference returns 1 less dimension
- if self.symbol.name.startswith('split'):
- return [i.asnumpy() for i in mod.get_outputs()]
- return [result]
- # using symbol bind method if data have different batch size
- else:
- exec1 = self.symbol.bind(ctx, args=dict(zip(data_names, data_forward)))
- exec1.forward(is_train=False)
- result = exec1.outputs[0].asnumpy()
- return [result]
-