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

ptrendx pushed a commit to branch v1.6.x
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git


The following commit(s) were added to refs/heads/v1.6.x by this push:
     new 00f169f  port shape op to 1.6.x (#16912)
00f169f is described below

commit 00f169f7519e1e416592b68c3dc8ac92362d6d07
Author: Hao Jin <hjjn.a...@gmail.com>
AuthorDate: Tue Nov 26 09:07:49 2019 -0800

    port shape op to 1.6.x (#16912)
---
 python/mxnet/ndarray/numpy/_op.py                  | 40 +++++++++++--
 python/mxnet/numpy/multiarray.py                   | 68 +++++++++++++++++-----
 python/mxnet/numpy_dispatch_protocol.py            |  1 +
 .../python/unittest/test_numpy_interoperability.py | 15 +++--
 tests/python/unittest/test_numpy_op.py             | 19 ++++++
 5 files changed, 119 insertions(+), 24 deletions(-)

diff --git a/python/mxnet/ndarray/numpy/_op.py 
b/python/mxnet/ndarray/numpy/_op.py
index ed3d9d8..4ce675a 100644
--- a/python/mxnet/ndarray/numpy/_op.py
+++ b/python/mxnet/ndarray/numpy/_op.py
@@ -28,7 +28,7 @@ from ...context import current_context
 from . import _internal as _npi
 from ..ndarray import NDArray
 
-__all__ = ['zeros', 'ones', 'full', 'add', 'subtract', 'multiply', 'divide', 
'mod', 'remainder', 'power',
+__all__ = ['shape', 'zeros', 'ones', 'full', 'add', 'subtract', 'multiply', 
'divide', 'mod', 'remainder', 'power',
            'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 
'sqrt', 'cbrt', 'abs',
            'absolute', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 
'log', 'degrees', 'log2',
            'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 
'fix', 'ceil', 'floor',
@@ -41,7 +41,37 @@ __all__ = ['zeros', 'ones', 'full', 'add', 'subtract', 
'multiply', 'divide', 'mo
            'hsplit', 'rot90', 'einsum', 'true_divide', 'nonzero', 
'shares_memory', 'may_share_memory', 'diff']
 
 @set_module('mxnet.ndarray.numpy')
-def zeros(shape, dtype=_np.float32, order='C', ctx=None):
+def shape(a):
+    """
+    Return the shape of an array.
+    Parameters
+    ----------
+    a : array_like
+        Input array.
+    Returns
+    -------
+    shape : tuple of ints
+        The elements of the shape tuple give the lengths of the
+        corresponding array dimensions.
+    See Also
+    --------
+    ndarray.shape : Equivalent array method.
+    Examples
+    --------
+    >>> np.shape(np.eye(3))
+    (3, 3)
+    >>> np.shape([[1, 2]])
+    (1, 2)
+    >>> np.shape([0])
+    (1,)
+    >>> np.shape(0)
+    ()
+    """
+    return a.shape
+
+
+@set_module('mxnet.ndarray.numpy')
+def zeros(shape, dtype=_np.float32, order='C', ctx=None):  # pylint: 
disable=redefined-outer-name
     """Return a new array of given shape and type, filled with zeros.
     This function currently only supports storing multi-dimensional data
     in row-major (C-style).
@@ -75,7 +105,7 @@ def zeros(shape, dtype=_np.float32, order='C', ctx=None):
 
 
 @set_module('mxnet.ndarray.numpy')
-def ones(shape, dtype=_np.float32, order='C', ctx=None):
+def ones(shape, dtype=_np.float32, order='C', ctx=None):  # pylint: 
disable=redefined-outer-name
     """Return a new array of given shape and type, filled with ones.
     This function currently only supports storing multi-dimensional data
     in row-major (C-style).
@@ -108,8 +138,9 @@ def ones(shape, dtype=_np.float32, order='C', ctx=None):
     return _npi.ones(shape=shape, ctx=ctx, dtype=dtype)
 
 
+# pylint: disable=too-many-arguments, redefined-outer-name
 @set_module('mxnet.ndarray.numpy')
-def full(shape, fill_value, dtype=None, order='C', ctx=None, out=None):  # 
pylint: disable=too-many-arguments
+def full(shape, fill_value, dtype=None, order='C', ctx=None, out=None):
     """
     Return a new array of given shape and type, filled with `fill_value`.
     Parameters
@@ -161,6 +192,7 @@ def full(shape, fill_value, dtype=None, order='C', 
ctx=None, out=None):  # pylin
         ctx = current_context()
     dtype = _np.float32 if dtype is None else dtype
     return _npi.full(shape=shape, value=fill_value, ctx=ctx, dtype=dtype, 
out=out)
+# pylint: enable=too-many-arguments, redefined-outer-name
 
 
 @set_module('mxnet.ndarray.numpy')
diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py
index ad5fb54..35a549e 100644
--- a/python/mxnet/numpy/multiarray.py
+++ b/python/mxnet/numpy/multiarray.py
@@ -45,7 +45,7 @@ from ..context import current_context
 from ..ndarray import numpy as _mx_nd_np
 from ..ndarray.numpy import _internal as _npi
 
-__all__ = ['ndarray', 'empty', 'array', 'zeros', 'ones', 'full', 'add', 
'subtract', 'multiply', 'divide',
+__all__ = ['ndarray', 'empty', 'array', 'shape', 'zeros', 'ones', 'full', 
'add', 'subtract', 'multiply', 'divide',
            'mod', 'remainder', 'power', 'arctan2', 'sin', 'cos', 'tan', 
'sinh', 'cosh', 'tanh', 'log10',
            'sqrt', 'cbrt', 'abs', 'absolute', 'exp', 'expm1', 'arcsin', 
'arccos', 'arctan', 'sign', 'log',
            'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 
'square', 'negative',
@@ -66,7 +66,7 @@ _NDARRAY_ADVANCED_INDEXING = 1
 
 # This function is copied from ndarray.py since pylint
 # keeps giving false alarm error of undefined-all-variable
-def _new_alloc_handle(shape, ctx, delay_alloc, dtype=mx_real_t):
+def _new_alloc_handle(shape, ctx, delay_alloc, dtype=mx_real_t):  # pylint: 
disable=redefined-outer-name
     """Return a new handle with specified shape and context.
 
     Empty handle is only used to hold results.
@@ -88,7 +88,7 @@ def _new_alloc_handle(shape, ctx, delay_alloc, 
dtype=mx_real_t):
     return hdl
 
 
-def _reshape_view(a, *shape):
+def _reshape_view(a, *shape):  # pylint: disable=redefined-outer-name
     """Returns a **view** of this array with a new shape without altering any 
data.
 
     Parameters
@@ -459,7 +459,7 @@ class ndarray(NDArray):
         """
         # handling possible boolean indexing first
         ndim = self.ndim
-        shape = self.shape
+        shape = self.shape  # pylint: disable=redefined-outer-name
 
         if isinstance(key, list):
             try:
@@ -801,7 +801,7 @@ class ndarray(NDArray):
 
     def __len__(self):
         """Number of elements along the first axis."""
-        shape = self.shape
+        shape = self.shape  # pylint: disable=redefined-outer-name
         if len(shape) == 0:
             raise TypeError('len() of unsized object')
         return self.shape[0]
@@ -1161,7 +1161,7 @@ class ndarray(NDArray):
         """
         raise AttributeError('mxnet.numpy.ndarray object has no attribute 
reshape_like')
 
-    def reshape_view(self, *shape, **kwargs):
+    def reshape_view(self, *shape, **kwargs):  # pylint: 
disable=redefined-outer-name
         """Returns a **view** of this array with a new shape without altering 
any data.
         Inheritated from NDArray.reshape.
         """
@@ -1515,13 +1515,15 @@ class ndarray(NDArray):
         """Returns the average of the array elements along given axis."""
         return mean(self, axis=axis, dtype=dtype, out=out, keepdims=keepdims)
 
-    def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False):  # 
pylint: disable=arguments-differ
+    # pylint: disable=too-many-arguments, arguments-differ
+    def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
         """Returns the standard deviation of the array elements along given 
axis."""
         return std(self, axis=axis, dtype=dtype, ddof=ddof, keepdims=keepdims, 
out=out)
 
-    def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False):  # 
pylint: disable=arguments-differ
+    def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
         """Returns the variance of the array elements, along given axis."""
         return var(self, axis=axis, dtype=dtype, out=out, ddof=ddof, 
keepdims=keepdims)
+    # pylint: enable=too-many-arguments, arguments-differ
 
     def cumsum(self, axis=None, dtype=None, out=None):
         """Return the cumulative sum of the elements along the given axis."""
@@ -1850,7 +1852,7 @@ class ndarray(NDArray):
         """Remove single-dimensional entries from the shape of a."""
         return _mx_np_op.squeeze(self, axis=axis)
 
-    def broadcast_to(self, shape):
+    def broadcast_to(self, shape):  # pylint: disable=redefined-outer-name
         return _mx_np_op.broadcast_to(self, shape)
 
     def broadcast_like(self, other):
@@ -1912,7 +1914,7 @@ class ndarray(NDArray):
 
 
 @set_module('mxnet.numpy')
-def empty(shape, dtype=_np.float32, order='C', ctx=None):
+def empty(shape, dtype=_np.float32, order='C', ctx=None):  # pylint: 
disable=redefined-outer-name
     """Return a new array of given shape and type, without initializing 
entries.
 
     Parameters
@@ -2016,7 +2018,37 @@ def array(object, dtype=None, ctx=None):
 
 
 @set_module('mxnet.numpy')
-def zeros(shape, dtype=_np.float32, order='C', ctx=None):
+def shape(a):
+    """
+    Return the shape of an array.
+    Parameters
+    ----------
+    a : array_like
+        Input array.
+    Returns
+    -------
+    shape : tuple of ints
+        The elements of the shape tuple give the lengths of the
+        corresponding array dimensions.
+    See Also
+    --------
+    ndarray.shape : Equivalent array method.
+    Examples
+    --------
+    >>> np.shape(np.eye(3))
+    (3, 3)
+    >>> np.shape([[1, 2]])
+    (1, 2)
+    >>> np.shape([0])
+    (1,)
+    >>> np.shape(0)
+    ()
+    """
+    return _mx_nd_np.shape(a)
+
+
+@set_module('mxnet.numpy')
+def zeros(shape, dtype=_np.float32, order='C', ctx=None):  # pylint: 
disable=redefined-outer-name
     """Return a new array of given shape and type, filled with zeros.
     This function currently only supports storing multi-dimensional data
     in row-major (C-style).
@@ -2057,7 +2089,7 @@ def zeros(shape, dtype=_np.float32, order='C', ctx=None):
 
 
 @set_module('mxnet.numpy')
-def ones(shape, dtype=_np.float32, order='C', ctx=None):
+def ones(shape, dtype=_np.float32, order='C', ctx=None):  # pylint: 
disable=redefined-outer-name
     """Return a new array of given shape and type, filled with ones.
     This function currently only supports storing multi-dimensional data
     in row-major (C-style).
@@ -2102,8 +2134,9 @@ def ones(shape, dtype=_np.float32, order='C', ctx=None):
     return _mx_nd_np.ones(shape, dtype, order, ctx)
 
 
+# pylint: disable=too-many-arguments, redefined-outer-name
 @set_module('mxnet.numpy')
-def full(shape, fill_value, dtype=None, order='C', ctx=None, out=None):  # 
pylint: disable=too-many-arguments
+def full(shape, fill_value, dtype=None, order='C', ctx=None, out=None):
     """
     Return a new array of given shape and type, filled with `fill_value`.
 
@@ -2156,6 +2189,7 @@ def full(shape, fill_value, dtype=None, order='C', 
ctx=None, out=None):  # pylin
            [2, 2]], dtype=int32)
     """
     return _mx_nd_np.full(shape, fill_value, order=order, ctx=ctx, 
dtype=dtype, out=out)
+# pylint: enable=too-many-arguments, redefined-outer-name
 
 
 @set_module('mxnet.numpy')
@@ -4220,7 +4254,7 @@ def tensordot(a, b, axes=2):
 
 
 @set_module('mxnet.numpy')
-def histogram(a, bins=10, range=None, normed=None, weights=None, 
density=None):  # pylint-disable=too-many-arguments
+def histogram(a, bins=10, range=None, normed=None, weights=None, 
density=None):  # pylint: disable=too-many-arguments
     """
     Compute the histogram of a set of data.
 
@@ -4379,6 +4413,7 @@ def linspace(start, stop, num=50, endpoint=True, 
retstep=False, dtype=None, axis
     return _mx_nd_np.linspace(start, stop, num, endpoint, retstep, dtype, 
axis, ctx)
 
 
+# pylint: disable=too-many-arguments
 @set_module('mxnet.numpy')
 def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, 
axis=0, ctx=None):
     r"""Return numbers spaced evenly on a log scale.
@@ -4453,6 +4488,7 @@ def logspace(start, stop, num=50, endpoint=True, 
base=10.0, dtype=None, axis=0,
     array([ 100.     ,  215.44347,  464.15887, 1000.     ], ctx=gpu(0))
     """
     return _mx_nd_np.logspace(start, stop, num, endpoint, base, dtype, axis, 
ctx=ctx)
+# pylint: enable=too-many-arguments
 
 
 @set_module('mxnet.numpy')
@@ -5418,7 +5454,7 @@ def mean(a, axis=None, dtype=None, out=None, 
keepdims=False):  # pylint: disable
 
 
 @set_module('mxnet.numpy')
-def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
+def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):  # 
pylint: disable=too-many-arguments
     """
     Compute the standard deviation along the specified axis.
     Returns the standard deviation, a measure of the spread of a distribution,
@@ -5485,7 +5521,7 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, 
keepdims=False):
 
 
 @set_module('mxnet.numpy')
-def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
+def var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):  # 
pylint: disable=too-many-arguments
     """
     Compute the variance along the specified axis.
     Returns the variance of the array elements, a measure of the spread of a
diff --git a/python/mxnet/numpy_dispatch_protocol.py 
b/python/mxnet/numpy_dispatch_protocol.py
index 8a4a90c..9e68d36 100644
--- a/python/mxnet/numpy_dispatch_protocol.py
+++ b/python/mxnet/numpy_dispatch_protocol.py
@@ -125,6 +125,7 @@ _NUMPY_ARRAY_FUNCTION_LIST = [
     'column_stack',
     'zeros_like',
     'linalg.norm',
+    'shape',
     'trace',
     'tril',
     'meshgrid',
diff --git a/tests/python/unittest/test_numpy_interoperability.py 
b/tests/python/unittest/test_numpy_interoperability.py
index 5b6cea7..da3c17c 100644
--- a/tests/python/unittest/test_numpy_interoperability.py
+++ b/tests/python/unittest/test_numpy_interoperability.py
@@ -1122,6 +1122,12 @@ def _add_workload_nonzero():
     OpArgMngr.add_workload('nonzero', np.array([True, False, False], 
dtype=np.bool_))
 
 
+def _add_workload_shape():
+    OpArgMngr.add_workload('shape', np.random.uniform(size=()))
+    OpArgMngr.add_workload('shape', np.random.uniform(size=(0, 1)))
+    OpArgMngr.add_workload('shape', np.random.uniform(size=(2, 3)))
+
+
 def _add_workload_diff():
     x = np.array([1, 4, 6, 7, 12])
     OpArgMngr.add_workload('diff', x)
@@ -1253,6 +1259,7 @@ def _prepare_workloads():
     _add_workload_greater_equal(array_pool)
     _add_workload_less(array_pool)
     _add_workload_less_equal(array_pool)
+    _add_workload_shape()
     _add_workload_diff()
 
 
@@ -1284,11 +1291,11 @@ def _check_interoperability_helper(op_name, *args, 
**kwargs):
     expected_out = _get_numpy_op_output(onp_op, *args, **kwargs)
     if isinstance(out, (tuple, list)):
         assert type(out) == type(expected_out)
-        for arr in out:
-            assert isinstance(arr, np.ndarray)
         for arr, expected_arr in zip(out, expected_out):
-            assert isinstance(arr, np.ndarray)
-            assert_almost_equal(arr.asnumpy(), expected_arr, rtol=1e-3, 
atol=1e-4, use_broadcast=False, equal_nan=True)
+            if isinstance(arr, np.ndarray):
+                assert_almost_equal(arr.asnumpy(), expected_arr, rtol=1e-3, 
atol=1e-4, use_broadcast=False, equal_nan=True)
+            else:
+                _np.testing.assert_equal(arr, expected_arr)
     else:
         assert isinstance(out, np.ndarray)
         assert_almost_equal(out.asnumpy(), expected_out, rtol=1e-3, atol=1e-4, 
use_broadcast=False, equal_nan=True)
diff --git a/tests/python/unittest/test_numpy_op.py 
b/tests/python/unittest/test_numpy_op.py
index 3aef5ca..5ec9944 100644
--- a/tests/python/unittest/test_numpy_op.py
+++ b/tests/python/unittest/test_numpy_op.py
@@ -756,6 +756,25 @@ def test_np_moment():
                                 np_out = getattr(_np, name)(x.asnumpy(), 
axis=axis, dtype=acc_type[itype], keepdims=keepdims, ddof=ddof).astype(dtype)
                                 assert_almost_equal(mx_out.asnumpy(), np_out, 
rtol=rtol, atol=atol, use_broadcast=False, equal_nan=True)
 
+@with_seed()
+@use_np
+def test_np_shape():
+    shapes = [
+        (),
+        (0, 1),
+        (2, 3),
+        (2, 3, 4),
+    ]
+
+    for shape in shapes:
+        mx_a = np.random.uniform(size=shape)
+        np_a = _np.random.uniform(size=shape)
+
+        mx_shape = np.shape(mx_a)
+        np_shape = _np.shape(np_a)
+
+        assert mx_shape == np_shape
+
 
 @with_seed()
 @use_np

Reply via email to