diff --git a/benchmark/python/ffi/benchmark_ffi.py b/benchmark/python/ffi/benchmark_ffi.py index 88af3cf3d55e..946bb8edbb00 100644 --- a/benchmark/python/ffi/benchmark_ffi.py +++ b/benchmark/python/ffi/benchmark_ffi.py @@ -55,6 +55,10 @@ def prepare_workloads(): OpArgMngr.add_workload("cumsum", pool['3x2'], axis=0, out=pool['3x2']) OpArgMngr.add_workload("add", pool['2x2'], pool['2x2']) OpArgMngr.add_workload("random.uniform", low=0, high=1, size=1) + OpArgMngr.add_workload("max", pool["2x2"], axis=0, out=pool['2'], keepdims=False) + OpArgMngr.add_workload("min", pool["2x2"], axis=0, out=pool['2'], keepdims=False) + OpArgMngr.add_workload("amax", pool["2x2"], axis=1, out=pool['2'], keepdims=False) + OpArgMngr.add_workload("amin", pool["2x2"], axis=1, out=pool['2'], keepdims=False) def benchmark_helper(f, *args, **kwargs): diff --git a/python/mxnet/_numpy_op_doc.py b/python/mxnet/_numpy_op_doc.py index 8dfc0867cdb2..1dd8eeac9029 100644 --- a/python/mxnet/_numpy_op_doc.py +++ b/python/mxnet/_numpy_op_doc.py @@ -699,256 +699,6 @@ def _np_squeeze(a, axis=None, out=None): pass -def _np_max(a, axis=None, keepdims=False, out=None): - """ - Return the maximum of an array or maximum along an axis. - - Parameters - ---------- - a : ndarray - Input data. - axis : int, optional - Axis along which to operate. By default, flattened input is used. - out : ndarray, optional - Alternative output array in which to place the result. Must - be of the same shape and buffer length as the expected output. - See `doc.ufuncs` (Section "Output arguments") for more details. - keepdims : bool, optional - If this is set to True, the axes which are reduced are left - in the result as dimensions with size one. With this option, - the result will broadcast correctly against the original `arr`. - - Returns - ------- - max : ndarray - Maximum of `a`. If `axis` is None, the result is an array of dimension 1. - If `axis` is given, the result is an array of dimension - ``a.ndim - 1``. - - See Also - -------- - min : - The minimum value of an array along a given axis, ignoring any nan. - maximum : - Element-wise maximum of two arrays, ignoring any nan. - argmax : - Return the indices of the maximum values. - - Notes - ----- - NaN in the orginal `numpy` is denoted as nan and will be ignored. - - Don't use `max` for element-wise comparison of 2 arrays; when - ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than - ``max(a, axis=0)``. - - Examples - -------- - >>> a = np.arange(4).reshape((2,2)) - >>> a - array([[0., 1.], - [2., 3.]]) - >>> np.max(a) # Maximum of the flattened array - array(3.) - >>> np.max(a, axis=0) # Maxima along the first axis - array([2., 3.]) - >>> np.max(a, axis=1) # Maxima along the second axis - array([1., 3.]) - - >>> b = np.arange(5, dtype=np.float32) - >>> b[2] = np.nan - >>> np.max(b) - array(4.) - """ - pass - - -def _np_amax(a, axis=None, keepdims=False, out=None): - """ - Return the maximum of an array or maximum along an axis. - - Parameters - ---------- - a : ndarray - Input data. - axis : int, optional - Axis along which to operate. By default, flattened input is used. - out : ndarray, optional - Alternative output array in which to place the result. Must - be of the same shape and buffer length as the expected output. - See `doc.ufuncs` (Section "Output arguments") for more details. - keepdims : bool, optional - If this is set to True, the axes which are reduced are left - in the result as dimensions with size one. With this option, - the result will broadcast correctly against the original `arr`. - - Returns - ------- - amax : ndarray - Maximum of `a`. If `axis` is None, the result is an array of dimension 1. - If `axis` is given, the result is an array of dimension - ``a.ndim - 1``. - - See Also - -------- - min : - The minimum value of an array along a given axis, ignoring any nan. - maximum : - Element-wise maximum of two arrays, ignoring any nan. - argmax : - Return the indices of the maximum values. - - Notes - ----- - NaN in the orginal `numpy` is denoted as nan and will be ignored. - - Don't use `amax` for element-wise comparison of 2 arrays; when - ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than - ``amax(a, axis=0)``. - - Examples - -------- - >>> a = np.arange(4).reshape((2,2)) - >>> a - array([[0., 1.], - [2., 3.]]) - >>> np.amax(a) # Maximum of the flattened array - array(3.) - >>> np.amax(a, axis=0) # Maxima along the first axis - array([2., 3.]) - >>> np.amax(a, axis=1) # Maxima along the second axis - array([1., 3.]) - - >>> b = np.arange(5, dtype=np.float32) - >>> b[2] = np.nan - >>> np.amax(b) - array(4.) - """ - pass - - -def _np_min(a, axis=None, keepdims=False, out=None): - """ - Return the minimum of an array or minimum along an axis. - - Parameters - ---------- - a : ndarray - Input data. - axis : int, optional - Axis along which to operate. By default, flattened input is used. - out : ndarray, optional - Alternative output array in which to place the result. Must - be of the same shape and buffer length as the expected output. - See `doc.ufuncs` (Section "Output arguments") for more details. - keepdims : bool, optional - If this is set to True, the axes which are reduced are left - in the result as dimensions with size one. With this option, - the result will broadcast correctly against the original `arr`. - - Returns - ------- - min : ndarray - Minimum of `a`. If `axis` is None, the result is an array of dimension 1. - If `axis` is given, the result is an array of dimension - ``a.ndim - 1``. - - See Also - -------- - max : - The maximum value of an array along a given axis, ignoring any nan. - minimum : - Element-wise minimum of two arrays, ignoring any nan. - - Notes - ----- - NaN in the orginal `numpy` is denoted as nan and will be ignored. - - Don't use `min` for element-wise comparison of 2 arrays; when - ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than - ``min(a, axis=0)``. - - Examples - -------- - >>> a = np.arange(4).reshape((2,2)) - >>> a - array([[0., 1.], - [2., 3.]]) - >>> np.min(a) # Minimum of the flattened array - array(0.) - >>> np.min(a, axis=0) # Minima along the first axis - array([0., 1.]) - >>> np.min(a, axis=1) # Minima along the second axis - array([0., 2.]) - >>> b = np.arange(5, dtype=np.float32) - >>> b[2] = np.nan - >>> np.min(b) - array(0.) # nan will be ignored - """ - pass - - -def _np_amin(a, axis=None, keepdims=False, out=None): - """ - Return the minimum of an array or minimum along an axis. - - Parameters - ---------- - a : ndarray - Input data. - axis : int, optional - Axis along which to operate. By default, flattened input is used. - out : ndarray, optional - Alternative output array in which to place the result. Must - be of the same shape and buffer length as the expected output. - See `doc.ufuncs` (Section "Output arguments") for more details. - keepdims : bool, optional - If this is set to True, the axes which are reduced are left - in the result as dimensions with size one. With this option, - the result will broadcast correctly against the original `arr`. - - Returns - ------- - amin : ndarray - Minimum of `a`. If `axis` is None, the result is an array of dimension 1. - If `axis` is given, the result is an array of dimension - ``a.ndim - 1``. - - See Also - -------- - max : - The maximum value of an array along a given axis, ignoring any nan. - minimum : - Element-wise minimum of two arrays, ignoring any nan. - - Notes - ----- - NaN in the orginal `numpy` is denoted as nan and will be ignored. - - Don't use `amin` for element-wise comparison of 2 arrays; when - ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than - ``amin(a, axis=0)``. - - Examples - -------- - >>> a = np.arange(4).reshape((2,2)) - >>> a - array([[0., 1.], - [2., 3.]]) - >>> np.amin(a) # Minimum of the flattened array - array(0.) - >>> np.amin(a, axis=0) # Minima along the first axis - array([0., 1.]) - >>> np.amin(a, axis=1) # Minima along the second axis - array([0., 2.]) - >>> b = np.arange(5, dtype=np.float32) - >>> b[2] = np.nan - >>> np.amin(b) - array(0.) # nan will be ignored - """ - pass - - def _np_prod(a, axis=None, dtype=None, out=None, keepdims=False): """ Return the product of array elements over a given axis. diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py index 3d30333d6da2..c15852903fd9 100644 --- a/python/mxnet/ndarray/numpy/_op.py +++ b/python/mxnet/ndarray/numpy/_op.py @@ -39,6 +39,7 @@ 'logspace', 'expand_dims', 'tile', 'arange', 'array_split', 'split', 'hsplit', 'vsplit', 'dsplit', 'concatenate', 'append', 'stack', 'vstack', 'row_stack', 'column_stack', 'hstack', 'dstack', 'average', 'mean', 'maximum', 'minimum', 'around', 'round', 'round_', 'flatnonzero', + 'max', 'min', 'amax', 'amin', 'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'unravel_index', 'diag_indices_from', 'hanning', 'hamming', 'blackman', 'flip', 'flipud', 'fliplr', 'hypot', 'bitwise_and', 'bitwise_xor', 'bitwise_or', 'rad2deg', 'deg2rad', 'unique', 'lcm', @@ -4386,6 +4387,260 @@ def minimum(x1, x2, out=None, **kwargs): return _ufunc_helper(x1, x2, _npi.minimum, _np.minimum, _npi.minimum_scalar, None, out) +@set_module('mxnet.ndarray.numpy') +def max(a, axis=None, out=None, keepdims=False): + """ + Return the maximum of an array or maximum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + max : ndarray + Maximum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + min : + The minimum value of an array along a given axis, ignoring any nan. + maximum : + Element-wise maximum of two arrays, ignoring any nan. + argmax : + Return the indices of the maximum values. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `max` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than + ``max(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.max(a) # Maximum of the flattened array + array(3.) + >>> np.max(a, axis=0) # Maxima along the first axis + array([2., 3.]) + >>> np.max(a, axis=1) # Maxima along the second axis + array([1., 3.]) + + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.max(b) + array(4.) + """ + return _api_internal.max(a, axis, keepdims, out) + + +@set_module('mxnet.ndarray.numpy') +def min(a, axis=None, out=None, keepdims=False): + """ + Return the minimum of an array or minimum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + min : ndarray + Minimum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + max : + The maximum value of an array along a given axis, ignoring any nan. + minimum : + Element-wise minimum of two arrays, ignoring any nan. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `min` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than + ``min(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.min(a) # Minimum of the flattened array + array(0.) + >>> np.min(a, axis=0) # Minima along the first axis + array([0., 1.]) + >>> np.min(a, axis=1) # Minima along the second axis + array([0., 2.]) + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.min(b) + array(0.) # nan will be ignored + """ + return _api_internal.min(a, axis, keepdims, out) + + +@set_module('mxnet.ndarray.numpy') +def amax(a, axis=None, out=None, keepdims=False): + """ + Return the maximum of an array or maximum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + max : ndarray + Maximum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + min : + The minimum value of an array along a given axis, ignoring any nan. + maximum : + Element-wise maximum of two arrays, ignoring any nan. + argmax : + Return the indices of the maximum values. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `max` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than + ``max(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.max(a) # Maximum of the flattened array + array(3.) + >>> np.max(a, axis=0) # Maxima along the first axis + array([2., 3.]) + >>> np.max(a, axis=1) # Maxima along the second axis + array([1., 3.]) + + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.max(b) + array(4.) + """ + return _api_internal.amax(a, axis, keepdims, out) + + +@set_module('mxnet.ndarray.numpy') +def amin(a, axis=None, out=None, keepdims=False): + """ + Return the minimum of an array or minimum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + min : ndarray + Minimum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + max : + The maximum value of an array along a given axis, ignoring any nan. + minimum : + Element-wise minimum of two arrays, ignoring any nan. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `min` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than + ``min(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.min(a) # Minimum of the flattened array + array(0.) + >>> np.min(a, axis=0) # Minima along the first axis + array([0., 1.]) + >>> np.min(a, axis=1) # Minima along the second axis + array([0., 2.]) + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.min(b) + array(0.) # nan will be ignored + """ + return _api_internal.amin(a, axis, keepdims, out) + + @set_module('mxnet.ndarray.numpy') def swapaxes(a, axis1, axis2): """Interchange two axes of an array. diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py index 09712c03ea96..48d62bbd83a4 100644 --- a/python/mxnet/numpy/multiarray.py +++ b/python/mxnet/numpy/multiarray.py @@ -61,7 +61,8 @@ 'sort', 'tensordot', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'array_split', 'split', 'hsplit', 'vsplit', 'dsplit', 'flatnonzero', 'concatenate', 'stack', 'vstack', 'row_stack', 'column_stack', 'hstack', 'dstack', - 'average', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'insert', + 'average', 'mean', 'maximum', 'minimum', 'max', 'min', 'swapaxes', 'clip', 'argmax', 'argmin', + 'amax', 'amin', 'std', 'var', 'insert', 'indices', 'copysign', 'ravel', 'unravel_index', 'diag_indices_from', 'hanning', 'hamming', 'blackman', 'flip', 'flipud', 'fliplr', 'around', 'round', 'round_', 'arctan2', 'hypot', 'bitwise_and', 'bitwise_xor', 'bitwise_or', 'rad2deg', 'deg2rad', @@ -1818,7 +1819,7 @@ def tolist(self): def max(self, axis=None, out=None, keepdims=False): # pylint: disable=arguments-differ """Return the maximum along a given axis.""" - return _mx_np_op.max(self, axis=axis, keepdims=keepdims, out=out) + return _mx_nd_np.max(self, axis=axis, out=out, keepdims=keepdims) def min(self, axis=None, out=None, keepdims=False): # pylint: disable=arguments-differ """Convenience fluent method for :py:func:`min`. @@ -1826,7 +1827,7 @@ def min(self, axis=None, out=None, keepdims=False): # pylint: disable=arguments The arguments are the same as for :py:func:`min`, with this array as data. """ - return _mx_np_op.min(self, axis=axis, keepdims=keepdims, out=out) + return _mx_nd_np.min(self, axis=axis, out=out, keepdims=keepdims) def norm(self, *args, **kwargs): """Convenience fluent method for :py:func:`norm`. @@ -6214,6 +6215,133 @@ def minimum(x1, x2, out=None, **kwargs): return _mx_nd_np.minimum(x1, x2, out=out) +@set_module('mxnet.numpy') +def max(a, axis=None, out=None, keepdims=False): + """ + Return the maximum of an array or maximum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + max : ndarray + Maximum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + min : + The minimum value of an array along a given axis, ignoring any nan. + maximum : + Element-wise maximum of two arrays, ignoring any nan. + argmax : + Return the indices of the maximum values. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `max` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than + ``max(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.max(a) # Maximum of the flattened array + array(3.) + >>> np.max(a, axis=0) # Maxima along the first axis + array([2., 3.]) + >>> np.max(a, axis=1) # Maxima along the second axis + array([1., 3.]) + + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.max(b) + array(4.) + """ + return _mx_nd_np.max(a, axis=axis, out=out, keepdims=keepdims) + + +@set_module('mxnet.numpy') +def min(a, axis=None, out=None, keepdims=False): + """ + Return the minimum of an array or minimum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + min : ndarray + Minimum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + max : + The maximum value of an array along a given axis, ignoring any nan. + minimum : + Element-wise minimum of two arrays, ignoring any nan. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `min` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than + ``min(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.min(a) # Minimum of the flattened array + array(0.) + >>> np.min(a, axis=0) # Minima along the first axis + array([0., 1.]) + >>> np.min(a, axis=1) # Minima along the second axis + array([0., 2.]) + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.min(b) + array(0.) # nan will be ignored + """ + return _mx_nd_np.min(a, axis=axis, out=out, keepdims=keepdims) + + @set_module('mxnet.numpy') def swapaxes(a, axis1, axis2): """Interchange two axes of an array. @@ -6450,6 +6578,133 @@ def argmin(a, axis=None, out=None): return _mx_nd_np.argmin(a, axis, out) +@set_module('mxnet.numpy') +def amax(a, axis=None, out=None, keepdims=False): + """ + Return the maximum of an array or maximum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + max : ndarray + Maximum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + min : + The minimum value of an array along a given axis, ignoring any nan. + maximum : + Element-wise maximum of two arrays, ignoring any nan. + argmax : + Return the indices of the maximum values. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `max` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than + ``max(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.max(a) # Maximum of the flattened array + array(3.) + >>> np.max(a, axis=0) # Maxima along the first axis + array([2., 3.]) + >>> np.max(a, axis=1) # Maxima along the second axis + array([1., 3.]) + + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.max(b) + array(4.) + """ + return _mx_nd_np.amax(a, axis=axis, out=out, keepdims=keepdims) + + +@set_module('mxnet.numpy') +def amin(a, axis=None, out=None, keepdims=False): + """ + Return the minimum of an array or minimum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + min : ndarray + Minimum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + max : + The maximum value of an array along a given axis, ignoring any nan. + minimum : + Element-wise minimum of two arrays, ignoring any nan. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `min` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than + ``min(a, axis=0)``. + + Examples + -------- + >>> a = np.arange(4).reshape((2,2)) + >>> a + array([[0., 1.], + [2., 3.]]) + >>> np.min(a) # Minimum of the flattened array + array(0.) + >>> np.min(a, axis=0) # Minima along the first axis + array([0., 1.]) + >>> np.min(a, axis=1) # Minima along the second axis + array([0., 2.]) + >>> b = np.arange(5, dtype=np.float32) + >>> b[2] = np.nan + >>> np.min(b) + array(0.) # nan will be ignored + """ + return _mx_nd_np.amin(a, axis=axis, out=out, keepdims=keepdims) + + @set_module('mxnet.numpy') def average(a, axis=None, weights=None, returned=False, out=None): """ diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py index 11e574ae5fd9..a0585a65537c 100644 --- a/python/mxnet/symbol/numpy/_symbol.py +++ b/python/mxnet/symbol/numpy/_symbol.py @@ -43,7 +43,8 @@ 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'argsort', 'sort', 'tensordot', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'array_split', 'split', 'hsplit', 'vsplit', 'dsplit', 'concatenate', 'append', 'stack', 'vstack', 'row_stack', 'column_stack', 'hstack', 'dstack', - 'average', 'mean', 'maximum', 'minimum', 'any', 'all', 'around', 'round', 'round_', 'flatnonzero', + 'average', 'mean', 'maximum', 'minimum', 'max', 'min', 'amax', 'amin', 'any', 'all', 'around', + 'round', 'round_', 'flatnonzero', 'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'unravel_index', 'diag_indices_from', 'hanning', 'hamming', 'blackman', 'flip', 'flipud', 'fliplr', 'hypot', 'bitwise_and', 'bitwise_xor', 'bitwise_or', 'rad2deg', 'deg2rad', 'unique', 'lcm', @@ -581,7 +582,7 @@ def argmin(self, axis=None, out=None): # pylint: disable=arguments-differ Refer to `mxnet.numpy.argmax` for full documentation.""" return argmin(self, axis, out) - def clip(self, min=None, max=None, out=None): # pylint: disable=arguments-differ + def clip(self, min=None, max=None, out=None): # pylint: disable=arguments-differ, redefined-outer-name """Return an array whose values are limited to [min, max]. One of max or min must be given. """ @@ -726,11 +727,11 @@ def cumsum(self, axis=None, dtype=None, out=None): def max(self, axis=None, out=None, keepdims=False): # pylint: disable=arguments-differ """Return the maximum along a given axis.""" - return _mx_np_op.max(self, axis=axis, keepdims=keepdims, out=out) + return _npi.max(self, axis=axis, keepdims=keepdims, out=out) def min(self, axis=None, out=None, keepdims=False): # pylint: disable=arguments-differ """Return the minimum along a given axis.""" - return _mx_np_op.min(self, axis=axis, keepdims=keepdims, out=out) + return _npi.min(self, axis=axis, keepdims=keepdims, out=out) def norm(self, *args, **kwargs): """Convenience fluent method for :py:func:`norm`. @@ -4133,6 +4134,190 @@ def minimum(x1, x2, out=None, **kwargs): return _ufunc_helper(x1, x2, _npi.minimum, _np.minimum, _npi.minimum_scalar, None, out) +@set_module('mxnet.symbol.numpy') +def max(a, axis=None, out=None, keepdims=False): + """ + Return the maximum of an array or maximum along an axis. + + Parameters + ---------- + a : _Symbol + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + max : _Symbol + Maximum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + min : + The minimum value of an array along a given axis, ignoring any nan. + maximum : + Element-wise maximum of two arrays, ignoring any nan. + argmax : + Return the indices of the maximum values. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `max` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than + ``max(a, axis=0)``. + """ + return _npi.max(a, axis=axis, keepdims=keepdims, out=out) + + +@set_module('mxnet.symbol.numpy') +def min(a, axis=None, out=None, keepdims=False): + """ + Return the minimum of an array or minimum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + min : ndarray + Minimum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + max : + The maximum value of an array along a given axis, ignoring any nan. + minimum : + Element-wise minimum of two arrays, ignoring any nan. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `min` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than + ``min(a, axis=0)``. + """ + return _npi.min(a, axis=axis, keepdims=keepdims, out=out) + + +@set_module('mxnet.symbol.numpy') +def amax(a, axis=None, out=None, keepdims=False): + """ + Return the maximum of an array or maximum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + max : ndarray + Maximum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + min : + The minimum value of an array along a given axis, ignoring any nan. + maximum : + Element-wise maximum of two arrays, ignoring any nan. + argmax : + Return the indices of the maximum values. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `max` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``maximum(a[0], a[1])`` is faster than + ``max(a, axis=0)``. + """ + return _npi.amax(a, axis=axis, keepdims=keepdims, out=out) + + +@set_module('mxnet.symbol.numpy') +def amin(a, axis=None, out=None, keepdims=False): + """ + Return the minimum of an array or minimum along an axis. + + Parameters + ---------- + a : ndarray + Input data. + axis : int, optional + Axis along which to operate. By default, flattened input is used. + out : ndarray, optional + Alternative output array in which to place the result. Must + be of the same shape and buffer length as the expected output. + See `doc.ufuncs` (Section "Output arguments") for more details. + keepdims : bool, optional + If this is set to True, the axes which are reduced are left + in the result as dimensions with size one. With this option, + the result will broadcast correctly against the original `arr`. + + Returns + ------- + min : ndarray + Minimum of `a`. If `axis` is None, the result is an array of dimension 1. + If `axis` is given, the result is an array of dimension + ``a.ndim - 1``. + + See Also + -------- + max : + The maximum value of an array along a given axis, ignoring any nan. + minimum : + Element-wise minimum of two arrays, ignoring any nan. + + Notes + ----- + NaN in the orginal `numpy` is denoted as nan and will be ignored. + + Don't use `min` for element-wise comparison of 2 arrays; when + ``a.shape[0]`` is 2, ``minimum(a[0], a[1])`` is faster than + ``min(a, axis=0)``. + """ + return _npi.amin(a, axis=axis, keepdims=keepdims, out=out) + + @set_module('mxnet.symbol.numpy') def all(a, axis=None, out=None, keepdims=False): """ diff --git a/python/mxnet/symbol/numpy/linalg.py b/python/mxnet/symbol/numpy/linalg.py index d326b37f0635..adc250510781 100644 --- a/python/mxnet/symbol/numpy/linalg.py +++ b/python/mxnet/symbol/numpy/linalg.py @@ -241,10 +241,10 @@ def norm(x, ord=None, axis=None, keepdims=False): if ord is None: return _npi.norm(x, ord=2, axis=axis, keepdims=keepdims, flag=1) if ord == 'inf': - return _mx_sym_np.max(_symbol.abs(x), axis=axis, keepdims=keepdims) + return _npi.max(_symbol.abs(x), axis=axis, keepdims=keepdims) #return _npi.norm(x, ord=float('inf'), axis=axis, keepdims=keepdims, flag=3) elif ord == '-inf': - return _mx_sym_np.min(_symbol.abs(x), axis=axis, keepdims=keepdims) + return _npi.min(_symbol.abs(x), axis=axis, keepdims=keepdims) #return _npi.norm(x, ord=-float('inf'), axis=axis, keepdims=keepdims, flag=4) elif ord is None: return _npi.norm(x, ord=2, axis=axis, keepdims=keepdims, flag=1) diff --git a/src/api/operator/numpy/np_broadcast_reduce_op_value.cc b/src/api/operator/numpy/np_broadcast_reduce_op_value.cc index 2322860aa609..2c23d5cf5b86 100644 --- a/src/api/operator/numpy/np_broadcast_reduce_op_value.cc +++ b/src/api/operator/numpy/np_broadcast_reduce_op_value.cc @@ -26,6 +26,7 @@ #include #include "../utils.h" #include "../../../operator/tensor/broadcast_reduce_op.h" +#include "../../../operator/numpy/np_broadcast_reduce_op.h" namespace mxnet { @@ -50,4 +51,128 @@ MXNET_REGISTER_API("_npi.broadcast_to") *ret = ndoutputs[0]; }); +MXNET_REGISTER_API("_npi.max") +.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) { + using namespace runtime; + static const nnvm::Op* op = Op::Get("_npi_max"); + nnvm::NodeAttrs attrs; + op::NumpyReduceAxesNoDTypeParam param; + + NDArray* out = args[3].operator mxnet::NDArray*(); + NDArray** outputs = out == nullptr ? nullptr : &out; + int num_outputs = out != nullptr; + if (args[1].type_code() == kNull) { + param.axis = dmlc::nullopt; + } else if (args[1].type_code() == kDLInt) { + param.axis = Tuple(1, args[1].operator int64_t()); + } else { + param.axis = Tuple(args[1].operator ObjectRef()); + } + param.keepdims = args[2].operator bool(); + NDArray* inputs[] = {args[0].operator mxnet::NDArray*()}; + int num_inputs = 1; + attrs.parsed = std::move(param); + attrs.op = op; + SetAttrDict(&attrs); + auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, outputs); + if (out) { + *ret = PythonArg(3); + } else { + *ret = reinterpret_cast(ndoutputs[0]); + } +}); + +MXNET_REGISTER_API("_npi.min") +.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) { + using namespace runtime; + static const nnvm::Op* op = Op::Get("_npi_min"); + nnvm::NodeAttrs attrs; + op::NumpyReduceAxesNoDTypeParam param; + + NDArray* out = args[3].operator mxnet::NDArray*(); + NDArray** outputs = out == nullptr ? nullptr : &out; + int num_outputs = out != nullptr; + if (args[1].type_code() == kNull) { + param.axis = dmlc::nullopt; + } else if (args[1].type_code() == kDLInt) { + param.axis = Tuple(1, args[1].operator int64_t()); + } else { + param.axis = Tuple(args[1].operator ObjectRef()); + } + param.keepdims = args[2].operator bool(); + NDArray* inputs[] = {args[0].operator mxnet::NDArray*()}; + int num_inputs = 1; + attrs.parsed = std::move(param); + attrs.op = op; + SetAttrDict(&attrs); + auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, outputs); + if (out) { + *ret = PythonArg(3); + } else { + *ret = reinterpret_cast(ndoutputs[0]); + } +}); + +MXNET_REGISTER_API("_npi.amax") +.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) { + using namespace runtime; + static const nnvm::Op* op = Op::Get("_npi_amax"); + nnvm::NodeAttrs attrs; + op::NumpyReduceAxesNoDTypeParam param; + + NDArray* out = args[3].operator mxnet::NDArray*(); + NDArray** outputs = out == nullptr ? nullptr : &out; + int num_outputs = out != nullptr; + if (args[1].type_code() == kNull) { + param.axis = dmlc::nullopt; + } else if (args[1].type_code() == kDLInt) { + param.axis = Tuple(1, args[1].operator int64_t()); + } else { + param.axis = Tuple(args[1].operator ObjectRef()); + } + param.keepdims = args[2].operator bool(); + NDArray* inputs[] = {args[0].operator mxnet::NDArray*()}; + int num_inputs = 1; + attrs.parsed = std::move(param); + attrs.op = op; + SetAttrDict(&attrs); + auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, outputs); + if (out) { + *ret = PythonArg(3); + } else { + *ret = reinterpret_cast(ndoutputs[0]); + } +}); + +MXNET_REGISTER_API("_npi.amin") +.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) { + using namespace runtime; + static const nnvm::Op* op = Op::Get("_npi_amin"); + nnvm::NodeAttrs attrs; + op::NumpyReduceAxesNoDTypeParam param; + + NDArray* out = args[3].operator mxnet::NDArray*(); + NDArray** outputs = out == nullptr ? nullptr : &out; + int num_outputs = out != nullptr; + if (args[1].type_code() == kNull) { + param.axis = dmlc::nullopt; + } else if (args[1].type_code() == kDLInt) { + param.axis = Tuple(1, args[1].operator int64_t()); + } else { + param.axis = Tuple(args[1].operator ObjectRef()); + } + param.keepdims = args[2].operator bool(); + NDArray* inputs[] = {args[0].operator mxnet::NDArray*()}; + int num_inputs = 1; + attrs.parsed = std::move(param); + attrs.op = op; + SetAttrDict(&attrs); + auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs, outputs); + if (out) { + *ret = PythonArg(3); + } else { + *ret = reinterpret_cast(ndoutputs[0]); + } +}); + } // namespace mxnet diff --git a/src/operator/numpy/np_broadcast_reduce_op.h b/src/operator/numpy/np_broadcast_reduce_op.h index dfa48440b848..075faf262201 100644 --- a/src/operator/numpy/np_broadcast_reduce_op.h +++ b/src/operator/numpy/np_broadcast_reduce_op.h @@ -84,6 +84,15 @@ struct NumpyReduceAxesNoDTypeParam : public dmlc::Parameter()) .describe("Starting value for the sum."); } + void SetAttrDict(std::unordered_map* dict) { + std::ostringstream axis_s, keepdims_s, initial_s; + axis_s << axis; + keepdims_s << keepdims; + initial_s << initial; + (*dict)["axis"] = axis_s.str(); + (*dict)["keepdims"] = keepdims_s.str(); + (*dict)["initial"] = initial_s.str(); + } }; struct NumpyReduceAxesBoolParam : public dmlc::Parameter { diff --git a/src/operator/numpy/np_broadcast_reduce_op_value.cc b/src/operator/numpy/np_broadcast_reduce_op_value.cc index 026e60e8bb25..fad9327e6ca7 100644 --- a/src/operator/numpy/np_broadcast_reduce_op_value.cc +++ b/src/operator/numpy/np_broadcast_reduce_op_value.cc @@ -165,8 +165,8 @@ inline bool NumpyReduceAxesNoDTypeType(const nnvm::NodeAttrs& attrs, return out_attrs->at(0) != -1 && in_attrs->at(0) != -1; } -NNVM_REGISTER_OP(_np_max) -.add_alias("_np_amax") +NNVM_REGISTER_OP(_npi_max) +.add_alias("_npi_amax") .describe(R"code()code" ADD_FILELINE) .set_num_inputs(1) .set_num_outputs(1) @@ -185,17 +185,17 @@ NNVM_REGISTER_OP(_np_max) return std::vector{ResourceRequest::kTempSpace}; }) .set_attr("THasDeterministicOutput", true) -.set_attr("FGradient", ReduceGrad{"_backward_np_max"}); +.set_attr("FGradient", ReduceGrad{"_backward_npi_max"}); -NNVM_REGISTER_OP(_backward_np_max) +NNVM_REGISTER_OP(_backward_npi_max) .set_num_outputs(1) .set_attr_parser(ParamParser) .set_attr("TIsBackward", true) .set_num_inputs(3) .set_attr("FCompute", NumpyReduceAxesNoDTypeBackward); -NNVM_REGISTER_OP(_np_min) -.add_alias("_np_amin") +NNVM_REGISTER_OP(_npi_min) +.add_alias("_npi_amin") .describe(R"code()code" ADD_FILELINE) .set_num_inputs(1) .set_num_outputs(1) @@ -214,9 +214,9 @@ return std::vector{"a"}; return std::vector{ResourceRequest::kTempSpace}; }) .set_attr("THasDeterministicOutput", true) -.set_attr("FGradient", ReduceGrad{"_backward_np_min"}); +.set_attr("FGradient", ReduceGrad{"_backward_npi_min"}); -NNVM_REGISTER_OP(_backward_np_min) +NNVM_REGISTER_OP(_backward_npi_min) .set_num_outputs(1) .set_attr_parser(ParamParser) .set_attr("TIsBackward", true) diff --git a/src/operator/numpy/np_broadcast_reduce_op_value.cu b/src/operator/numpy/np_broadcast_reduce_op_value.cu index 684348fcaa37..b5cf4f90ce2d 100644 --- a/src/operator/numpy/np_broadcast_reduce_op_value.cu +++ b/src/operator/numpy/np_broadcast_reduce_op_value.cu @@ -32,16 +32,16 @@ NNVM_REGISTER_OP(_np_sum) NNVM_REGISTER_OP(_backward_np_sum) .set_attr("FCompute", NumpyReduceAxesBackwardUseNone); -NNVM_REGISTER_OP(_np_max) +NNVM_REGISTER_OP(_npi_max) .set_attr("FCompute", NumpyReduceAxesNoDTypeCompute); -NNVM_REGISTER_OP(_backward_np_max) +NNVM_REGISTER_OP(_backward_npi_max) .set_attr("FCompute", NumpyReduceAxesNoDTypeBackward); -NNVM_REGISTER_OP(_np_min) +NNVM_REGISTER_OP(_npi_min) .set_attr("FCompute", NumpyReduceAxesNoDTypeCompute); -NNVM_REGISTER_OP(_backward_np_min) +NNVM_REGISTER_OP(_backward_npi_min) .set_attr("FCompute", NumpyReduceAxesNoDTypeBackward); NNVM_REGISTER_OP(_np_prod)