Що робить numpy.random.seed (0)?


282

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

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

Відповіді:


556

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, або, якщо жодне з них не доступне, воно використовуватиме годинник.

Для отримання додаткової інформації про використання насіння для генерування псевдовипадкових чисел див. У Вікіпедії .


86
Цю відповідь слід додати до документації нуме. Дякую.
gorjanz

8
Крім того, коли ви телефонуєте numpy.random.seed(None), він "спробує прочитати дані з / dev / urandom (або аналог Windows), якщо вони доступні, або вивести з годинника в іншому випадку".
Джонатан

1
@Jonathan Чудовий пункт о 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викликів, поки не зміниться насіння? Доводиться дзвонити це кожен раз, здається багатослівним і легко забути.
Замальовано 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функцій, ймовірно, призведе до небажаних результатів.
Закупований Слуг

17

Як зазначалося, numpy.random.seed (0) встановлює випадкове насіння в 0, тому псевдо випадкові числа, які ви отримаєте від випадкових, почнуться з тієї ж точки. Це може бути корисним для налагодження в деяких випадках. ЗАРАЗ, після деякого читання, здається, це неправильний шлях для цього, якщо у вас є теми, тому що це не безпечно для ниток.

від відмінностей між-numpy-random-and-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). Згадуючи насіння () до певного числа, ви завжди звисаєте до одного набору випадкових чисел.


3

Уявіть, що ви показуєте комусь, як щось кодувати з купою "випадкових" чисел. Використовуючи numpy насіння, вони можуть використовувати одне і те ж число насіння і отримувати однаковий набір "випадкових" чисел.

Отже, це не зовсім випадково, оскільки алгоритм випльовує числа, але він схожий на випадково згенерований зв'язок.


0

Випадкове насіння визначає початкову точку, коли комп'ютер генерує випадкову послідовність чисел.

Наприклад, скажімо, що ви хотіли генерувати випадкове число в Excel (Примітка: Excel встановлює ліміт 9999 для насіння). Якщо ви введете число у поле "Випадкові насіння" під час процесу, ви зможете знову використовувати той самий набір випадкових чисел. Якщо ви ввели "77" у поле і набрали "77" при наступному запуску генератора випадкових чисел, Excel відобразить той самий набір випадкових чисел. Якщо ви введете "99", ви отримаєте зовсім інший набір чисел. Але якщо ви повернетесь до насіння 77, ви отримаєте той самий набір випадкових чисел, з яким ви почали.

Наприклад, "взяти число x, додати 900 + x, а потім відняти 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.