Random sampling (numpy.random
)#
Numpy’s random number routines produce pseudo random numbers using
combinations of a BitGenerator
to create sequences and a Generator
to use those sequences to sample from different statistical distributions:
BitGenerators: Objects that generate random numbers. These are typically unsigned integer words filled with sequences of either 32 or 64 random bits.
Generators: Objects that transform sequences of random bits from a BitGenerator into sequences of numbers that follow a specific probability distribution (such as uniform, Normal or Binomial) within a specified interval.
Since Numpy version 1.17.0 the Generator can be initialized with a
number of different BitGenerators. It exposes many different probability
distributions. See NEP 19 for context on the updated random Numpy number
routines. The legacy RandomState
random number routines are still
available, but limited to a single BitGenerator. See What’s New or Different
for a complete list of improvements and differences from the legacy
RandomState
.
For convenience and backward compatibility, a single RandomState
instance’s methods are imported into the numpy.random namespace, see
Legacy Random Generation for the complete list.
Quick Start#
Call default_rng
to get a new instance of a Generator
, then call its
methods to obtain samples from different distributions. By default,
Generator
uses bits provided by PCG64
which has better statistical
properties than the legacy MT19937
used in RandomState
.
# Do this (new version)
from numpy.random import default_rng
rng = default_rng()
vals = rng.standard_normal(10)
more_vals = rng.standard_normal(10)
# instead of this (legacy version)
from numpy import random
vals = random.standard_normal(10)
more_vals = random.standard_normal(10)
Generator
can be used as a replacement for RandomState
. Both class
instances hold an internal BitGenerator
instance to provide the bit
stream, it is accessible as gen.bit_generator
. Some long-overdue API
cleanup means that legacy and compatibility methods have been removed from
Generator
Notes |
||
|
|
Compatible with |
|
||
|
|
Add an |
|
||
|
removed |
Use |
|
removed |
See What’s New or Different for more information.
Something like the following code can be used to support both RandomState
and Generator
, with the understanding that the interfaces are slightly
different
try:
rng_integers = rng.integers
except AttributeError:
rng_integers = rng.randint
a = rng_integers(1000)
Seeds can be passed to any of the BitGenerators. The provided value is mixed
via SeedSequence
to spread a possible sequence of seeds across a wider
range of initialization states for the BitGenerator. Here PCG64
is used and
is wrapped with a Generator
.
from numpy.random import Generator, PCG64
rng = Generator(PCG64(12345))
rng.standard_normal()
Here we use default_rng
to create an instance of Generator
to generate a
random float:
>>> import numpy as np
>>> rng = np.random.default_rng(12345)
>>> print(rng)
Generator(PCG64)
>>> rfloat = rng.random()
>>> rfloat
0.22733602246716966
>>> type(rfloat)
<class 'float'>
Here we use default_rng
to create an instance of Generator
to generate 3
random integers between 0 (inclusive) and 10 (exclusive):
>>> import numpy as np
>>> rng = np.random.default_rng(12345)
>>> rints = rng.integers(low=0, high=10, size=3)
>>> rints
array([6, 2, 7])
>>> type(rints[0])
<class 'numpy.int64'>
Introduction#
The new infrastructure takes a different approach to producing random numbers
from the RandomState
object. Random number generation is separated into
two components, a bit generator and a random generator.
The BitGenerator
has a limited set of responsibilities. It manages state
and provides functions to produce random doubles and random unsigned 32- and
64-bit values.
The random generator
takes the
bit generator-provided stream and transforms them into more useful
distributions, e.g., simulated normal random values. This structure allows
alternative bit generators to be used with little code duplication.
The Generator
is the user-facing object that is nearly identical to the
legacy RandomState
. It accepts a bit generator instance as an argument.
The default is currently PCG64
but this may change in future versions.
As a convenience NumPy provides the default_rng
function to hide these
details:
>>> from numpy.random import default_rng
>>> rng = default_rng(12345)
>>> print(rng)
Generator(PCG64)
>>> print(rng.random())
0.22733602246716966
One can also instantiate Generator
directly with a BitGenerator
instance.
To use the default PCG64
bit generator, one can instantiate it directly and
pass it to Generator
:
>>> from numpy.random import Generator, PCG64
>>> rng = Generator(PCG64(12345))
>>> print(rng)
Generator(PCG64)
Similarly to use the older MT19937
bit generator (not recommended), one can
instantiate it directly and pass it to Generator
:
>>> from numpy.random import Generator, MT19937
>>> rng = Generator(MT19937(12345))
>>> print(rng)
Generator(MT19937)
What’s New or Different#
Warning
The Box-Muller method used to produce NumPy’s normals is no longer available
in Generator
. It is not possible to reproduce the exact random
values using Generator for the normal distribution or any other
distribution that relies on the normal such as the RandomState.gamma
or
RandomState.standard_t
. If you require bitwise backward compatible
streams, use RandomState
.
The Generator’s normal, exponential and gamma functions use 256-step Ziggurat methods which are 2-10 times faster than NumPy’s Box-Muller or inverse CDF implementations.
Optional
dtype
argument that acceptsnp.float32
ornp.float64
to produce either single or double precision uniform random variables for select distributionsOptional
out
argument that allows existing arrays to be filled for select distributionsAll BitGenerators can produce doubles, uint64s and uint32s via CTypes (
PCG64.ctypes
) and CFFI (PCG64.cffi
). This allows the bit generators to be used in numba.The bit generators can be used in downstream projects via Cython.
Generator.integers
is now the canonical way to generate integer random numbers from a discrete uniform distribution. Therand
andrandn
methods are only available through the legacyRandomState
. Theendpoint
keyword can be used to specify open or closed intervals. This replaces bothrandint
and the deprecatedrandom_integers
.Generator.random
is now the canonical way to generate floating-point random numbers, which replacesRandomState.random_sample
, RandomState.sample, and RandomState.ranf. This is consistent with Python’srandom.random
.All BitGenerators in numpy use
SeedSequence
to convert seeds into initialized states.The addition of an
axis
keyword argument to methods such asGenerator.choice
,Generator.permutation
, andGenerator.shuffle
improves support for sampling from and shuffling multi-dimensional arrays.
See What’s New or Different for a complete list of improvements and
differences from the traditional Randomstate
.
Parallel Generation#
The included generators can be used in parallel, distributed applications in a number of ways:
Users with a very large amount of parallelism will want to consult Upgrading PCG64 with PCG64DXSM.
Concepts#
Features#
Original Source of the Generator and BitGenerators#
This package was developed independently of NumPy and was integrated in version 1.17.0. The original repo is at https://github.com/bashtage/randomgen.