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

100

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

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

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

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

Лаура
источник

Ответы:

121

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

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

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

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

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

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

Ханнеле
источник
14
В качестве отдаленного замечания, иногда необходимо использовать ни то , ни другое , поскольку твистер Мерсенна не производит случайных последовательностей энтропии, достаточных для криптографических (и некоторых необычных научных) целей. В этих редких случаях вам часто требуется Crypto.Random , который может использовать источники энтропии, специфичные для ОС, для генерации недетерминированных случайных последовательностей гораздо более высокого качества, чем доступно в random.randomодиночку. Однако обычно вам это не нужно.
SingleNegationElimination
Спасибо, Ханнеле. Ваши идеи были действительно очень полезны! Оказывается, я не могу обойтись без использования ТОЛЬКО одного генератора случайных чисел (который должен быть numpy, поскольку random не дает биномиальных распределений), потому что части моей программы вызывают другую программу, которая использует random. Придется засеять два генератора.
Лаура
2
«если вы знаете, какое число у вас есть сейчас, можно с абсолютной уверенностью предсказать, какое число будет следующим». Думаю, это заявление может потребовать некоторых пояснений. Имеется в виду, что если вы знаете внутреннее состояние генератора, вы можете воспроизвести последовательность - что вы и делаете, когда заполняете генератор. Учитывая, что генератор выводит одно число, вы не можете предсказать следующее число. Период настолько велик, что вам, вероятно, понадобится длинная последовательность чисел, прежде чем вы сможете вычислить, где вы находитесь в псевдослучайной последовательности и, таким образом, предсказать следующую.
Kaushik Ghose,
12

Из 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
lmiguelvargasf
источник
1
Не в случае других методов. по сравнению np.random.randint(2)с random.randrange(2)NumPy и медленнее . NumPy: 1,25 мкс и Random: 891 нс. А также такое же соотношение для np.random.rand()и random.random().
Шаян Амани
3

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

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

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

вы, сэр, возьмите это
источник
Большое спасибо, Пол, ваш ответ был действительно полезен! Я не ищу криптографическую случайность, я занимаюсь математическим моделированием и мне достаточно псевдослучайных чисел. Оказывается, я не могу придерживаться одного генератора, как я хотел, так как мне нужно numpy для биномиального распределения, и моя программа вызывает другую программу, которая использует случайное :(
Лаура