pytutorial/numpy/random/README.md
David Rotermund 047a245148
Update README.md
Signed-off-by: David Rotermund <54365609+davrot@users.noreply.github.com>
2023-12-13 18:05:40 +01:00

8.8 KiB
Raw Blame History

Random numbers the non-legacy way

{:.no_toc}

* TOC {:toc}

Goal

If you don't see something like np.random.default_rng() in your code then you are probably using the old Legacy Random Generation.

Don't use the legacy methods for new source code!!!

numpy.random.random() == old == bad == don't use

Do it like this:

import numpy as np

rng = np.random.default_rng()
random_values = rng.random(size=(2, 10))

Questions to David Rotermund

Random Generator

Typical usage

import numpy as np

rng = np.random.default_rng()
random_values = rng.random(size=(2, 10))

print(random_values)

Output:

[[0.81103943 0.1110591  0.42978062 0.47818377 0.91138636 0.47051031
  0.08662082 0.1643707  0.48717037 0.17870536]
 [0.94499902 0.74089677 0.12221184 0.61603001 0.91198789 0.33900609
  0.75832792 0.74465679 0.19940125 0.56674595]]

With seed:

import numpy as np

rng = np.random.default_rng(seed=23)
random_values = rng.random(size=(2, 10))

print(random_values)

Output:

[[0.69393308 0.64145822 0.12864422 0.11370805 0.65334552 0.85345711
  0.20177913 0.21801864 0.71658464 0.47069967]
 [0.41522193 0.3491478  0.06385375 0.45466617 0.30145328 0.38907675
  0.54029782 0.68358969 0.62475238 0.74270445]]

Changing the random number generator

Default

import numpy as np

rng = np.random.default_rng()
print(rng)  # -> Generator(PCG64)

If you don't like it there are other options:

PCG64 -- The default A fast generator that can be advanced by an arbitrary amount. See the documentation for advance. PCG-64 has a period of 2^128. See the PCG authors page for more details about this class of PRNG.
MT19937 The standard Python BitGenerator. Adds a MT19937.jumped function that returns a new generator with state as-if 2^128 draws have been made.
PCG64DXSM An upgraded version of PCG-64 with better statistical properties in parallel contexts. See Upgrading PCG64 with PCG64DXSM for more information on these improvements.
Philox A counter-based generator capable of being advanced an arbitrary number of steps or generating independent streams. See the Random123 page for more details about this class of bit generators.
SFC64 A fast generator based on random invertible mappings. Usually the fastest generator of the four. See the SFC authors page for (a little) more detail.

Distributions (you will use)

The most important ones are in bold. If you see a function argument out, then you can reuse an existing np array (i.e. in-place operation) as target.

integers(low[, high, size, dtype, endpoint]) Return random integers from low (inclusive) to high (exclusive), or if endpoint=True, low (inclusive) to high (inclusive).
random([size, dtype, out]) Return random floats in the half-open interval [0.0, 1.0).
choice(a[, size, replace, p, axis, shuffle]) Generates a random sample from a given array
bytes(length) Return random bytes.
binomial(n, p[, size]) Draw samples from a binomial distribution.
multinomial(n, pvals[, size]) Draw samples from a multinomial distribution.
multivariate_normal(mean, cov[, size, ...]) Draw random samples from a multivariate normal distribution.
normal([loc, scale, size]) Draw random samples from a normal (Gaussian) distribution.
poisson([lam, size]) Draw samples from a Poisson distribution.
standard_normal([size, dtype, out]) Draw samples from a standard Normal distribution (mean=0, stdev=1).
uniform([low, high, size]) Draw samples from a uniform distribution.

random

import numpy as np

rng = np.random.default_rng()
random_values = rng.random(size=(2, 10))
print(random_values)

Output:

[[0.75309105 0.15751286 0.49454759 0.18204807 0.88459006 0.78685769
  0.68525047 0.4000365  0.45317167 0.62412358]
 [0.01082224 0.13257961 0.75638974 0.84886965 0.19755022 0.18697649
  0.47064409 0.66128207 0.30285691 0.53465021]]

integers

import numpy as np

rng = np.random.default_rng()
random_values = rng.integers(
    low=1, high=3, size=(2, 10), dtype=np.uint64, endpoint=True
)
print(random_values)

Output:

[[2 3 3 2 1 3 1 1 2 2]
 [3 3 2 3 3 2 3 3 1 3]]

choice

import numpy as np

rng = np.random.default_rng()
p = np.array([1, 2, 3]).astype(np.float64)
p /= p.sum()
print(f"p: {p}")
random_values = rng.choice(a=p.shape[0], p=p, size=(2, 10))
print(random_values)

Output:

p: [0.16666667 0.33333333 0.5       ]
[[0 2 2 1 2 1 2 1 0 1]
 [2 0 1 2 2 1 0 2 1 2]]

Permutations

shuffle(x[, axis]) Modify an array or sequence in-place by shuffling its contents.
permutation(x[, axis]) Randomly permute a sequence, or return a permuted range.
permuted(x[, axis, out]) Randomly permute x along axis axis.
method copy/in-place axis handling
shuffle in-place as if 1d
permutation copy as if 1d
permuted either (use out for in-place) axis independent

shuffle

import numpy as np

rng = np.random.default_rng()
idx_randomized = np.arange(0, 10)
rng.shuffle(idx_randomized)

print(idx_randomized)

Output:

[0 2 8 9 5 4 3 6 1 7]

permutation

import numpy as np

rng = np.random.default_rng()
idx_randomized = rng.permutation(10)

print(idx_randomized)

Output:

[9 4 7 2 6 3 1 8 5 0]

permuted

import numpy as np

rng = np.random.default_rng()
idx = np.arange(0, 10)

idx_randomized = rng.permuted(idx)

print(idx_randomized)

Output:

[4 1 2 8 9 6 0 5 7 3]

All Distributions

You need more distributions? Go here.

Multithreaded Generation

The four core distribution (random, standard_normal, standard_exponential, and standard_gamma) can be used with multi-threading. Please look here for an example.