What’s new or different#
NumPy 1.17.0 introduced Generator as an improved replacement for
the legacy RandomState. Here is a quick comparison of the two
implementations.
Feature |
Older Equivalent |
Notes |
|
||
Access the values in a
BitGenerator, convert them to
Many other distributions are also supported. |
||
Use the |
The normal, exponential and gamma generators use 256-step Ziggurat methods which are 2-10 times faster than NumPy’s default implementation in
standard_normal,standard_exponentialorstandard_gamma. Because of the change in algorithms, it is not possible to reproduce the exact random values usingGeneratorfor these distributions or any distribution method that relies on them.
In [1]: import numpy.random
In [2]: rng = np.random.default_rng()
In [3]: %timeit -n 1 rng.standard_normal(100000)
...: %timeit -n 1 numpy.random.standard_normal(100000)
...:
1.45 ms +- 42 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
2.77 ms +- 72.7 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [4]: %timeit -n 1 rng.standard_exponential(100000)
...: %timeit -n 1 numpy.random.standard_exponential(100000)
...:
673 us +- 63.6 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
2.07 ms +- 29 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [5]: %timeit -n 1 rng.standard_gamma(3.0, 100000)
...: %timeit -n 1 numpy.random.standard_gamma(3.0, 100000)
...:
2.68 ms +- 88.2 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
5.71 ms +- 55.8 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
integersis now the canonical way to generate integer random numbers from a discrete uniform distribution. This replaces bothrandintand the deprecatedrandom_integers.The
randandrandnmethods are only available through the legacyRandomState.Generator.randomis now the canonical way to generate floating-point random numbers, which replacesRandomState.random_sample,sample, andranf, all of which were aliases. This is consistent with Python’srandom.random.All bit generators can produce doubles, uint64s and uint32s via CTypes (
ctypes) and CFFI (cffi). This allows these bit generators to be used in numba.The bit generators can be used in downstream projects via Cython.
All bit generators use
SeedSequenceto convert seed integers to initialized states.Optional
dtypeargument that acceptsnp.float32ornp.float64to produce either single or double precision uniform random variables for select distributions.integersaccepts adtypeargument with any signed or unsigned integer dtype.Normals (
standard_normal)Standard Gammas (
standard_gamma)Standard Exponentials (
standard_exponential)
In [6]: rng = np.random.default_rng()
In [7]: rng.random(3, dtype=np.float64)
Out[7]: array([0.94414369, 0.62474448, 0.80607091])
In [8]: rng.random(3, dtype=np.float32)
Out[8]: array([0.4812641 , 0.4058587 , 0.32835156], dtype=float32)
In [9]: rng.integers(0, 256, size=3, dtype=np.uint8)
Out[9]: array([ 44, 219, 139], dtype=uint8)
Optional
outargument that allows existing arrays to be filled for select distributionsUniforms (
random)Normals (
standard_normal)Standard Gammas (
standard_gamma)Standard Exponentials (
standard_exponential)
This allows multithreading to fill large arrays in chunks using suitable BitGenerators in parallel.
In [10]: rng = np.random.default_rng()
In [11]: existing = np.zeros(4)
In [12]: rng.random(out=existing[:2])
Out[12]: array([0.0811171 , 0.65147786])
In [13]: print(existing)
[0.0811171 0.65147786 0. 0. ]
Optional
axisargument for methods likechoice,permutationandshufflethat controls which axis an operation is performed over for multi-dimensional arrays.
In [14]: rng = np.random.default_rng()
In [15]: a = np.arange(12).reshape((3, 4))
In [16]: a
Out[16]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [17]: rng.choice(a, axis=1, size=5)
Out[17]:
array([[ 3, 1, 1, 2, 2],
[ 7, 5, 5, 6, 6],
[11, 9, 9, 10, 10]])
In [18]: rng.shuffle(a, axis=1) # Shuffle in-place
In [19]: a
Out[19]:
array([[ 1, 0, 3, 2],
[ 5, 4, 7, 6],
[ 9, 8, 11, 10]])
Added a method to sample from the complex normal distribution (complex_normal)