Различия между numpy.random и random.random в Python

У меня есть большой script в Python. Я вдохновил себя на код других людей, поэтому для некоторых вещей я использовал модуль numpy.random (например, для создания массива случайных чисел, взятых из биномиального распределения), а в других местах я использую модуль random.random.

Может кто-нибудь скажет мне основные отличия между ними? Если посмотреть на веб-страницу doc для каждого из двух, мне кажется, что numpy.random имеет больше методов, но я не понимаю, как происходит генерация случайных чисел.

Причина, по которой я спрашиваю, заключается в том, что мне нужно засеять основную программу для целей отладки. Но это не работает, если я не использую тот же генератор случайных чисел во всех модулях, которые я импортирую, это правильно?

Кроме того, я прочитал здесь, в другом посте, обсуждение об использовании numpy.random.seed(), но я не совсем понял, почему это была такая плохая идея. Я был бы очень признателен, если кто-нибудь объяснит мне, почему это так.

Ответ 1

Вы уже сделали много правильных наблюдений!

Если вы не захотите засеять оба случайных генератора, возможно, в конечном итоге проще выбрать один генератор или другой.

Для numpy.random.seed() основная трудность заключается в том, что она не является потокобезопасной, то есть ее небезопасно использовать, если у вас много разных потоков выполнения, поскольку он не гарантированно работает, если два разных потока выполняют функцию одновременно. Если вы не используете потоки, и если вы можете разумно ожидать, что вам не понадобится переписывать вашу программу таким образом в будущем, numpy.random.seed() должно быть в порядке. Если есть основания подозревать, что вам понадобятся потоки в будущем, гораздо более безопасно в долгосрочной перспективе сделать так, как было предложено, а сделать локальный экземпляр класса numpy.random.Random/a > . Насколько я могу судить, random.random.seed() является потокобезопасным (или, по крайней мере, я не нашел никаких доказательств обратного).

Библиотека numpy.random содержит несколько дополнительных распределений вероятностей, обычно используемых в научных исследованиях, а также несколько удобных функций для генерации массивов случайных данных. Библиотека random.random немного более легкая, и должно быть хорошо, если вы не занимаетесь научными исследованиями или другими видами работы в статистике.

В противном случае они оба используют последовательность Mersenne twister для генерации своих случайных чисел, и оба они полностью детерминированы - то есть, если вы знаете несколько ключевых бит информации, можно с абсолютной уверенностью предсказать какое число будет дальше. По этой причине ни один из них не подходит для серьезных криптографических целей. Но так как последовательность очень очень длинная, оба отлично подходят для генерации случайных чисел в повседневных программах. Это также является причиной необходимости посеять случайное значение - если вы начинаете в одном и том же месте каждый раз, вы всегда будете получать одну и ту же последовательность случайных чисел!

В качестве побочного примечания, если вам нужна криптографическая степень случайности, вы должны использовать модуль secrets или что-то вроде Crypto.Random, если вы используете версию Python раньше, чем Python 3.6.

Ответ 2

Источник используемого семени и используемый профиль распределения будут влиять на выходы - если вы ищете криптографическую случайность, то высевка из os.urandom() будет получать почти реальные случайные байты от болтовни устройства (например, ethernet или диск) (т.е./dev/random на BSD)

это позволит вам не давать семена и таким образом генерировать детерминированные случайные числа. Однако случайные вызовы позволяют вам сопоставлять числа с распределением (что я называю научным случайным образом - в конечном итоге все, что вам нужно, - это распределение колоколообразных кривых случайных чисел, numpy лучше всего разбирать это.

SO да, придерживайтесь одного генератора, но решайте, какой случайный вы хотите - случайный, но деформированный из кривой распределения или как случайный, как вы можете получить без квантового устройства.

Ответ 3

Из Python для анализа данных модуль numpy.random дополняет Python random функциями для эффективного создания целых массивов значений выборки из многих видов вероятностных распределений.

Напротив, встроенный модуль random Python производит выборку только одного значения за раз, а numpy.random может генерировать очень большой образец быстрее. Используя магическую функцию IPython %timeit, можно увидеть, какой модуль работает быстрее:

In [1]: from random import normalvariate
In [2]: N = 1000000

In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
1 loop, best of 3: 963 ms per loop

In [4]: %timeit np.random.normal(size=N)
10 loops, best of 3: 38.5 ms per loop