You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by ha...@apache.org on 2019/08/13 03:53:49 UTC
[incubator-mxnet] branch master updated: numpy linspace (#15852)
This is an automated email from the ASF dual-hosted git repository.
haoj 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 795990b numpy linspace (#15852)
795990b is described below
commit 795990b81b3fd40fed0dbea801dc33dfb6475a00
Author: Jake Lee <gs...@gmail.com>
AuthorDate: Mon Aug 12 20:52:43 2019 -0700
numpy linspace (#15852)
---
python/mxnet/ndarray/numpy/_op.py | 100 ++++++++++++++++++++++++++++++++-
python/mxnet/numpy/multiarray.py | 88 ++++++++++++++++++++++++++++-
python/mxnet/symbol/numpy/_symbol.py | 75 ++++++++++++++++++++++++-
src/operator/tensor/init_op.cc | 1 +
tests/python/unittest/test_numpy_op.py | 70 +++++++++++++++++++++++
5 files changed, 331 insertions(+), 3 deletions(-)
diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py
index caa9ba1..0cc2192 100644
--- a/python/mxnet/ndarray/numpy/_op.py
+++ b/python/mxnet/ndarray/numpy/_op.py
@@ -24,8 +24,9 @@ from ...base import numeric_types
from ...util import set_module
from ...context import current_context
from . import _internal as _npi
+from ..ndarray import NDArray
-__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'tensordot']
+__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'tensordot', 'linspace']
@set_module('mxnet.ndarray.numpy')
@@ -364,3 +365,100 @@ def tensordot(a, b, axes=2):
raise ValueError('Axes length mismatch')
return _npi.tensordot(a, b, a_axes_summed, b_axes_summed)
+
+
+def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0, ctx=None): # pylint: disable=too-many-arguments
+ r"""
+ Return evenly spaced numbers over a specified interval.
+
+ Returns num evenly spaced samples, calculated over the interval [start, stop].
+ The endpoint of the interval can optionally be excluded.
+
+ Parameters
+ ----------
+ start : real number
+ The starting value of the sequence.
+ stop : real number
+ The end value of the sequence, unless endpoint is set to False. In
+ that case, the sequence consists of all but the last of num + 1
+ evenly spaced samples, so that stop is excluded. Note that the step
+ size changes when endpoint is False.
+ num : int, optional
+ Number of samples to generate. Default is 50. Must be non-negative.
+ endpoint : bool, optional
+ If True, stop is the last sample. Otherwise, it is not included.
+ Default is True.
+ retstep : bool, optional
+ If True, return (samples, step), where step is the spacing between samples.
+ dtype : dtype, optional
+ The type of the output array. If dtype is not given, infer the data
+ type from the other input arguments.
+ axis : int, optional
+ The axis in the result to store the samples. Relevant only if start or
+ stop are array-like. By default (0), the samples will be along a new
+ axis inserted at the beginning. Use -1 to get an axis at the end.
+
+ Returns
+ -------
+ samples : ndarray
+ There are num equally spaced samples in the closed interval
+ `[start, stop]` or the half-open interval `[start, stop)`
+ (depending on whether endpoint is True or False).
+ step : float, optional
+ Only returned if retstep is True
+ Size of spacing between samples.
+
+
+ See Also
+ --------
+ arange : Similar to `linspace`, but uses a step size (instead of the
+ number of samples).
+
+ Examples
+ --------
+ >>> np.linspace(2.0, 3.0, num=5)
+ array([2. , 2.25, 2.5 , 2.75, 3. ])
+ >>> np.linspace(2.0, 3.0, num=5, endpoint=False)
+ array([2. , 2.2, 2.4, 2.6, 2.8])
+ >>> np.linspace(2.0, 3.0, num=5, retstep=True)
+ (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
+
+ Graphical illustration:
+
+ >>> import matplotlib.pyplot as plt
+ >>> N = 8
+ >>> y = np.zeros(N)
+ >>> x1 = np.linspace(0, 10, N, endpoint=True)
+ >>> x2 = np.linspace(0, 10, N, endpoint=False)
+ >>> plt.plot(x1.asnumpy(), y.asnumpy(), 'o')
+ [<matplotlib.lines.Line2D object at 0x...>]
+ >>> plt.plot(x2.asnumpy(), (y + 0.5).asnumpy(), 'o')
+ [<matplotlib.lines.Line2D object at 0x...>]
+ >>> plt.ylim([-0.5, 1])
+ (-0.5, 1)
+ >>> plt.show()
+
+ Notes
+ -----
+
+ This function differs from the original `numpy.linspace
+ <https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html>`_ in
+ the following aspects:
+
+ - `start` and `stop` do not support list, numpy ndarray and mxnet ndarray
+ - axis could only be 0
+ - There could be an additional `ctx` argument to specify the device, e.g. the i-th
+ GPU.
+ """
+ if isinstance(start, (list, _np.ndarray, NDArray)) or \
+ isinstance(stop, (list, _np.ndarray, NDArray)):
+ raise NotImplementedError('start and stop only support int')
+ if axis != 0:
+ raise NotImplementedError("the function only support axis 0")
+ if ctx is None:
+ ctx = current_context()
+ if retstep:
+ step = (stop - start) / (num - 1)
+ return _npi.linspace(start=start, stop=stop, num=num, endpoint=endpoint, ctx=ctx, dtype=dtype), step
+ else:
+ return _npi.linspace(start=start, stop=stop, num=num, endpoint=endpoint, ctx=ctx, dtype=dtype)
diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py
index f4b6e73..8a9028b 100644
--- a/python/mxnet/numpy/multiarray.py
+++ b/python/mxnet/numpy/multiarray.py
@@ -44,7 +44,7 @@ from ..ndarray import numpy as _mx_nd_np
from ..ndarray.numpy import _internal as _npi
__all__ = ['ndarray', 'empty', 'array', 'zeros', 'ones', 'add', 'subtract', 'multiply', 'divide',
- 'mod', 'power', 'tensordot']
+ 'mod', 'power', 'tensordot', 'linspace']
# This function is copied from ndarray.py since pylint
@@ -1606,3 +1606,89 @@ def tensordot(a, b, axes=2):
[ 4928., 5306.]])
"""
return _mx_nd_np.tensordot(a, b, axes)
+
+
+def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0, ctx=None): # pylint: disable=too-many-arguments
+ r"""
+ Return evenly spaced numbers over a specified interval.
+
+ Returns num evenly spaced samples, calculated over the interval [start, stop].
+ The endpoint of the interval can optionally be excluded.
+
+ Parameters
+ ----------
+ start : real number
+ The starting value of the sequence.
+ stop : real number
+ The end value of the sequence, unless endpoint is set to False. In
+ that case, the sequence consists of all but the last of num + 1
+ evenly spaced samples, so that stop is excluded. Note that the step
+ size changes when endpoint is False.
+ num : int, optional
+ Number of samples to generate. Default is 50. Must be non-negative.
+ endpoint : bool, optional
+ If True, stop is the last sample. Otherwise, it is not included.
+ Default is True.
+ retstep : bool, optional
+ If True, return (samples, step), where step is the spacing between samples.
+ dtype : dtype, optional
+ The type of the output array. If dtype is not given, infer the data
+ type from the other input arguments.
+ axis : int, optional
+ The axis in the result to store the samples. Relevant only if start or
+ stop are array-like. By default (0), the samples will be along a new
+ axis inserted at the beginning. Use -1 to get an axis at the end.
+
+ Returns
+ -------
+ samples : ndarray
+ There are num equally spaced samples in the closed interval
+ `[start, stop]` or the half-open interval `[start, stop)`
+ (depending on whether endpoint is True or False).
+ step : float, optional
+ Only returned if retstep is True
+ Size of spacing between samples.
+
+
+ See Also
+ --------
+ arange : Similar to `linspace`, but uses a step size (instead of the
+ number of samples).
+
+ Examples
+ --------
+ >>> np.linspace(2.0, 3.0, num=5)
+ array([2. , 2.25, 2.5 , 2.75, 3. ])
+ >>> np.linspace(2.0, 3.0, num=5, endpoint=False)
+ array([2. , 2.2, 2.4, 2.6, 2.8])
+ >>> np.linspace(2.0, 3.0, num=5, retstep=True)
+ (array([2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
+
+ Graphical illustration:
+
+ >>> import matplotlib.pyplot as plt
+ >>> N = 8
+ >>> y = np.zeros(N)
+ >>> x1 = np.linspace(0, 10, N, endpoint=True)
+ >>> x2 = np.linspace(0, 10, N, endpoint=False)
+ >>> plt.plot(x1.asnumpy(), y.asnumpy(), 'o')
+ [<matplotlib.lines.Line2D object at 0x...>]
+ >>> plt.plot(x2.asnumpy(), (y + 0.5).asnumpy(), 'o')
+ [<matplotlib.lines.Line2D object at 0x...>]
+ >>> plt.ylim([-0.5, 1])
+ (-0.5, 1)
+ >>> plt.show()
+
+ Notes
+ -----
+
+ This function differs from the original `numpy.linspace
+ <https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html>`_ in
+ the following aspects:
+
+ - `start` and `stop` do not support list, numpy ndarray and mxnet ndarray
+ - axis could only be 0
+ - There could be an additional `ctx` argument to specify the device, e.g. the i-th
+ GPU.
+ """
+ return _mx_nd_np.linspace(start, stop, num, endpoint, retstep, dtype, axis, ctx)
diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py
index 65db429..d013793 100644
--- a/python/mxnet/symbol/numpy/_symbol.py
+++ b/python/mxnet/symbol/numpy/_symbol.py
@@ -28,7 +28,7 @@ from ..symbol import Symbol
from .._internal import _set_np_symbol_class
from . import _internal as _npi
-__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'tensordot']
+__all__ = ['zeros', 'ones', 'add', 'subtract', 'multiply', 'divide', 'mod', 'power', 'tensordot', 'linspace']
def _num_outputs(sym):
@@ -1065,4 +1065,77 @@ def tensordot(a, b, axes=2):
return _npi.tensordot(a, b, a_axes_summed, b_axes_summed)
+def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0, ctx=None): # pylint: disable=too-many-arguments
+ r"""
+ Return evenly spaced numbers over a specified interval.
+
+ Returns num evenly spaced samples, calculated over the interval [start, stop].
+ The endpoint of the interval can optionally be excluded.
+
+ Parameters
+ ----------
+ start : real number
+ The starting value of the sequence.
+ stop : real number
+ The end value of the sequence, unless endpoint is set to False. In
+ that case, the sequence consists of all but the last of num + 1
+ evenly spaced samples, so that stop is excluded. Note that the step
+ size changes when endpoint is False.
+ num : int, optional
+ Number of samples to generate. Default is 50. Must be non-negative.
+ endpoint : bool, optional
+ If True, stop is the last sample. Otherwise, it is not included.
+ Default is True.
+ retstep : bool, optional
+ If True, return (samples, step), where step is the spacing between samples.
+ dtype : dtype, optional
+ The type of the output array. If dtype is not given, infer the data
+ type from the other input arguments.
+ axis : int, optional
+ The axis in the result to store the samples. Relevant only if start or
+ stop are array-like. By default (0), the samples will be along a new
+ axis inserted at the beginning. Use -1 to get an axis at the end.
+
+ Returns
+ -------
+ samples : _Symbol
+ There are num equally spaced samples in the closed interval
+ `[start, stop]` or the half-open interval `[start, stop)`
+ (depending on whether endpoint is True or False).
+ step : float, optional
+ Only returned if retstep is True
+ Size of spacing between samples.
+
+
+ See Also
+ --------
+ arange : Similar to `linspace`, but uses a step size (instead of the
+ number of samples).
+
+ Notes
+ -----
+
+ This function differs from the original `numpy.linspace
+ <https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html>`_ in
+ the following aspects:
+
+ - `start` and `stop` do not support list, numpy ndarray and mxnet ndarray
+ - axis could only be 0
+ - There could be an additional `ctx` argument to specify the device, e.g. the i-th
+ GPU.
+ """
+ if isinstance(start, (list, _np.ndarray)) or \
+ isinstance(stop, (list, _np.ndarray)):
+ raise NotImplementedError('start and stop only support int')
+ if axis != 0:
+ raise NotImplementedError("the function only support axis 0")
+ if ctx is None:
+ ctx = current_context()
+ if retstep:
+ step = (stop - start) / (num - 1)
+ return (_npi.linspace(start=start, stop=stop, num=num, endpoint=endpoint, ctx=ctx, dtype=dtype), step)
+ else:
+ return _npi.linspace(start=start, stop=stop, num=num, endpoint=endpoint, ctx=ctx, dtype=dtype)
+
+
_set_np_symbol_class(_Symbol)
diff --git a/src/operator/tensor/init_op.cc b/src/operator/tensor/init_op.cc
index 239cff7..172665f 100644
--- a/src/operator/tensor/init_op.cc
+++ b/src/operator/tensor/init_op.cc
@@ -138,6 +138,7 @@ Examples::
.add_arguments(RangeLikeParam::__FIELDS__());
NNVM_REGISTER_OP(_linspace)
+.add_alias("_npi_linspace")
.describe("Return evenly spaced numbers over a specified interval. Similar to Numpy")
.set_num_inputs(0)
.set_num_outputs(1)
diff --git a/tests/python/unittest/test_numpy_op.py b/tests/python/unittest/test_numpy_op.py
index b0388d7..12d9f77 100644
--- a/tests/python/unittest/test_numpy_op.py
+++ b/tests/python/unittest/test_numpy_op.py
@@ -277,6 +277,76 @@ def test_np_sum():
@with_seed()
@use_np
+def test_np_linspace():
+ configs = [
+ (0.0, 1.0, 10),
+ (-2, 4, 30),
+ (5.234324, 8.98324, 324),
+ (2, 10, 100)
+ ]
+ exception_configs = [
+ (0, 10, -1),
+ (0, 1, 2.5)
+ ]
+ dtypes = ['int32', 'float16', 'float32', 'float64', None]
+ for config in configs:
+ for dtype in dtypes:
+ for endpoint in [False, True]:
+ for retstep in [False, True]:
+ if isinstance(config, tuple):
+ mx_ret = np.linspace(*config, endpoint=endpoint, retstep=retstep, dtype=dtype)
+ np_ret = _np.linspace(*config, endpoint=endpoint, retstep=retstep, dtype=dtype)
+ else:
+ mx_ret = np.linspace(config, endpoint=endpoint, retstep=retstep, dtype=dtype)
+ np_ret = _np.linspace(config, endpoint=endpoint, retstep=retstep, dtype=dtype)
+ if retstep:
+ assert_almost_equal(mx_ret[0].asnumpy(), np_ret[0], atol=1e-3, rtol=1e-5)
+ same(mx_ret[1], np_ret[1])
+ else:
+ assert_almost_equal(mx_ret.asnumpy(), np_ret, atol=1e-3, rtol=1e-5)
+ # check for exception input
+ for config in exception_configs:
+ assertRaises(MXNetError, np.linspace, *config)
+ # check linspace equivalent to arange
+ for test_index in range(1000):
+ assert_almost_equal(mx.np.linspace(0, test_index, test_index + 1).asnumpy(), _np.arange(test_index + 1))
+ @use_np
+ class TestLinspace(HybridBlock):
+ def __init__(self, start, stop, num=50, endpoint=None, retstep=False, dtype=None, axis=0):
+ super(TestLinspace, self).__init__()
+ self._start = start
+ self._stop = stop
+ self._num = num
+ self._endpoint = endpoint
+ self._retstep = retstep
+ self._dtype = dtype
+
+ def hybrid_forward(self, F, x):
+ if self._retstep:
+ raise ValueError("linspace didn't support retstep = True inside HybridBlock")
+ else:
+ return x + F.np.linspace(self._start, self._stop, self._num, \
+ self._endpoint, self._retstep, self._dtype)
+
+ for dtype in dtypes:
+ x = np.zeros(shape=(), dtype=dtype)
+ for config in configs:
+ for hybridize in [False, True]:
+ for endpoint in [False, True]:
+ if isinstance(config, tuple):
+ net = TestLinspace(*config, endpoint=endpoint, dtype=dtype)
+ np_out = _np.linspace(*config, endpoint=endpoint, dtype=dtype)
+ else:
+ net = TestLinspace(config, endpoint=endpoint, dtype=dtype)
+ np_out = _np.linspace(config, endpoint=endpoint, dtype=dtype)
+ if hybridize:
+ net.hybridize()
+ mx_out = net(x)
+ assert_almost_equal(mx_out.asnumpy(), np_out, atol=1e-3, rtol=1e-5)
+
+
+@with_seed()
+@use_np
def test_npx_slice():
class TestSlice(HybridBlock):
def __init__(self, begin, end, step):