From 392448f2dd6d2e463ec356ea54af634f6423a56f Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 21 Aug 2019 03:20:57 +0000 Subject: [PATCH 1/5] randint completed --- python/mxnet/ndarray/numpy/random.py | 63 +++++++++++++++++++++++++- python/mxnet/numpy/random.py | 52 ++++++++++++++++++++- python/mxnet/symbol/numpy/random.py | 63 +++++++++++++++++++++++++- src/operator/random/sample_op.cc | 1 + tests/python/unittest/test_numpy_op.py | 46 +++++++++++++++++++ 5 files changed, 222 insertions(+), 3 deletions(-) diff --git a/python/mxnet/ndarray/numpy/random.py b/python/mxnet/ndarray/numpy/random.py index 339fb1e77920..362ad5be6bbd 100644 --- a/python/mxnet/ndarray/numpy/random.py +++ b/python/mxnet/ndarray/numpy/random.py @@ -17,5 +17,66 @@ """Namespace for operators used in Gluon dispatched by F=ndarray.""" from __future__ import absolute_import +from ...context import current_context +from . import _internal as _npi -__all__ = [] +__all__ = ['randint'] + + +def randint(low, high=None, size=None, dtype=None, **kwargs): + """Return random integers from `low` (inclusive) to `high` (exclusive). + + Return random integers from the "discrete uniform" distribution of + the specified dtype in the "half-open" interval [`low`, `high`). If + `high` is None (the default), then results are from [0, `low`). + + Parameters + ---------- + low : int + Lowest (signed) integer to be drawn from the distribution (unless + ``high=None``, in which case this parameter is one above the + *highest* such integer). + high : int, optional + If provided, one above the largest (signed) integer to be drawn + from the distribution (see above for behavior if ``high=None``). + size : int or tuple of ints, optional + Output shape. If the given shape is, e.g., ``(m, n, k)``, then + ``m * n * k`` samples are drawn. Default is None, in which case a + single value is returned. + dtype : dtype, optional + Desired dtype of the result. All dtypes are determined by their + name, i.e., 'int64', 'int', etc, so byteorder is not available + and a specific precision may have different C types depending + on the platform. The default value is 'np.int'. + + Returns + ------- + out : ndarray of ints + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + + Examples + -------- + >>> np.random.randint(2, size=10) + array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) + >>> np.random.randint(1, size=10) + array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + + Generate a 2 x 4 array of ints between 0 and 4, inclusive: + + >>> np.random.randint(5, size=(2, 4)) + array([[4, 0, 2, 1], + [3, 2, 2, 0]]) + """ + ctx = kwargs.pop('ctx', None) + out = kwargs.pop('out', None) + if dtype is None: + dtype = 'int' + if ctx is None: + ctx = current_context() + if size is None: + size = 1 + if high is None: + high = low + low = 0 + return _npi.random_randint(low, high, shape=size, dtype=dtype, ctx=ctx, out=out) diff --git a/python/mxnet/numpy/random.py b/python/mxnet/numpy/random.py index c4109378e146..3aff551622cf 100644 --- a/python/mxnet/numpy/random.py +++ b/python/mxnet/numpy/random.py @@ -18,5 +18,55 @@ """Namespace for ops used in imperative programming.""" from __future__ import absolute_import +from ..ndarray import numpy as _mx_nd_np -__all__ = [] + +__all__ = ["randint"] + + +def randint(low, high=None, size=None, dtype=None, **kwargs): + """Return random integers from `low` (inclusive) to `high` (exclusive). + + Return random integers from the "discrete uniform" distribution of + the specified dtype in the "half-open" interval [`low`, `high`). If + `high` is None (the default), then results are from [0, `low`). + + Parameters + ---------- + low : int + Lowest (signed) integer to be drawn from the distribution (unless + ``high=None``, in which case this parameter is one above the + *highest* such integer). + high : int, optional + If provided, one above the largest (signed) integer to be drawn + from the distribution (see above for behavior if ``high=None``). + size : int or tuple of ints, optional + Output shape. If the given shape is, e.g., ``(m, n, k)``, then + ``m * n * k`` samples are drawn. Default is None, in which case a + single value is returned. + dtype : dtype, optional + Desired dtype of the result. All dtypes are determined by their + name, i.e., 'int64', 'int', etc, so byteorder is not available + and a specific precision may have different C types depending + on the platform. The default value is 'np.int'. + + Returns + ------- + out : ndarray of ints + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + + Examples + -------- + >>> np.random.randint(2, size=10) + array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) + >>> np.random.randint(1, size=10) + array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + + Generate a 2 x 4 array of ints between 0 and 4, inclusive: + + >>> np.random.randint(5, size=(2, 4)) + array([[4, 0, 2, 1], + [3, 2, 2, 0]]) + """ + return _mx_nd_np.random.randint(low, high, size, dtype, **kwargs) diff --git a/python/mxnet/symbol/numpy/random.py b/python/mxnet/symbol/numpy/random.py index 28cfd0f3806a..461de83c5c55 100644 --- a/python/mxnet/symbol/numpy/random.py +++ b/python/mxnet/symbol/numpy/random.py @@ -18,5 +18,66 @@ """Namespace for operators used in Gluon dispatched by F=symbol.""" from __future__ import absolute_import +from ...context import current_context +from . import _internal as _npi -__all__ = [] +__all__ = ['randint'] + + +def randint(low, high=None, size=None, dtype=None, **kwargs): + """Return random integers from `low` (inclusive) to `high` (exclusive). + + Return random integers from the "discrete uniform" distribution of + the specified dtype in the "half-open" interval [`low`, `high`). If + `high` is None (the default), then results are from [0, `low`). + + Parameters + ---------- + low : int + Lowest (signed) integer to be drawn from the distribution (unless + ``high=None``, in which case this parameter is one above the + *highest* such integer). + high : int, optional + If provided, one above the largest (signed) integer to be drawn + from the distribution (see above for behavior if ``high=None``). + size : int or tuple of ints, optional + Output shape. If the given shape is, e.g., ``(m, n, k)``, then + ``m * n * k`` samples are drawn. Default is None, in which case a + single value is returned. + dtype : dtype, optional + Desired dtype of the result. All dtypes are determined by their + name, i.e., 'int64', 'int', etc, so byteorder is not available + and a specific precision may have different C types depending + on the platform. The default value is 'np.int'. + + Returns + ------- + out : symbol + `size`-shaped array of random integers from the appropriate + distribution, or a single such random int if `size` not provided. + + Examples + -------- + >>> np.random.randint(2, size=10) + array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0]) + >>> np.random.randint(1, size=10) + array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + + Generate a 2 x 4 array of ints between 0 and 4, inclusive: + + >>> np.random.randint(5, size=(2, 4)) + array([[4, 0, 2, 1], + [3, 2, 2, 0]]) + """ + ctx = kwargs.pop('ctx', None) + out = kwargs.pop('out', None) + if dtype is None: + dtype = 'int' + if ctx is None: + ctx = current_context() + if size is None: + size = 1 + if high is None: + high = low + low = 0 + return _npi.random_randint(low, high, shape=size, dtype=dtype, ctx=ctx, out=out) diff --git a/src/operator/random/sample_op.cc b/src/operator/random/sample_op.cc index 543146257ddf..d5b5e288258c 100644 --- a/src/operator/random/sample_op.cc +++ b/src/operator/random/sample_op.cc @@ -182,6 +182,7 @@ Example:: MXNET_OPERATOR_REGISTER_SAMPLE(_random_randint, SampleRandIntParam) .add_alias("random_randint") +.add_alias("_npi_random_randint") .describe(R"code(Draw random samples from a discrete uniform distribution. Samples are uniformly distributed over the half-open interval *[low, high)* diff --git a/tests/python/unittest/test_numpy_op.py b/tests/python/unittest/test_numpy_op.py index 6a1a6a6dfd5d..38fb52809fbe 100644 --- a/tests/python/unittest/test_numpy_op.py +++ b/tests/python/unittest/test_numpy_op.py @@ -28,6 +28,8 @@ from common import assertRaises, with_seed import random import collections +import scipy.stats as ss +from mxnet.test_utils import verify_generator, gen_buckets_probs_with_ppf, retry @with_seed() @@ -931,6 +933,50 @@ def hybrid_forward(self, F, a, *args): assert same(mx_out.asnumpy(), np_out) +@with_seed() +@use_np +def test_np_randint(): + ctx = mx.context.current_context() + # test shapes + params = [ + (0, 10), + (5, None) + ] + shapes = [ + (3, 3), + (3, 4), + (0, 0), + (3, 3, 3), + (0, 0, 0), + (2, 2, 4, 3), + (2, 2, 4, 3), + (2, 0, 3, 0), + (2, 0, 2, 3) + ] + for shape in shapes: + for (low, high) in params: + data_mx = np.random.randint(low, high, size=shape) + assert data_mx.shape == shape + + # test generator + for dtype in ['int32', 'int64']: + for low, high in [(50000000, 50001000),(-50000100,-50000000),(-500,199)]: + scale = high - low + buckets, probs = gen_buckets_probs_with_ppf(lambda x: ss.uniform.ppf(x, loc=low, scale=scale), 5) + # Quantize bucket boundaries to reflect the actual dtype and adjust probs accordingly + buckets = _np.array(buckets, dtype=dtype).tolist() + probs = [(buckets[i][1] - buckets[i][0]) / float(scale) for i in range(5)] + generator_mx = lambda x: np.random.randint(low, high, size=x, dtype=dtype, ctx=ctx).asnumpy() + verify_generator(generator=generator_mx, buckets=buckets, probs=probs, nrepeat=100) + # Scipy uses alpha = 0.01 for testing discrete distribution generator but we are using default alpha=0.05 (higher threshold ensures robustness) + # Refer - https://github.com/scipy/scipy/blob/9f12af697763fb5f9767d5cb1280ce62456a3974/scipy/stats/tests/test_discrete_basic.py#L45 + generator_mx_same_seed = \ + lambda x: _np.concatenate( + [np.random.randint(low, high, size=x // 10, dtype=dtype, ctx=ctx).asnumpy() + for _ in range(10)]) + verify_generator(generator=generator_mx_same_seed, buckets=buckets, probs=probs, nrepeat=100) + + if __name__ == '__main__': import nose nose.runmodule() From 37453b416f08146ab679dda5dc9b486a0330b147 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Thu, 22 Aug 2019 04:43:43 +0000 Subject: [PATCH 2/5] doc fixed --- python/mxnet/ndarray/numpy/random.py | 4 ++++ python/mxnet/numpy/random.py | 4 ++++ python/mxnet/symbol/numpy/random.py | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/python/mxnet/ndarray/numpy/random.py b/python/mxnet/ndarray/numpy/random.py index edf21c8bdefb..71707d41c8e8 100644 --- a/python/mxnet/ndarray/numpy/random.py +++ b/python/mxnet/ndarray/numpy/random.py @@ -49,6 +49,10 @@ def randint(low, high=None, size=None, dtype=None, **kwargs): name, i.e., 'int64', 'int', etc, so byteorder is not available and a specific precision may have different C types depending on the platform. The default value is 'np.int'. + ctx : Context, optional + Device context of output. Default is current context. + out : ndarray, optional + The output ndarray (default is `None`). Returns ------- diff --git a/python/mxnet/numpy/random.py b/python/mxnet/numpy/random.py index f0ec84a3d683..f0fd43eb0e70 100644 --- a/python/mxnet/numpy/random.py +++ b/python/mxnet/numpy/random.py @@ -49,6 +49,10 @@ def randint(low, high=None, size=None, dtype=None, **kwargs): name, i.e., 'int64', 'int', etc, so byteorder is not available and a specific precision may have different C types depending on the platform. The default value is 'np.int'. + ctx : Context, optional + Device context of output. Default is current context. + out : ndarray, optional + The output ndarray (default is `None`). Returns ------- diff --git a/python/mxnet/symbol/numpy/random.py b/python/mxnet/symbol/numpy/random.py index 3d396a7c774b..86d0ba3095e1 100644 --- a/python/mxnet/symbol/numpy/random.py +++ b/python/mxnet/symbol/numpy/random.py @@ -50,6 +50,10 @@ def randint(low, high=None, size=None, dtype=None, **kwargs): name, i.e., 'int64', 'int', etc, so byteorder is not available and a specific precision may have different C types depending on the platform. The default value is 'np.int'. + ctx : Context, optional + Device context of output. Default is current context. + out : symbol, optional + The output symbol (default is `None`). Returns ------- From 34ec25d2fad5ad6cc7233ce3015bdbfe440cb494 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Thu, 22 Aug 2019 05:38:04 +0000 Subject: [PATCH 3/5] tiny bugs fixed --- ci/docker/runtime_functions.sh | 2 +- ci/jenkins/Jenkins_steps.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/docker/runtime_functions.sh b/ci/docker/runtime_functions.sh index 2518f4c7c64f..233756e29467 100755 --- a/ci/docker/runtime_functions.sh +++ b/ci/docker/runtime_functions.sh @@ -542,7 +542,7 @@ build_ubuntu_cpu_clang60_mkldnn() { build_ccache_wrappers make \ - ENABLE_TESTCOVERAGE=1 \ + USE_CPP_PACKAGE=1 \ USE_BLAS=openblas \ USE_OPENMP=1 \ diff --git a/ci/jenkins/Jenkins_steps.groovy b/ci/jenkins/Jenkins_steps.groovy index f653e0c5cb63..24d4415ea60d 100644 --- a/ci/jenkins/Jenkins_steps.groovy +++ b/ci/jenkins/Jenkins_steps.groovy @@ -389,7 +389,7 @@ def compile_unix_clang_6_mkldnn_cpu() { timeout(time: max_time, unit: 'MINUTES') { utils.init_git() utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_clang60_mkldnn', false) - utils.pack_lib('mkldnn_cpu_clang6', mx_mkldnn_lib, true) + utils.pack_lib('mkldnn_cpu_clang6', mx_mkldnn_lib, false) } } } From 31baff63417d53e40c31d1296009c20f14c562a3 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Thu, 22 Aug 2019 15:05:08 +0800 Subject: [PATCH 4/5] Update runtime_functions.sh --- ci/docker/runtime_functions.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/docker/runtime_functions.sh b/ci/docker/runtime_functions.sh index 233756e29467..0fda8a05eb47 100755 --- a/ci/docker/runtime_functions.sh +++ b/ci/docker/runtime_functions.sh @@ -542,7 +542,6 @@ build_ubuntu_cpu_clang60_mkldnn() { build_ccache_wrappers make \ - USE_CPP_PACKAGE=1 \ USE_BLAS=openblas \ USE_OPENMP=1 \ From 2f5ea56ea126b90657743da335f3d85a903a8dda Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Sat, 24 Aug 2019 05:17:36 +0000 Subject: [PATCH 5/5] change CI config back --- ci/docker/runtime_functions.sh | 1 + ci/jenkins/Jenkins_steps.groovy | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/docker/runtime_functions.sh b/ci/docker/runtime_functions.sh index 0fda8a05eb47..2518f4c7c64f 100755 --- a/ci/docker/runtime_functions.sh +++ b/ci/docker/runtime_functions.sh @@ -542,6 +542,7 @@ build_ubuntu_cpu_clang60_mkldnn() { build_ccache_wrappers make \ + ENABLE_TESTCOVERAGE=1 \ USE_CPP_PACKAGE=1 \ USE_BLAS=openblas \ USE_OPENMP=1 \ diff --git a/ci/jenkins/Jenkins_steps.groovy b/ci/jenkins/Jenkins_steps.groovy index 24d4415ea60d..f653e0c5cb63 100644 --- a/ci/jenkins/Jenkins_steps.groovy +++ b/ci/jenkins/Jenkins_steps.groovy @@ -389,7 +389,7 @@ def compile_unix_clang_6_mkldnn_cpu() { timeout(time: max_time, unit: 'MINUTES') { utils.init_git() utils.docker_run('ubuntu_cpu', 'build_ubuntu_cpu_clang60_mkldnn', false) - utils.pack_lib('mkldnn_cpu_clang6', mx_mkldnn_lib, false) + utils.pack_lib('mkldnn_cpu_clang6', mx_mkldnn_lib, true) } } }