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

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

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

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

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

4 ответа

Решение

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

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

За 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.

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

Напротив, встроенный в Python random модуль выбирает только одно значение за раз, в то время как 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

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

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

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

Меня удивило randint(a, b)метод существует в обоих numpy.randomа также random, но они имеют разное поведение для верхней границы.

random.randint(a, b)возвращает случайное целое число N такое, что a <= N <= b. Псевдоним для randrange(a, b+1). Оно имеет bвключительно. случайная документация

Однако, если вы позвоните numpy.random.randint(a, b), он вернет низкий (включительно) высокий (эксклюзивный). Непонятная документация

Другие вопросы по тегам