You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by li...@apache.org on 2020/08/20 05:43:38 UTC
[incubator-mxnet] branch master updated: add ffi (#18868)
This is an automated email from the ASF dual-hosted git repository.
liuyizhi 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 5e408bc add ffi (#18868)
5e408bc is described below
commit 5e408bce1b1d9ae69bde98f11b358d8d835fb7aa
Author: Yijun Chen <ch...@gmail.com>
AuthorDate: Thu Aug 20 13:42:33 2020 +0800
add ffi (#18868)
---
python/mxnet/ndarray/numpy/_op.py | 206 +++++++++++++++++++-
python/mxnet/numpy/multiarray.py | 203 +++++++++++++++++++-
python/mxnet/symbol/numpy/_symbol.py | 211 ++++++++++++++++++++-
src/api/operator/numpy/np_dot_op.cc | 50 +++++
.../operator/numpy/np_elemwise_unary_op_basic.cc | 13 ++
src/api/operator/numpy/np_matrix_op.cc | 55 ++++++
src/operator/numpy/np_dot.cc | 6 +-
src/operator/numpy/np_dot.cu | 4 +-
src/operator/numpy/np_elemwise_unary_op_basic.cc | 2 +-
src/operator/numpy/np_elemwise_unary_op_basic.cu | 2 +-
src/operator/numpy/np_matrix_op-inl.h | 16 ++
src/operator/numpy/np_matrix_op.cc | 4 +-
src/operator/numpy/np_matrix_op.cu | 2 +-
13 files changed, 750 insertions(+), 24 deletions(-)
diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py
index e3af383..68eea62 100644
--- a/python/mxnet/ndarray/numpy/_op.py
+++ b/python/mxnet/ndarray/numpy/_op.py
@@ -32,7 +32,7 @@ from ..ndarray import NDArray
__all__ = ['shape', 'zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 'empty_like', 'invert', 'delete',
'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'fmod',
- 'power', 'bitwise_not', 'trace', 'transpose',
+ 'power', 'bitwise_not', 'trace', 'transpose', 'copy', 'moveaxis', 'reshape', 'dot',
'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 'cbrt', 'abs', 'insert', 'fabs',
'absolute', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'matmul',
'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor', 'histogram',
@@ -708,7 +708,7 @@ def take(a, indices, axis=None, mode='raise', out=None):
raise NotImplementedError(
"function take does not support mode '{}'".format(mode))
if axis is None:
- return _api_internal.take(_npi.reshape(a, -1), indices, 0, mode, out)
+ return _api_internal.take(reshape(a, -1), indices, 0, mode, out)
else:
return _api_internal.take(a, indices, axis, mode, out)
# pylint: enable=redefined-outer-name
@@ -1666,6 +1666,67 @@ def sort(a, axis=-1, kind=None, order=None):
raise NotImplementedError("order not supported here")
return _api_internal.sort(a, axis, True)
+@set_module('mxnet.ndarray.numpy')
+def dot(a, b, out=None):
+ """
+ Dot product of two arrays. Specifically,
+
+ - If both `a` and `b` are 1-D arrays, it is inner product of vectors
+
+ - If both `a` and `b` are 2-D arrays, it is matrix multiplication,
+
+ - If either `a` or `b` is 0-D (scalar), it is equivalent to :func:`multiply`
+ and using ``np.multiply(a, b)`` or ``a * b`` is preferred.
+
+ - If `a` is an N-D array and `b` is a 1-D array, it is a sum product over
+ the last axis of `a` and `b`.
+
+ - If `a` is an N-D array and `b` is a 2-D array, it is a
+ sum product over the last axis of `a` and the second-to-last axis of `b`::
+
+ dot(a, b)[i,j,k] = sum(a[i,j,:] * b[:,k])
+
+ Parameters
+ ----------
+ a : ndarray
+ First argument.
+ b : ndarray
+ Second argument.
+
+ out : ndarray, optional
+ Output argument. It must have the same shape and type as the expected output.
+
+ Returns
+ -------
+ output : ndarray
+ Returns the dot product of `a` and `b`. If `a` and `b` are both
+ scalars or both 1-D arrays then a scalar is returned; otherwise
+ an array is returned.
+ If `out` is given, then it is returned
+
+ Examples
+ --------
+ >>> a = np.array(3)
+ >>> b = np.array(4)
+ >>> np.dot(a, b)
+ array(12.)
+
+ For 2-D arrays it is the matrix product:
+
+ >>> a = np.array([[1, 0], [0, 1]])
+ >>> b = np.array([[4, 1], [2, 2]])
+ >>> np.dot(a, b)
+ array([[4., 1.],
+ [2., 2.]])
+
+ >>> a = np.arange(3*4*5*6).reshape((3,4,5,6))
+ >>> b = np.arange(5*6)[::-1].reshape((6,5))
+ >>> np.dot(a, b)[2,3,2,2]
+ array(29884.)
+ >>> np.sum(a[2,3,2,:] * b[:,2])
+ array(29884.)
+ """
+ return _api_internal.dot(a, b, out)
@set_module('mxnet.ndarray.numpy')
def tensordot(a, b, axes=2):
@@ -5837,7 +5898,7 @@ def ravel(x, order='C'):
if isinstance(x, numeric_types):
return _np.reshape(x, -1)
elif isinstance(x, NDArray):
- return _npi.reshape(x, -1)
+ return reshape(x, -1)
else:
raise TypeError('type {} not supported'.format(str(type(x))))
@@ -8457,7 +8518,7 @@ def squeeze(x, axis=None):
"""
return _api_internal.squeeze(x, axis)
-
+# pylint: disable=redefined-outer-name
@set_module('mxnet.ndarray.numpy')
def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None, **kwargs):
"""
@@ -9374,6 +9435,143 @@ def cumsum(a, axis=None, dtype=None, out=None):
"""
return _api_internal.cumsum(a, axis, dtype, out)
+@set_module('mxnet.ndarray.numpy')
+def reshape(a, newshape, reverse=False, order='C'):
+ """
+ Gives a new shape to an array without changing its data.
+ This function always returns a copy of the input array if
+ ``out`` is not provided.
+
+ Parameters
+ ----------
+ a : ndarray
+ Array to be reshaped.
+
+ newshape : int or tuple of ints
+ The new shape should be compatible with the original shape. If
+ an integer, then the result will be a 1-D array of that length.
+ One shape dimension can be -1. In this case, the value is
+ inferred from the length of the array and remaining dimensions.
+
+ order : {'C'}, optional
+ Read the elements of `a` using this index order, and place the
+ elements into the reshaped array using this index order. 'C'
+ means to read / write the elements using C-like index order,
+ with the last axis index changing fastest, back to the first
+ axis index changing slowest. Other order types such as 'F'/'A'
+ may be added in the future.
+
+ Returns
+ -------
+ reshaped_array : ndarray
+ It will be always a copy of the original array. This behavior is different
+ from the official NumPy ``reshape`` operator where views of the original array may be
+ generated.
+
+ See Also
+ --------
+ ndarray.reshape : Equivalent method.
+
+ Examples
+ --------
+ >>> a = np.arange(6).reshape((3, 2))
+ >>> a
+ array([[0., 1.],
+ [2., 3.],
+ [4., 5.]])
+
+ >>> np.reshape(a, (2, 3)) # C-like index ordering
+ array([[0., 1., 2.],
+ [3., 4., 5.]])
+
+ >>> np.reshape(np.ravel(a), (2, 3)) # equivalent to C ravel then C reshape
+ array([[0., 1., 2.],
+ [3., 4., 5.]])
+
+ >>> a = np.array([[1,2,3], [4,5,6]])
+ >>> np.reshape(a, 6)
+ array([1., 2., 3., 4., 5., 6.])
+
+ >>> np.reshape(a, (3,-1)) # the unspecified value is inferred to be 2
+ array([[1., 2.],
+ [3., 4.],
+ [5., 6.]])
+ """
+ return _api_internal.reshape(a, newshape, reverse, order)
+
+@set_module('mxnet.ndarray.numpy')
+def moveaxis(a, source, destination):
+ """Move axes of an array to new positions.
+ Other axes remain in their original order.
+
+ Parameters
+ ----------
+ a : ndarray
+ The array whose axes should be reordered.
+ source : int or sequence of int
+ Original positions of the axes to move. These must be unique.
+ destination : int or sequence of int
+ Destination positions for each of the original axes. These must also be
+ unique.
+
+ Returns
+ -------
+ result : ndarray
+ Array with moved axes. This array is a view of the input array.
+
+ See Also
+ --------
+ transpose: Permute the dimensions of an array.
+ swapaxes: Interchange two axes of an array.
+
+ Examples
+ --------
+ >>> x = np.zeros((3, 4, 5))
+ >>> np.moveaxis(x, 0, -1).shape
+ (4, 5, 3)
+ >>> np.moveaxis(x, -1, 0).shape
+ (5, 3, 4)
+ These all achieve the same result:
+ >>> np.transpose(x).shape
+ (5, 4, 3)
+ >>> np.swapaxes(x, 0, -1).shape
+ (5, 4, 3)
+ >>> np.moveaxis(x, [0, 1], [-1, -2]).shape
+ (5, 4, 3)
+ >>> np.moveaxis(x, [0, 1, 2], [-1, -2, -3]).shape
+ (5, 4, 3)
+ """
+ return _api_internal.moveaxis(a, source, destination)
+
+# pylint: disable=redefined-outer-name
+@set_module('mxnet.ndarray.numpy')
+def copy(a):
+ """
+ Return an array copy of the given object.
+
+ Parameters
+ ----------
+ a :
+ Input array.
+
+ Returns
+ -------
+ arr : ndarray
+ Array interpretation of a.
+
+ -----
+ Examples
+ --------
+ >>> x = np.array([1, 2, 3])
+ >>> y = x
+ >>> z = np.copy(x)
+ >>> x[0] = 10
+ >>> x[0] == y[0]
+ True
+ >>> x[0] == z[0]
+ False
+ """
+ return _api_internal.copy(a)
@set_module('mxnet.ndarray.numpy')
def rollaxis(a, axis, start=0):
diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py
index b616867..87f9d4f 100644
--- a/python/mxnet/numpy/multiarray.py
+++ b/python/mxnet/numpy/multiarray.py
@@ -59,7 +59,7 @@ from . import fallback
__all__ = ['ndarray', 'empty', 'empty_like', 'array', 'shape', 'median',
'zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 'all', 'any', 'broadcast_to',
'add', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'fmod', 'power', 'bitwise_not',
- 'delete', 'trace', 'transpose',
+ 'delete', 'trace', 'transpose', 'copy', 'moveaxis', 'reshape', 'dot',
'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'invert',
'sqrt', 'cbrt', 'abs', 'absolute', 'fabs', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log',
'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'histogram',
@@ -1563,7 +1563,7 @@ class ndarray(NDArray):
def dot(self, b, out=None):
"""Dot product of two arrays.
Refer to ``numpy.dot`` for full documentation."""
- return _mx_np_op.dot(self, b, out=out)
+ return dot(self, b, out=out)
def reshape(self, *args, **kwargs): # pylint: disable=arguments-differ
"""Returns a copy of the array with a new shape.
@@ -10700,7 +10700,7 @@ def fill_diagonal(a, val, wrap=False):
"""
_mx_nd_np.fill_diagonal(a, val=val, wrap=wrap)
-
+# pylint: disable=redefined-outer-name
@set_module('mxnet.numpy')
def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None, **kwargs):
"""
@@ -11546,6 +11546,67 @@ def prod(a, axis=None, dtype=None, out=None, keepdims=False, initial=None): # py
"""
return _mx_nd_np.prod(a, axis=axis, dtype=dtype, keepdims=keepdims, initial=initial, out=out)
+@set_module('mxnet.numpy')
+def dot(a, b, out=None):
+ """
+ Dot product of two arrays. Specifically,
+
+ - If both `a` and `b` are 1-D arrays, it is inner product of vectors
+
+ - If both `a` and `b` are 2-D arrays, it is matrix multiplication,
+
+ - If either `a` or `b` is 0-D (scalar), it is equivalent to :func:`multiply`
+ and using ``np.multiply(a, b)`` or ``a * b`` is preferred.
+
+ - If `a` is an N-D array and `b` is a 1-D array, it is a sum product over
+ the last axis of `a` and `b`.
+
+ - If `a` is an N-D array and `b` is a 2-D array, it is a
+ sum product over the last axis of `a` and the second-to-last axis of `b`::
+
+ dot(a, b)[i,j,k] = sum(a[i,j,:] * b[:,k])
+
+ Parameters
+ ----------
+ a : ndarray
+ First argument.
+ b : ndarray
+ Second argument.
+
+ out : ndarray, optional
+ Output argument. It must have the same shape and type as the expected output.
+
+ Returns
+ -------
+ output : ndarray
+ Returns the dot product of `a` and `b`. If `a` and `b` are both
+ scalars or both 1-D arrays then a scalar is returned; otherwise
+ an array is returned.
+ If `out` is given, then it is returned
+
+ Examples
+ --------
+ >>> a = np.array(3)
+ >>> b = np.array(4)
+ >>> np.dot(a, b)
+ array(12.)
+
+ For 2-D arrays it is the matrix product:
+
+ >>> a = np.array([[1, 0], [0, 1]])
+ >>> b = np.array([[4, 1], [2, 2]])
+ >>> np.dot(a, b)
+ array([[4., 1.],
+ [2., 2.]])
+
+ >>> a = np.arange(3*4*5*6).reshape((3,4,5,6))
+ >>> b = np.arange(5*6)[::-1].reshape((6,5))
+ >>> np.dot(a, b)[2,3,2,2]
+ array(29884.)
+ >>> np.sum(a[2,3,2,:] * b[:,2])
+ array(29884.)
+ """
+ return _mx_nd_np.dot(a, b, out=out)
# pylint: disable=redefined-outer-name
@set_module('mxnet.numpy')
@@ -11599,6 +11660,142 @@ def cumsum(a, axis=None, dtype=None, out=None):
"""
return _mx_nd_np.cumsum(a, axis=axis, dtype=dtype, out=out)
+@set_module('mxnet.numpy')
+def reshape(a, newshape, reverse, order='C'):
+ """
+ Gives a new shape to an array without changing its data.
+ This function always returns a copy of the input array if
+ ``out`` is not provided.
+
+ Parameters
+ ----------
+ a : ndarray
+ Array to be reshaped.
+
+ newshape : int or tuple of ints
+ The new shape should be compatible with the original shape. If
+ an integer, then the result will be a 1-D array of that length.
+ One shape dimension can be -1. In this case, the value is
+ inferred from the length of the array and remaining dimensions.
+
+ order : {'C'}, optional
+ Read the elements of `a` using this index order, and place the
+ elements into the reshaped array using this index order. 'C'
+ means to read / write the elements using C-like index order,
+ with the last axis index changing fastest, back to the first
+ axis index changing slowest. Other order types such as 'F'/'A'
+ may be added in the future.
+
+ Returns
+ -------
+ reshaped_array : ndarray
+ It will be always a copy of the original array. This behavior is different
+ from the official NumPy ``reshape`` operator where views of the original array may be
+ generated.
+
+ See Also
+ --------
+ ndarray.reshape : Equivalent method.
+
+ Examples
+ --------
+ >>> a = np.arange(6).reshape((3, 2))
+ >>> a
+ array([[0., 1.],
+ [2., 3.],
+ [4., 5.]])
+
+ >>> np.reshape(a, (2, 3)) # C-like index ordering
+ array([[0., 1., 2.],
+ [3., 4., 5.]])
+
+ >>> np.reshape(np.ravel(a), (2, 3)) # equivalent to C ravel then C reshape
+ array([[0., 1., 2.],
+ [3., 4., 5.]])
+
+ >>> a = np.array([[1,2,3], [4,5,6]])
+ >>> np.reshape(a, 6)
+ array([1., 2., 3., 4., 5., 6.])
+
+ >>> np.reshape(a, (3,-1)) # the unspecified value is inferred to be 2
+ array([[1., 2.],
+ [3., 4.],
+ [5., 6.]])
+ """
+ return _mx_nd_np.reshape(a, newshape, reverse, order)
+
+@set_module('mxnet.numpy')
+def moveaxis(a, source, destination):
+ """Move axes of an array to new positions.
+ Other axes remain in their original order.
+
+ Parameters
+ ----------
+ a : ndarray
+ The array whose axes should be reordered.
+ source : int or sequence of int
+ Original positions of the axes to move. These must be unique.
+ destination : int or sequence of int
+ Destination positions for each of the original axes. These must also be
+ unique.
+
+ Returns
+ -------
+ result : ndarray
+ Array with moved axes. This array is a view of the input array.
+
+ See Also
+ --------
+ transpose: Permute the dimensions of an array.
+ swapaxes: Interchange two axes of an array.
+
+ Examples
+ --------
+ >>> x = np.zeros((3, 4, 5))
+ >>> np.moveaxis(x, 0, -1).shape
+ (4, 5, 3)
+ >>> np.moveaxis(x, -1, 0).shape
+ (5, 3, 4)
+ These all achieve the same result:
+ >>> np.transpose(x).shape
+ (5, 4, 3)
+ >>> np.swapaxes(x, 0, -1).shape
+ (5, 4, 3)
+ >>> np.moveaxis(x, [0, 1], [-1, -2]).shape
+ (5, 4, 3)
+ >>> np.moveaxis(x, [0, 1, 2], [-1, -2, -3]).shape
+ (5, 4, 3)
+ """
+ return _mx_nd_np.moveaxis(a, source, destination)
+
+@set_module('mxnet.numpy')
+def copy(a): # pylint: disable=redefined-outer-name
+ """
+ Return an array copy of the given object.
+
+ Parameters
+ ----------
+ a : _Symbol
+ Input array.
+
+ Returns
+ -------
+ arr : _Symbol
+ Array interpretation of a.
+
+ -----
+ Examples
+ --------
+ >>> x = np.array([1, 2, 3])
+ >>> y = x
+ >>> z = np.copy(x)
+ >>> x[0] = 10
+ >>> x[0] == y[0]
+ True
+ >>> x[0] == z[0]
+ False
+ """
+ return _mx_nd_np.copy(a)
# pylint: disable=redefined-outer-name
@set_module('mxnet.numpy')
diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py
index ee46544..95b232b 100644
--- a/python/mxnet/symbol/numpy/_symbol.py
+++ b/python/mxnet/symbol/numpy/_symbol.py
@@ -38,7 +38,7 @@ except ImportError:
__all__ = ['zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 'empty_like', 'bitwise_not', 'invert',
'delete', 'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'fmod',
- 'power', 'arctan2', 'trace', 'transpose',
+ 'power', 'arctan2', 'trace', 'transpose', 'copy', 'moveaxis', 'reshape', 'dot',
'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 'cbrt', 'abs', 'absolute', 'fabs', 'exp',
'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'log1p', 'matmul', 'median',
'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor', 'histogram', 'insert',
@@ -354,7 +354,7 @@ class _Symbol(Symbol):
return self.transpose()
# pylint: enable= invalid-name, undefined-variable
- def astype(self, dtype, order='K', casting='unsafe', subok=True, copy=True): # pylint: disable=arguments-differ,unused-argument,too-many-arguments
+ def astype(self, dtype, order='K', casting='unsafe', subok=True, copy=True): # pylint: disable=arguments-differ,unused-argument,too-many-arguments,redefined-outer-name
"""
Copy of the array, cast to a specified type.
@@ -414,7 +414,7 @@ class _Symbol(Symbol):
def dot(self, b, out=None):
"""Dot product of two arrays.
Refer to ``numpy.dot`` for full documentation."""
- return _mx_np_op.dot(self, b, out=out)
+ return _npi.dot(self, b, out=out)
def reshape(self, *args, **kwargs): # pylint: disable=arguments-differ
"""Returns a copy of the array with a new shape.
@@ -1822,6 +1822,67 @@ def sort(a, axis=-1, kind=None, order=None):
return _npi.sort(data=a, axis=axis, is_ascend=True)
+@set_module('mxnet.symbol.numpy')
+def dot(a, b, out=None):
+ """
+ Dot product of two arrays. Specifically,
+
+ - If both `a` and `b` are 1-D arrays, it is inner product of vectors
+
+ - If both `a` and `b` are 2-D arrays, it is matrix multiplication,
+
+ - If either `a` or `b` is 0-D (scalar), it is equivalent to :func:`multiply`
+ and using ``np.multiply(a, b)`` or ``a * b`` is preferred.
+
+ - If `a` is an N-D array and `b` is a 1-D array, it is a sum product over
+ the last axis of `a` and `b`.
+
+ - If `a` is an N-D array and `b` is a 2-D array, it is a
+ sum product over the last axis of `a` and the second-to-last axis of `b`::
+
+ dot(a, b)[i,j,k] = sum(a[i,j,:] * b[:,k])
+
+ Parameters
+ ----------
+ a : _Symbol
+ First argument.
+ b : _Symbol
+ Second argument.
+
+ out : _Symbol, optional
+ Output argument. It must have the same shape and type as the expected output.
+
+ Returns
+ -------
+ output : _Symbol
+ Returns the dot product of `a` and `b`. If `a` and `b` are both
+ scalars or both 1-D arrays then a scalar is returned; otherwise
+ an array is returned.
+ If `out` is given, then it is returned
+
+ Examples
+ --------
+ >>> a = np.array(3)
+ >>> b = np.array(4)
+ >>> np.dot(a, b)
+ array(12.)
+
+ For 2-D arrays it is the matrix product:
+
+ >>> a = np.array([[1, 0], [0, 1]])
+ >>> b = np.array([[4, 1], [2, 2]])
+ >>> np.dot(a, b)
+ array([[4., 1.],
+ [2., 2.]])
+
+ >>> a = np.arange(3*4*5*6).reshape((3,4,5,6))
+ >>> b = np.arange(5*6)[::-1].reshape((6,5))
+ >>> np.dot(a, b)[2,3,2,2]
+ array(29884.)
+ >>> np.sum(a[2,3,2,:] * b[:,2])
+ array(29884.)
+ """
+ return _npi.dot(a, b, out=out)
@set_module('mxnet.symbol.numpy')
def tensordot(a, b, axes=2):
@@ -5219,7 +5280,7 @@ def ravel(x, order='C'):
if isinstance(x, numeric_types):
return _np.reshape(x, -1)
elif isinstance(x, _Symbol):
- return _npi.reshape(x, -1)
+ return reshape(x, -1)
else:
raise TypeError('type {} not supported'.format(str(type(x))))
@@ -7113,7 +7174,7 @@ def resize(a, new_shape):
"""
return _npi.resize_fallback(a, new_shape=new_shape)
-
+# pylint: disable=redefined-outer-name
@set_module('mxnet.symbol.numpy')
def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None, **kwargs):
"""
@@ -7879,6 +7940,142 @@ def cumsum(a, axis=None, dtype=None, out=None):
"""
return _npi.cumsum(a, axis=axis, dtype=dtype, out=out)
+@set_module('mxnet.symbol.numpy')
+def reshape(a, newshape, reverse=False, order='C'):
+ """
+ Gives a new shape to an array without changing its data.
+ This function always returns a copy of the input array if
+ ``out`` is not provided.
+
+ Parameters
+ ----------
+ a : _Symbol
+ Array to be reshaped.
+
+ newshape : int or tuple of ints
+ The new shape should be compatible with the original shape. If
+ an integer, then the result will be a 1-D array of that length.
+ One shape dimension can be -1. In this case, the value is
+ inferred from the length of the array and remaining dimensions.
+
+ order : {'C'}, optional
+ Read the elements of `a` using this index order, and place the
+ elements into the reshaped array using this index order. 'C'
+ means to read / write the elements using C-like index order,
+ with the last axis index changing fastest, back to the first
+ axis index changing slowest. Other order types such as 'F'/'A'
+ may be added in the future.
+
+ Returns
+ -------
+ reshaped_array : _Symbol
+ It will be always a copy of the original array. This behavior is different
+ from the official NumPy ``reshape`` operator where views of the original array may be
+ generated.
+
+ See Also
+ --------
+ ndarray.reshape : Equivalent method.
+
+ Examples
+ --------
+ >>> a = np.arange(6).reshape((3, 2))
+ >>> a
+ array([[0., 1.],
+ [2., 3.],
+ [4., 5.]])
+
+ >>> np.reshape(a, (2, 3)) # C-like index ordering
+ array([[0., 1., 2.],
+ [3., 4., 5.]])
+
+ >>> np.reshape(np.ravel(a), (2, 3)) # equivalent to C ravel then C reshape
+ array([[0., 1., 2.],
+ [3., 4., 5.]])
+
+ >>> a = np.array([[1,2,3], [4,5,6]])
+ >>> np.reshape(a, 6)
+ array([1., 2., 3., 4., 5., 6.])
+
+ >>> np.reshape(a, (3,-1)) # the unspecified value is inferred to be 2
+ array([[1., 2.],
+ [3., 4.],
+ [5., 6.]])
+ """
+ return _npi.reshape(a, newshape, reverse, order)
+
+@set_module('mxnet.symbol.numpy')
+def moveaxis(a, source, destination):
+ """Move axes of an array to new positions.
+ Other axes remain in their original order.
+
+ Parameters
+ ----------
+ a : _Symbol
+ The array whose axes should be reordered.
+ source : int or sequence of int
+ Original positions of the axes to move. These must be unique.
+ destination : int or sequence of int
+ Destination positions for each of the original axes. These must also be
+ unique.
+
+ Returns
+ -------
+ result : _Symbol
+ Array with moved axes. This array is a view of the input array.
+
+ See Also
+ --------
+ transpose: Permute the dimensions of an array.
+ swapaxes: Interchange two axes of an array.
+
+ Examples
+ --------
+ >>> x = np.zeros((3, 4, 5))
+ >>> np.moveaxis(x, 0, -1).shape
+ (4, 5, 3)
+ >>> np.moveaxis(x, -1, 0).shape
+ (5, 3, 4)
+ These all achieve the same result:
+ >>> np.transpose(x).shape
+ (5, 4, 3)
+ >>> np.swapaxes(x, 0, -1).shape
+ (5, 4, 3)
+ >>> np.moveaxis(x, [0, 1], [-1, -2]).shape
+ (5, 4, 3)
+ >>> np.moveaxis(x, [0, 1, 2], [-1, -2, -3]).shape
+ (5, 4, 3)
+ """
+ return _npi.moveaxis(a, source, destination)
+
+@set_module('mxnet.symbol.numpy')
+def copy(a): # pylint: disable=redefined-outer-name
+ """
+ Return an array copy of the given object.
+
+ Parameters
+ ----------
+ a : _Symbol
+ Input array.
+
+ Returns
+ -------
+ arr : _Symbol
+ Array interpretation of a.
+
+ -----
+ Examples
+ --------
+ >>> x = np.array([1, 2, 3])
+ >>> y = x
+ >>> z = np.copy(x)
+ >>> x[0] = 10
+ >>> x[0] == y[0]
+ True
+ >>> x[0] == z[0]
+ False
+ """
+ return _npi.copy(a)
@set_module('mxnet.symbol.numpy')
def rollaxis(a, axis, start=0):
@@ -7887,7 +8084,7 @@ def rollaxis(a, axis, start=0):
Parameters
----------
- a : ndarray
+ a : _Symbol
Input array.
axis : integer
The axis to roll backwards. The positions of the other axes do not
@@ -7898,7 +8095,7 @@ def rollaxis(a, axis, start=0):
Returns
-------
- res : ndarray
+ res : _Symbol
A view after applying rollaxis to `a` is returned.
-----
diff --git a/src/api/operator/numpy/np_dot_op.cc b/src/api/operator/numpy/np_dot_op.cc
new file mode 100644
index 0000000..66a0f11
--- /dev/null
+++ b/src/api/operator/numpy/np_dot_op.cc
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+/*!
+ * \file np_dot_op.cc
+ * \brief Implementation of the API of functions in src/operator/numpy/np_dot.cc
+ */
+#include <mxnet/api_registry.h>
+#include "../utils.h"
+#include "../../../operator/numpy/np_dot-inl.h"
+
+namespace mxnet {
+
+MXNET_REGISTER_API("_npi.dot")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+ using namespace runtime;
+ const nnvm::Op* op = Op::Get("_npi_dot");
+ nnvm::NodeAttrs attrs;
+ attrs.op = op;
+ NDArray* inputs[] = {args[0].operator mxnet::NDArray*(),
+ args[1].operator mxnet::NDArray*()};
+ NDArray* out = args[2].operator NDArray*();
+ NDArray** outputs = out == nullptr ? nullptr : &out;
+ int num_inputs = 2;
+ int num_outputs = out != nullptr;
+ auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, outputs);
+ if (outputs) {
+ *ret = PythonArg(2);
+ } else {
+ *ret = ndoutputs[0];
+ }
+});
+
+} // namespace mxnet
diff --git a/src/api/operator/numpy/np_elemwise_unary_op_basic.cc b/src/api/operator/numpy/np_elemwise_unary_op_basic.cc
index 9840fc4..7d2b4bb 100644
--- a/src/api/operator/numpy/np_elemwise_unary_op_basic.cc
+++ b/src/api/operator/numpy/np_elemwise_unary_op_basic.cc
@@ -114,4 +114,17 @@ MXNET_REGISTER_API("_npi.around")
}
});
+MXNET_REGISTER_API("_npi.copy")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+ using namespace runtime;
+ const nnvm::Op* op = Op::Get("_npi_copy");
+ nnvm::NodeAttrs attrs;
+ attrs.op = op;
+ NDArray* inputs[] = {args[0].operator NDArray*()};
+ int num_inputs = 1;
+ int num_outputs = 0;
+ auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, nullptr);
+ *ret = ndoutputs[0];
+});
+
} // namespace mxnet
diff --git a/src/api/operator/numpy/np_matrix_op.cc b/src/api/operator/numpy/np_matrix_op.cc
index 61d1796..2fd81f4 100644
--- a/src/api/operator/numpy/np_matrix_op.cc
+++ b/src/api/operator/numpy/np_matrix_op.cc
@@ -519,6 +519,61 @@ MXNET_REGISTER_API("_npi.rollaxis")
*ret = ndoutputs[0];
});
+MXNET_REGISTER_API("_npi.reshape")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+ using namespace runtime;
+ const nnvm::Op* op = Op::Get("_npi_reshape");
+ nnvm::NodeAttrs attrs;
+ op::NumpyXReshapeParam param;
+ if (args[1].type_code() == kNull) {
+ param.newshape = TShape(-1, 0);
+ } else if (args[1].type_code() == kDLInt) {
+ param.newshape = TShape(1, args[1].operator int64_t());
+ } else {
+ param.newshape = TShape(args[1].operator ObjectRef());
+ }
+ param.reverse = args[2].operator bool();
+ param.order = args[3].operator std::string();
+ attrs.parsed = param;
+ attrs.op = op;
+ SetAttrDict<op::NumpyXReshapeParam>(&attrs);
+ NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+ int num_inputs = 1;
+ int num_outputs = 0;
+ auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, nullptr);
+ *ret = ndoutputs[0];
+});
+
+MXNET_REGISTER_API("_npi.moveaxis")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+ using namespace runtime;
+ const nnvm::Op* op = Op::Get("_npi_moveaxis");
+ nnvm::NodeAttrs attrs;
+ op::NumpyMoveaxisParam param;
+ if (args[1].type_code() == kNull) {
+ param.source = TShape(-1, 0);
+ } else if (args[1].type_code() == kDLInt) {
+ param.source = TShape(1, args[1].operator int64_t());
+ } else {
+ param.source = TShape(args[1].operator ObjectRef());
+ }
+ if (args[2].type_code() == kNull) {
+ param.destination = TShape(-1, 0);
+ } else if (args[2].type_code() == kDLInt) {
+ param.destination = TShape(1, args[2].operator int64_t());
+ } else {
+ param.destination = TShape(args[2].operator ObjectRef());
+ }
+ attrs.parsed = param;
+ attrs.op = op;
+ SetAttrDict<op::NumpyMoveaxisParam>(&attrs);
+ NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+ int num_inputs = 1;
+ int num_outputs = 0;
+ auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, nullptr);
+ *ret = ndoutputs[0];
+});
+
MXNET_REGISTER_API("_npi.diagonal")
.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
using namespace runtime;
diff --git a/src/operator/numpy/np_dot.cc b/src/operator/numpy/np_dot.cc
index feb032a..a65be36 100644
--- a/src/operator/numpy/np_dot.cc
+++ b/src/operator/numpy/np_dot.cc
@@ -101,7 +101,7 @@ inline bool NumpyDotShape(const nnvm::NodeAttrs& attrs,
return shape_is_known(*in_attrs) && shape_is_known(*out_attrs);
}
-NNVM_REGISTER_OP(_np_dot)
+NNVM_REGISTER_OP(_npi_dot)
.describe(R"doc(Dot product of two arrays. Specifically,
- If both a and b are 1-D arrays, it is inner product of vectors.
@@ -133,11 +133,11 @@ NNVM_REGISTER_OP(_np_dot)
})
.set_attr<THasDeterministicOutput>("THasDeterministicOutput", true)
.set_attr<FCompute>("FCompute<cpu>", NumpyDotForward<cpu>)
-.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseIn{"_backward_np_dot"})
+.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseIn{"_backward_npi_dot"})
.add_argument("a", "NDArray-or-Symbol", "First input")
.add_argument("b", "NDArray-or-Symbol", "Second input");
-NNVM_REGISTER_OP(_backward_np_dot)
+NNVM_REGISTER_OP(_backward_npi_dot)
.set_num_inputs(3)
.set_num_outputs(2)
.set_attr<nnvm::TIsBackward>("TIsBackward", true)
diff --git a/src/operator/numpy/np_dot.cu b/src/operator/numpy/np_dot.cu
index 9a9c69a..085c7e4 100644
--- a/src/operator/numpy/np_dot.cu
+++ b/src/operator/numpy/np_dot.cu
@@ -27,10 +27,10 @@
namespace mxnet {
namespace op {
-NNVM_REGISTER_OP(_np_dot)
+NNVM_REGISTER_OP(_npi_dot)
.set_attr<FCompute>("FCompute<gpu>", NumpyDotForward<gpu>);
-NNVM_REGISTER_OP(_backward_np_dot)
+NNVM_REGISTER_OP(_backward_npi_dot)
.set_attr<FCompute>("FCompute<gpu>", NumpyDotBackward<gpu>);
} // namespace op
diff --git a/src/operator/numpy/np_elemwise_unary_op_basic.cc b/src/operator/numpy/np_elemwise_unary_op_basic.cc
index 74b2b7e..c375b3a 100644
--- a/src/operator/numpy/np_elemwise_unary_op_basic.cc
+++ b/src/operator/numpy/np_elemwise_unary_op_basic.cc
@@ -44,7 +44,7 @@ MXNET_OPERATOR_REGISTER_UNARY(_npx_sigmoid)
.set_attr<FCompute>("FCompute<cpu>", UnaryOp::Compute<cpu, mshadow_op::sigmoid>)
.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseOut{"_backward_sigmoid"});
-NNVM_REGISTER_OP(_np_copy)
+NNVM_REGISTER_OP(_npi_copy)
.describe(R"code(Return an array copy of the given object.)code" ADD_FILELINE)
.set_num_inputs(1)
.set_num_outputs(1)
diff --git a/src/operator/numpy/np_elemwise_unary_op_basic.cu b/src/operator/numpy/np_elemwise_unary_op_basic.cu
index bce6335..a872006 100644
--- a/src/operator/numpy/np_elemwise_unary_op_basic.cu
+++ b/src/operator/numpy/np_elemwise_unary_op_basic.cu
@@ -33,7 +33,7 @@ NNVM_REGISTER_OP(_npx_relu)
NNVM_REGISTER_OP(_npx_sigmoid)
.set_attr<FCompute>("FCompute<gpu>", UnaryOp::Compute<gpu, mshadow_op::sigmoid>);
-NNVM_REGISTER_OP(_np_copy)
+NNVM_REGISTER_OP(_npi_copy)
.set_attr<FCompute>("FCompute<gpu>", UnaryOp::IdentityCompute<gpu>);
#define MXNET_OPERATOR_REGISTER_NUMPY_UNARY_GPU(__name$, __kernel$) \
diff --git a/src/operator/numpy/np_matrix_op-inl.h b/src/operator/numpy/np_matrix_op-inl.h
index 6ff792e..5461e61 100644
--- a/src/operator/numpy/np_matrix_op-inl.h
+++ b/src/operator/numpy/np_matrix_op-inl.h
@@ -131,6 +131,15 @@ struct NumpyXReshapeParam : public dmlc::Parameter<NumpyXReshapeParam> {
" Note that currently only C-like order is"
" supported");
}
+ void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+ std::ostringstream newshape_s, reverse_s, order_s;
+ newshape_s << newshape;
+ reverse_s << reverse;
+ order_s << order;
+ (*dict)["newshape"] = newshape_s.str();
+ (*dict)["reverse"] = reverse_s.str();
+ (*dict)["order"] = order_s.str();
+ }
};
template<typename xpu>
@@ -704,6 +713,13 @@ struct NumpyMoveaxisParam : public dmlc::Parameter<NumpyMoveaxisParam> {
.describe("Destination positions for each of the original axes. "
"These must also be unique.");
}
+ void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+ std::ostringstream source_s, destination_s;
+ source_s << source;
+ destination_s << destination;
+ (*dict)["source"] = source_s.str();
+ (*dict)["destination"] = destination_s.str();
+ }
};
inline mxnet::TShape NumpyMoveaxisShapeImpl(const nnvm::NodeAttrs& attrs,
diff --git a/src/operator/numpy/np_matrix_op.cc b/src/operator/numpy/np_matrix_op.cc
index 2bb2fe3..8d6d0a3 100644
--- a/src/operator/numpy/np_matrix_op.cc
+++ b/src/operator/numpy/np_matrix_op.cc
@@ -1391,7 +1391,7 @@ bool NumpyMoveaxisShape(const nnvm::NodeAttrs& attrs,
return shape_is_known(ret);
}
-NNVM_REGISTER_OP(_np_moveaxis)
+NNVM_REGISTER_OP(_npi_moveaxis)
.describe(R"code(Move axes of an array to new positions.
Other axes remain in their original order.
)code" ADD_FILELINE)
@@ -1407,7 +1407,7 @@ Other axes remain in their original order.
os1 << param.source;
std::ostringstream os2;
os2 << param.destination;
- return MakeNonlossGradNode("_np_moveaxis", n, ograds, {},
+ return MakeNonlossGradNode("_npi_moveaxis", n, ograds, {},
{{"source", os2.str()}, {"destination", os1.str()}});
})
.set_attr<FCompute>("FCompute<cpu>", NumpyMoveaxisCompute<cpu>)
diff --git a/src/operator/numpy/np_matrix_op.cu b/src/operator/numpy/np_matrix_op.cu
index 5c834e2..1b14365 100644
--- a/src/operator/numpy/np_matrix_op.cu
+++ b/src/operator/numpy/np_matrix_op.cu
@@ -112,7 +112,7 @@ NNVM_REGISTER_OP(_npi_flip)
NNVM_REGISTER_OP(_backward_npi_flip)
.set_attr<FCompute>("FCompute<gpu>", NumpyFlipForward<gpu>);
-NNVM_REGISTER_OP(_np_moveaxis)
+NNVM_REGISTER_OP(_npi_moveaxis)
.set_attr<FCompute>("FCompute<gpu>", NumpyMoveaxisCompute<gpu>);
NNVM_REGISTER_OP(_npi_rollaxis)