Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Commit

Permalink
[Numpy] Implementation npx.{sample}_n (#16876)
Browse files Browse the repository at this point in the history
* sample_n done

* add gpu register

* move randomness tests to nightly test

* add empty line
  • Loading branch information
xidulu authored and haojin2 committed Nov 23, 2019
1 parent 20f8bbc commit 6c20fb9
Show file tree
Hide file tree
Showing 11 changed files with 703 additions and 38 deletions.
165 changes: 164 additions & 1 deletion python/mxnet/ndarray/numpy_extension/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from ..numpy import _internal as _npi


__all__ = ['bernoulli']
__all__ = ['bernoulli', 'normal_n', 'uniform_n']


def bernoulli(prob, logit, size, dtype, ctx, out):
Expand Down Expand Up @@ -102,3 +102,166 @@ def bernoulli(prob, logit, size, dtype, ctx, out):
else:
return _npi.bernoulli(prob=None, logit=logit, is_logit=True,
size=size, ctx=ctx, dtype=dtype, out=out)


def uniform_n(low=0.0, high=1.0, batch_shape=None, dtype=None, ctx=None):
r"""Draw samples from a uniform distribution.
Samples are uniformly distributed over the half-open interval
``[low, high)`` (includes low, but excludes high). In other words,
any value within the given interval is equally likely to be drawn
by `uniform`.
Parameters
----------
low : float, ndarray, optional
Lower boundary of the output interval. All values generated will be
greater than or equal to low. The default value is 0.
high : float, ndarray, optional
Upper boundary of the output interval. All values generated will be
less than high. The default value is 1.0.
batch_shape : int or tuple of ints, optional
Batch shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k * broadcast(low, high).size`` samples are drawn.
If size is ``None`` (default),
a scalar tensor containing a single value is returned if
``low`` and ``high`` are both scalars. Otherwise,
``np.broadcast(low, high).size`` samples are drawn.
dtype : {'float16', 'float32', 'float64'}, optional
Data type of output samples. Default is 'float32'
ctx : Context, optional
Device context of output. Default is current context.
Returns
-------
out : ndarray
Drawn samples from the parameterized uniform distribution.
See Also
--------
randint : Discrete uniform distribution, yielding integers.
rand : Convenience function that accepts dimensions as input, e.g.,
``rand(2,2)`` would generate a 2-by-2 array of floats,
uniformly distributed over ``[0, 1)``.
Notes
-----
The probability density function of the uniform distribution is
.. math:: p(x) = \frac{1}{b - a}
anywhere within the interval ``[a, b)``, and zero elsewhere.
When ``high`` == ``low``, values of ``low`` will be returned.
If ``high`` < ``low``, the results are officially undefined
and may eventually raise an error, i.e. do not rely on this
function to behave when passed arguments satisfying that
inequality condition.
"""
from ...numpy import ndarray as np_ndarray
input_type = (isinstance(low, np_ndarray), isinstance(high, np_ndarray))
if dtype is None:
dtype = 'float32'
if ctx is None:
ctx = current_context()
if batch_shape == ():
batch_shape = None
if input_type == (True, True):
return _npi.uniform_n(low, high, low=None, high=None, size=batch_shape,
ctx=ctx, dtype=dtype)
elif input_type == (False, True):
return _npi.uniform_n(high, low=low, high=None, size=batch_shape,
ctx=ctx, dtype=dtype)
elif input_type == (True, False):
return _npi.uniform_n(low, low=None, high=high, size=batch_shape,
ctx=ctx, dtype=dtype)
else:
return _npi.uniform_n(low=low, high=high, size=batch_shape,
ctx=ctx, dtype=dtype)


def normal_n(loc=0.0, scale=1.0, batch_shape=None, dtype=None, ctx=None):
r"""Draw random samples from a normal (Gaussian) distribution.
Samples are distributed according to a normal distribution parametrized
by *loc* (mean) and *scale* (standard deviation).
Parameters
----------
loc : float, optional
Mean (centre) of the distribution.
scale : float, optional
Standard deviation (spread or "width") of the distribution.
batch_shape : int or tuple of ints, optional
Batch shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k * broadcast(low, high).size`` samples are drawn.
If size is ``None`` (default),
a scalar tensor containing a single value is returned if
``low`` and ``high`` are both scalars. Otherwise,
``np.broadcast(loc, scale).size`` samples are drawn.
dtype : {'float16', 'float32', 'float64'}, optional
Data type of output samples. Default is 'float32'
ctx : Context, optional
Device context of output, default is current context.
Returns
-------
out : ndarray
Drawn samples from the parameterized normal distribution.
Notes
-----
The probability density for the Gaussian distribution is
.. math:: p(x) = \frac{1}{\sqrt{ 2 \pi \sigma^2 }}
e^{ - \frac{ (x - \mu)^2 } {2 \sigma^2} },
where :math:`\mu` is the mean and :math:`\sigma` the standard
deviation. The square of the standard deviation, :math:`\sigma^2`,
is called the variance.
The function has its peak at the mean, and its "spread" increases with
the standard deviation (the function reaches 0.607 times its maximum at
:math:`x + \sigma` and :math:`x - \sigma` [2]_). This implies that
`numpy.random.normal` is more likely to return samples lying close to
the mean, rather than those far away.
References
----------
.. [1] Wikipedia, "Normal distribution",
https://en.wikipedia.org/wiki/Normal_distribution
.. [2] P. R. Peebles Jr., "Central Limit Theorem" in "Probability,
Random Variables and Random Signal Principles", 4th ed., 2001,
pp. 51, 51, 125.
Examples
--------
>>> mu, sigma = 0, 0.1 # mean and standard deviation
>>> s = np.random.normal(mu, sigma, 1000)
Verify the mean and the variance:
>>> np.abs(mu - np.mean(s)) < 0.01
array(True)
"""
from ...numpy import ndarray as np_ndarray
input_type = (isinstance(loc, np_ndarray), isinstance(scale, np_ndarray))
if dtype is None:
dtype = 'float32'
if ctx is None:
ctx = current_context()
if batch_shape == ():
batch_shape = None
if input_type == (True, True):
return _npi.normal_n(loc, scale, loc=None, scale=None, size=batch_shape,
ctx=ctx, dtype=dtype)
elif input_type == (False, True):
return _npi.normal_n(scale, loc=loc, scale=None, size=batch_shape,
ctx=ctx, dtype=dtype)
elif input_type == (True, False):
return _npi.normal_n(loc, loc=None, scale=scale, size=batch_shape,
ctx=ctx, dtype=dtype)
else:
return _npi.normal_n(loc=loc, scale=scale, size=batch_shape,
ctx=ctx, dtype=dtype)
127 changes: 126 additions & 1 deletion python/mxnet/numpy_extension/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ..ndarray import numpy_extension as _mx_nd_npx


__all__ = ['seed', 'bernoulli']
__all__ = ['seed', 'bernoulli', 'normal_n', 'uniform_n']


def seed(seed, ctx='all'): # pylint: disable=redefined-outer-name
Expand Down Expand Up @@ -126,3 +126,128 @@ def bernoulli(prob=None, logit=None, size=None, dtype=None, ctx=None, out=None):
[1., 0., 1., 0.]])
"""
return _mx_nd_npx.random.bernoulli(prob, logit, size, dtype, ctx, out)


def uniform_n(low=0.0, high=1.0, batch_shape=None, dtype=None, ctx=None):
r"""Draw samples from a uniform distribution.
Samples are uniformly distributed over the half-open interval
``[low, high)`` (includes low, but excludes high). In other words,
any value within the given interval is equally likely to be drawn
by `uniform`.
Parameters
----------
low : float, ndarray, optional
Lower boundary of the output interval. All values generated will be
greater than or equal to low. The default value is 0.
high : float, ndarray, optional
Upper boundary of the output interval. All values generated will be
less than high. The default value is 1.0.
batch_shape : int or tuple of ints, optional
Batch shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k * broadcast(low, high).size`` samples are drawn.
If size is ``None`` (default),
a scalar tensor containing a single value is returned if
``low`` and ``high`` are both scalars. Otherwise,
``np.broadcast(low, high).size`` samples are drawn.
dtype : {'float16', 'float32', 'float64'}, optional
Data type of output samples. Default is 'float32'
ctx : Context, optional
Device context of output. Default is current context.
Returns
-------
out : ndarray
Drawn samples from the parameterized uniform distribution.
See Also
--------
randint : Discrete uniform distribution, yielding integers.
rand : Convenience function that accepts dimensions as input, e.g.,
``rand(2,2)`` would generate a 2-by-2 array of floats,
uniformly distributed over ``[0, 1)``.
Notes
-----
The probability density function of the uniform distribution is
.. math:: p(x) = \frac{1}{b - a}
anywhere within the interval ``[a, b)``, and zero elsewhere.
When ``high`` == ``low``, values of ``low`` will be returned.
If ``high`` < ``low``, the results are officially undefined
and may eventually raise an error, i.e. do not rely on this
function to behave when passed arguments satisfying that
inequality condition.
"""
return _mx_nd_npx.random.uniform_n(low, high, batch_shape=batch_shape, ctx=ctx, dtype=dtype)


def normal_n(loc=0.0, scale=1.0, batch_shape=None, dtype=None, ctx=None):
r"""Draw random samples from a normal (Gaussian) distribution.
Samples are distributed according to a normal distribution parametrized
by *loc* (mean) and *scale* (standard deviation).
Parameters
----------
loc : float, optional
Mean (centre) of the distribution.
scale : float, optional
Standard deviation (spread or "width") of the distribution.
batch_shape : int or tuple of ints, optional
Batch shape. If the given shape is, e.g., ``(m, n, k)``, then
``m * n * k * broadcast(low, high).size`` samples are drawn.
If size is ``None`` (default),
a scalar tensor containing a single value is returned if
``low`` and ``high`` are both scalars. Otherwise,
``np.broadcast(loc, scale).size`` samples are drawn.
dtype : {'float16', 'float32', 'float64'}, optional
Data type of output samples. Default is 'float32'
ctx : Context, optional
Device context of output, default is current context.
Returns
-------
out : ndarray
Drawn samples from the parameterized normal distribution.
Notes
-----
The probability density for the Gaussian distribution is
.. math:: p(x) = \frac{1}{\sqrt{ 2 \pi \sigma^2 }}
e^{ - \frac{ (x - \mu)^2 } {2 \sigma^2} },
where :math:`\mu` is the mean and :math:`\sigma` the standard
deviation. The square of the standard deviation, :math:`\sigma^2`,
is called the variance.
The function has its peak at the mean, and its "spread" increases with
the standard deviation (the function reaches 0.607 times its maximum at
:math:`x + \sigma` and :math:`x - \sigma` [2]_). This implies that
`numpy.random.normal` is more likely to return samples lying close to
the mean, rather than those far away.
References
----------
.. [1] Wikipedia, "Normal distribution",
https://en.wikipedia.org/wiki/Normal_distribution
.. [2] P. R. Peebles Jr., "Central Limit Theorem" in "Probability,
Random Variables and Random Signal Principles", 4th ed., 2001,
pp. 51, 51, 125.
Examples
--------
>>> mu, sigma = 0, 0.1 # mean and standard deviation
>>> s = np.random.normal(mu, sigma, 1000)
Verify the mean and the variance:
>>> np.abs(mu - np.mean(s)) < 0.01
array(True)
"""
return _mx_nd_npx.random.normal_n(loc, scale, batch_shape, dtype, ctx)
Loading

0 comments on commit 6c20fb9

Please sign in to comment.