Что делает numpy.random.seed (0)?


282

Что делает np.random.seedв приведенном ниже коде из учебника Scikit-Learn? Я не очень хорошо разбираюсь в материалах генератора случайных состояний NumPy, так что я бы очень признателен, если принять во внимание то, что говорят обыватели.

np.random.seed(0)
indices = np.random.permutation(len(iris_X))

Ответы:


559

np.random.seed(0) делает случайные числа предсказуемыми

>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])
>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])

При сбросе семян (каждый раз) один и тот же набор номеров будет появляться каждый раз.

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

>>> numpy.random.rand(4)
array([ 0.42,  0.65,  0.44,  0.89])
>>> numpy.random.rand(4)
array([ 0.96,  0.38,  0.79,  0.53])

(псевдо-) случайные числа работают, начиная с числа (начального числа), умножая его на большое число, добавляя смещение, а затем получая по модулю эту сумму. Полученное число затем используется в качестве начального числа для генерации следующего «случайного» числа. Когда вы устанавливаете семя (каждый раз), оно делает то же самое каждый раз, давая вам одинаковые числа.

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

Чтобы получить наиболее случайные числа для каждого запуска, позвоните numpy.random.seed(). Это приведет к тому, что numpy установит начальное число на случайное число, полученное из /dev/urandomили его аналога в Windows, или, если ни один из них не будет доступен, он будет использовать часы.

Для получения дополнительной информации об использовании seed для генерации псевдослучайных чисел см. Википедию .


86
Этот ответ должен быть добавлен в документацию numpy. Спасибо.
gorjanz

8
Кроме того, когда вы вызываете numpy.random.seed(None), он «попытается прочитать данные из / dev / urandom (или аналога Windows), если он доступен, или запитать от часов в противном случае».
Джонатан

1
@Джонатан: Отличная мысль numpy.random.seed(None). Я обновил ответ с этой информацией и ссылкой на документы.
John1024

@ curio1729 Реализация может варьироваться от одной операционной системы к другой, но numpy пытается сделать ее команды, в том числе seed, совместимыми.
John1024

1
@ L3viathan Хорошая мысль! Чтобы быть более полным и точным, я должен был упомянуть, что добавлено смещение. Ответ обновлен. Для тех, кто хочет получить больше информации, я также добавил ссылку на обсуждение википедии генераторов псевдослучайных чисел.
John1024

38

Если вы установите np.random.seed(a_fixed_number)каждый раз, когда вызываете другую случайную функцию numpy, результат будет таким же:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10) 
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]

Однако, если вы просто вызовете его один раз и будете использовать различные случайные функции, результаты все равно будут другими:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10)
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> print np.random.permutation(10) 
[3 5 1 2 9 8 0 6 7 4]
>>> print np.random.permutation(10) 
[2 3 8 4 5 1 0 6 9 7]
>>> print np.random.rand(4) 
[0.64817187 0.36824154 0.95715516 0.14035078]
>>> print np.random.rand(4) 
[0.87008726 0.47360805 0.80091075 0.52047748]

3
Существует ли функция, которую можно вызвать один раз, чтобы случайное начальное число устанавливалось для всех последующих np.randomвызовов до тех пор, пока начальное число не будет изменено? Необходимость называть это каждый раз кажется ненужно многословной и легко забываемой.
Lubed Up Slug

@LubedUpSlug вы можете украсить их - по крайней мере, для некоторых простых случаев, которые я проверял, это должно работать. def seed_first(fun, seed=0):| \tdef wrapped(*args, **kwargs):| \t\tnp.random.seed(seed)| \t\treturn fun(*args, **kwargs)| \treturn wrapped, а затем for m in np.random.__all__:| \tif m != 'seed':| \t\tsetattr(np.random, m, seed_first(getattr(np.random, m)))Однако это может привести к очень тонким ошибкам и странному поведению в долгосрочной перспективе. (Замените \ t четырьмя пробелами и |
Себастьян

1
@ SebastianHöffner спасибо за ваш комментарий. Мой вопрос был немного ошибочным, потому что меня смутило предложение «Однако, если вы просто вызовете его один раз и будете использовать различные случайные функции, результаты все равно будут другими:« np.random.seed()Один вызов в начале программы всегда будет приводить к одному и тому же результату ». для того же начального числа, поскольку последующие вызовы np.randomфункций будут детерминировано изменять начальное значение для последующих вызовов. Вызов np.random.seed()перед каждым вызовом np.randomфункций, вероятно, приведет к нежелательным результатам.
Lubed Up Slug

17

Как уже отмечалось, numpy.random.seed (0) устанавливает случайное начальное число в 0, поэтому псевдослучайные числа, которые вы получаете из случайного числа, начнутся с той же точки. Это может быть полезно для отладки в некоторых случаях. ОДНАКО после некоторого прочтения кажется, что это неправильный путь, если у вас есть потоки, потому что он не безопасен для потоков.

из различий между numpy-random-random-random-random-in-python :

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

Пример того, как это сделать:

from numpy.random import RandomState
prng = RandomState()
print prng.permutation(10)
prng = RandomState()
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)

может дать:

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

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

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

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

Наконец, обратите внимание, что могут быть случаи, когда инициализация в 0 (в отличие от начального числа, в котором не все биты 0) может привести к неравномерному распределению для некоторых первых итераций из-за способа работы xor, но это зависит от алгоритма и выходит за рамки моих текущих забот и объема этого вопроса.


12

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

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

Что если каждый раз, когда вы начинаете тренироваться с нуля, модель инициализируется одним и тем же набором случайных весов инициализации? В этом случае ваша модель может стать воспроизводимой. Это достигается с помощью numpy.random.seed (0). Упоминая seed () для определенного числа, вы всегда держитесь за один и тот же набор случайных чисел.


3

Представьте, что вы показываете кому-то, как кодировать что-то с помощью «случайных» чисел. Используя numy seed, они могут использовать один и тот же номер seed и получать одинаковый набор «случайных» чисел.

Так что это не совсем случайно, потому что алгоритм выплевывает числа, но выглядит как случайно сгенерированная связка.


0

Случайное начальное число определяет начальную точку, когда компьютер генерирует последовательность случайных чисел.

Например, предположим, что вы хотите сгенерировать случайное число в Excel (примечание: Excel устанавливает предел в 9999 для начального числа). Если вы введете число в поле «Случайное семя» во время процесса, вы сможете снова использовать тот же набор случайных чисел. Если вы ввели «77» в поле и набрали «77» при следующем запуске генератора случайных чисел, Excel отобразит тот же набор случайных чисел. Если вы введете «99», вы получите совершенно другой набор цифр. Но если вы вернетесь к семени 77, то получите тот же набор случайных чисел, с которого вы начали.

Например, «взять число х, добавить 900 + х, а затем вычесть 52». Для запуска процесса необходимо указать начальный номер x (начальное число). Давайте возьмем стартовый номер 77:

Добавить 900 + 77 = 977 Вычесть 52 = 925 Следуя тому же алгоритму, второе «случайное» число будет:

900 + 925 = 1825 вычесть 52 = 1773 Этот простой пример следует шаблону, но алгоритмы генерации компьютерных номеров намного сложнее


0

Все случайные числа, сгенерированные после установки конкретного начального значения, одинаковы для всех платформ / систем.



0
numpy.random.seed(0)
numpy.random.randint(10, size=5)

Это производит следующий вывод: array([5, 0, 3, 3, 7]) опять же, если мы запустим один и тот же код, мы получим тот же результат.

Теперь, если мы изменим начальное значение с 0 на 1 или другие:

numpy.random.seed(1)
numpy.random.randint(10, size=5)

Это приводит к следующему выводу: array([5 8 9 5 0])но теперь вывод не такой, как выше.


0

Все ответы выше показывают реализацию np.random.seed() в коде. Я постараюсь кратко объяснить, почему это происходит на самом деле. Компьютеры - это машины, которые разработаны на основе заранее определенных алгоритмов. Любой вывод с компьютера является результатом алгоритма, реализованного на входе. Поэтому, когда мы запрашиваем компьютер для генерации случайных чисел, они бывают случайными, но компьютер не просто случайно их подбирает!

Поэтому, когда мы пишем, np.random.seed(any_number_here)алгоритм выведет определенный набор чисел, который является уникальным для аргумента any_number_here. Это почти как определенный набор случайных чисел может быть получен, если мы передадим правильный аргумент. Но это потребует от нас знать, как работает алгоритм, что довольно утомительно.

Так, например, если я напишу np.random.seed(10)определенный набор чисел, который я получу, он останется прежним, даже если я выполню ту же строку через 10 лет, если алгоритм не изменится.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.