Что нового или отличается#

NumPy 1.17.0 представил Generator как улучшенная замена для устаревший RandomState. Вот краткое сравнение двух реализаций.

Функция

Старый эквивалент

Примечания

Generator

RandomState

Generator требует источника потока, называемого BitGenerator Предоставлено несколько таких. RandomState использует вихрь Мерсенна MT19937 по умолчанию, но также могут быть созданы с любым BitGenerator.

random

random_sample, rand

Доступ к значениям в BitGenerator, преобразование их в float64 в интервале [0.0., 1.0). В дополнение к size kwarg, теперь поддерживает dtype='d' или dtype='f', и out kwarg для заполнения предоставленного пользователем массива.

Многие другие распределения также поддерживаются.

integers

randint, random_integers

Используйте endpoint kwarg для регулировки включения или исключения high конечная точка интервала.

  • Генераторы нормального, экспоненциального и гамма-распределений используют 256-шаговые методы Циггурата, которые в 2-10 раз быстрее стандартной реализации NumPy в standard_normal, standard_exponential или standard_gamma. Из-за изменения алгоритмов невозможно воспроизвести точные случайные значения с помощью Generator для этих распределений или любого метода распределения, который на них полагается.

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.02 ms +- 9.03 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
1.75 ms +- 15.3 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)
   ...: 
487 us +- 6.98 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
1.25 ms +- 6.35 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)
   ...: 
1.85 ms +- 24.4 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
3.42 ms +- 27.1 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
  • integers теперь является каноническим способом генерации целочисленных случайных чисел из дискретного равномерного распределения. Это заменяет как randint и устаревший random_integers.

  • The rand и randn методы доступны только через устаревший RandomState.

  • Generator.random теперь является каноническим способом генерации случайных чисел с плавающей точкой, который заменяет RandomState.random_sample, sample, и ranf, все из которых были псевдонимами. Это соответствует Python’s random.random.

  • Все генераторы битов могут производить double, uint64 и uint32 через CTypes (ctypes) и CFFI (cffi). Это позволяет использовать эти генераторы битов в numba.

  • Генераторы битов могут использоваться в сторонних проектах через Cython.

  • Все генераторы битов используют SeedSequence to преобразовать начальные целые числа в инициализированные состояния.

  • Необязательный dtype аргумент, который принимает np.float32 или np.float64 для генерации равномерных случайных величин одинарной или двойной точности для выбранных распределений. integers принимает dtype аргумент с любым знаковым или беззнаковым целочисленным типом данных.

In [6]: rng = np.random.default_rng()

In [7]: rng.random(3, dtype=np.float64)
Out[7]: array([0.15428534, 0.69863672, 0.45724786])

In [8]: rng.random(3, dtype=np.float32)
Out[8]: array([0.1729908 , 0.0745824 , 0.42687505], dtype=float32)

In [9]: rng.integers(0, 256, size=3, dtype=np.uint8)
Out[9]: array([183, 218, 161], dtype=uint8)
  • Необязательный out аргумент, который позволяет заполнять существующие массивы для выбранных распределений

    Это позволяет многопоточности заполнять большие массивы блоками с использованием подходящих BitGenerators параллельно.

In [10]: rng = np.random.default_rng()

In [11]: existing = np.zeros(4)

In [12]: rng.random(out=existing[:2])
Out[12]: array([0.99546415, 0.1408341 ])

In [13]: print(existing)
[0.99546415 0.1408341  0.         0.        ]
  • Необязательный axis аргумент для методов, таких как choice, permutation и shuffle который управляет тем, по какой оси выполняется операция для многомерных массивов.

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([[ 2,  2,  3,  2,  1],
       [ 6,  6,  7,  6,  5],
       [10, 10, 11, 10,  9]])

In [18]: rng.shuffle(a, axis=1)        # Shuffle in-place

In [19]: a
Out[19]: 
array([[ 3,  1,  2,  0],
       [ 7,  5,  6,  4],
       [11,  9, 10,  8]])
  • Добавлен метод для выборки из комплексного нормального распределения (complex_normal)