Co robi numpy.random.seed (0)?


282

Co robi np.random.seedponiższy kod z samouczka Scikit-Learn? Nie znam się zbyt dobrze na generatorach losowych stanów NumPy, więc naprawdę doceniłbym wyjaśnienie tego dla laika.

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

Odpowiedzi:


556

np.random.seed(0) sprawia, że ​​liczby losowe są przewidywalne

>>> 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])

Z resetem nasion (za każdym razem), to samo każdym razem pojawia się zestaw liczb.

Jeśli losowe ziarno nie zostanie zresetowane, przy każdym wywołaniu pojawiają się różne liczby:

>>> 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])

Liczby (pseudo-) losowe działają zaczynając od liczby (nasienia), mnożąc ją przez dużą liczbę, dodając przesunięcie, a następnie biorąc modulo tej sumy. Wynikowa liczba jest następnie używana jako ziarno do wygenerowania następnej „losowej” liczby. Kiedy ustawiasz ziarno (za każdym razem), robi to samo za każdym razem, dając ci te same liczby.

Jeśli chcesz pozornie losowe liczby, nie ustawiaj nasion. Jeśli masz kod, który używa liczb losowych, które chcesz debugować, bardzo pomocne może być ustawienie zarodka przed każdym uruchomieniem, aby kod działał tak samo przy każdym uruchomieniu.

Aby uzyskać najbardziej losowe numery dla każdego biegu, zadzwoń numpy.random.seed(). Spowoduje to, że numpy ustawi ziarno na losową liczbę uzyskaną z/dev/urandom jego analogu Windows lub, jeśli żaden z nich nie jest dostępny, użyje zegara.

Aby uzyskać więcej informacji na temat używania nasion do generowania liczb pseudolosowych, zobacz wikipedia .


86
Ta odpowiedź powinna zostać dodana do dokumentacji numpy. Dziękuję Ci.
gorjanz

8
Ponadto, gdy zadzwonisz numpy.random.seed(None), „spróbuje odczytać dane z / dev / urandom (lub analogu Windows), jeśli są dostępne, lub w przeciwnym razie zaczną od początku”.
Jonathan

1
@Jonathan Excellent point about numpy.random.seed(None). Zaktualizowałem odpowiedź o te informacje i link do dokumentów.
John1024,

@ curio1729 Implementacja może się różnić w zależności od systemu operacyjnego, ale numpy próbuje uczynić swoje polecenia, w tym seedkompatybilnymi.
John1024

1
@ L3viathan Dobra uwaga! Aby być bardziej kompletnym i dokładnym, powinienem wspomnieć, że dodano przesunięcie. Odpowiedź zaktualizowana. Dla tych, którzy chcą więcej szczegółów, dodałem również link do dyskusji w Wikipedii na temat generatorów liczb pseudolosowych.
John1024

38

Jeśli ustawisz za np.random.seed(a_fixed_number)każdym razem, gdy wywołasz inną losową funkcję numpy, wynik będzie taki sam:

>>> 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]

Jeśli jednak zadzwonisz raz i użyjesz różnych losowych funkcji, wyniki będą nadal różne:

>>> 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
Czy istnieje funkcja, którą można wywołać raz, tak że losowe ziarno jest ustawiane dla wszystkich kolejnych np.randomwywołań, dopóki ziarno nie zostanie zmienione? Konieczność nazywania go za każdym razem wydaje się niepotrzebnie pełna i łatwa do zapomnienia.
Lubed Up Slug

@LubedUpSlug możesz je ozdobić - przynajmniej w niektórych prostych przypadkach przetestowałem, że powinien działać. def seed_first(fun, seed=0):| \tdef wrapped(*args, **kwargs):| \t\tnp.random.seed(seed)| \t\treturn fun(*args, **kwargs)| \treturn wrapped, a następnie for m in np.random.__all__:| \tif m != 'seed':| \t\tsetattr(np.random, m, seed_first(getattr(np.random, m)))Może to jednak prowadzić do bardzo subtelnych błędów i dziwnych zachowań na dłuższą metę. (Zamień \ t na cztery spacje, a | na podziały linii ...)
Sebastian Höffner

1
@ SebastianHöffner dziękuję za komentarz. Moje pytanie było trochę mylące, ponieważ zdezorientowało mnie zdanie „Jeśli jednak wywołasz je tylko raz i użyjesz różnych funkcji losowych, wyniki będą nadal różne:„ Wywołanie np.random.seed()raz na początku programu zawsze da ten sam wynik dla tego samego ziarna, ponieważ kolejne wywołania np.randomfunkcji będą deterministycznie zmieniać ziarno dla kolejnych wywołań. Wywołanie np.random.seed()przed każdym wywołaniem np.randomfunkcji prawdopodobnie przyniesie niepożądane rezultaty.
Lubed Up Slug

17

Jak wspomniano, numpy.random.seed (0) ustawia losowe ziarno na 0, więc pseudolosowe liczby, które otrzymujesz z losowych, zaczną się od tego samego punktu. W niektórych przypadkach może to być przydatne do debugowania. JEDNAK po pewnym przeczytaniu wydaje się to niewłaściwa metoda, jeśli masz wątki, ponieważ nie jest to bezpieczne.

z różnic między numpy-random-and-random-random-in-python :

W przypadku numpy.random.seed () główna trudność polega na tym, że nie jest bezpieczna dla wątków - to znaczy nie jest bezpieczna w użyciu, jeśli masz wiele różnych wątków wykonania, ponieważ nie gwarantuje się, że działają dwa różne wątki funkcja w tym samym czasie. Jeśli nie używasz wątków i jeśli możesz oczekiwać, że nie będziesz musiał ponownie pisać programu w ten sposób w przyszłości, numpy.random.seed () powinno wystarczyć do testowania. Jeśli istnieje jakikolwiek powód, by podejrzewać, że możesz potrzebować wątków w przyszłości, na dłuższą metę o wiele bezpieczniej jest robić to, co sugerowano, i tworzyć lokalną instancję klasy numpy.random.Random. O ile mogę stwierdzić, random.random.seed () jest bezpieczny dla wątków (a przynajmniej nie znalazłem żadnych dowodów przeciwnych).

przykład jak to zrobić:

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)

może dać:

[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]

Na koniec zauważ, że mogą wystąpić przypadki, w których inicjowanie na 0 (w przeciwieństwie do zarodka, który nie ma wszystkich bitów 0) może spowodować nierównomierne rozkłady dla kilku pierwszych iteracji ze względu na sposób działania xor, ale zależy to od algorytmu i jest poza moimi obecnymi obawami i zakresem tego pytania.


12

Używałem tego bardzo często w sieciach neuronowych. Powszechnie wiadomo, że kiedy rozpoczynamy trening sieci neuronowej, losowo inicjujemy wagi. Model jest szkolony w zakresie tych wag w określonym zestawie danych. Po kilku epokach otrzymasz wyszkolony zestaw ciężarów.

Załóżmy teraz, że chcesz ponownie ćwiczyć od zera lub przekazać model innym osobom w celu odtworzenia wyników, wagi zostaną ponownie zainicjalizowane na liczby losowe, które w większości będą inne niż wcześniejsze. Uzyskane wyćwiczone wagi po tej samej liczbie epok (przy zachowaniu tych samych danych i innych parametrów), jak wcześniej, będą się różnić. Problem polega na tym, że model nie jest już odtwarzalny, ponieważ za każdym razem, gdy trenujesz swój model od zera, zapewnia on różne zestawy wag. Wynika to z faktu, że model jest inicjowany za każdym razem różnymi liczbami losowymi.

Co jeśli za każdym razem, gdy zaczynasz trening od zera, model jest inicjowany do tego samego zestawu losowych ciężarów inicjalizacyjnych? W takim przypadku Twój model może stać się odtwarzalny. Osiąga się to przez numpy.random.seed (0). Wspominając seed () o określonej liczbie, zawsze trzymasz się tego samego zestawu liczb losowych.


3

Wyobraź sobie, że pokazujesz komuś, jak zakodować coś za pomocą kilku „losowych” liczb. Używając numpy seed, mogą użyć tego samego numeru nasion i uzyskać ten sam zestaw liczb „losowych”.

Nie jest to więc przypadkowe, ponieważ algorytm wyrzuca liczby, ale wygląda jak losowo wygenerowana wiązka.


0

Losowe ziarno określa punkt początkowy, kiedy komputer generuje losową sekwencję liczb.

Załóżmy na przykład, że chcesz wygenerować liczbę losową w programie Excel (uwaga: program Excel ustawia limit 9999 dla zarodka). Jeśli wpiszesz liczbę w polu Losowe ziarno podczas procesu, będziesz mógł ponownie użyć tego samego zestawu liczb losowych. Jeśli wpiszesz „77” w polu i wpiszesz „77” przy następnym uruchomieniu generatora liczb losowych, Excel wyświetli ten sam zestaw liczb losowych. Jeśli wpiszesz „99”, otrzymasz zupełnie inny zestaw liczb. Ale jeśli wrócisz do zera 77, otrzymasz ten sam zestaw liczb losowych, od którego zacząłeś.

Na przykład: „weź liczbę x, dodaj 900 + x, a następnie odejmij 52”. Aby proces się rozpoczął, musisz podać liczbę początkową x (ziarno). Weźmy liczbę początkową 77:

Dodaj 900 + 77 = 977 Odejmij 52 = 925 Zgodnie z tym samym algorytmem druga „losowa” liczba to:

900 + 925 = 1825 Odejmij 52 = 1773 Ten prosty przykład jest wzorcem, ale algorytmy generowania liczb komputerowych są znacznie bardziej skomplikowane


0

Wszystkie liczby losowe wygenerowane po ustawieniu określonej wartości początkowej są takie same na wszystkich platformach / systemach.



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

Daje to następujący wynik: array([5, 0, 3, 3, 7]) Ponownie, jeśli uruchomimy ten sam kod, otrzymamy ten sam wynik.

Teraz, jeśli zmienimy wartość początkową 0 na 1 lub inne:

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

Daje to następujące dane wyjściowe: array([5 8 9 5 0])ale teraz dane wyjściowe nie są takie same jak powyżej.


0

Wszystkie powyższe odpowiedzi pokazują wdrożenie np.random.seed() kodu. Postaram się jak najlepiej wyjaśnić, dlaczego tak się dzieje. Komputery to maszyny zaprojektowane w oparciu o predefiniowane algorytmy. Każde wyjście z komputera jest wynikiem algorytmu zaimplementowanego na wejściu. Kiedy więc poprosimy komputer o generowanie liczb losowych, upewnij się, że są one losowe, ale komputer nie wymyślił ich losowo!

Kiedy więc piszemy, np.random.seed(any_number_here)algorytm wyświetli określony zestaw liczb, który jest unikalny dla argumentu any_number_here. To prawie tak, jakby konkretny zestaw liczb losowych można uzyskać, jeśli przekażemy poprawny argument. Będzie to jednak wymagało od nas znajomości działania algorytmu, co jest dość uciążliwe.

Na przykład, jeśli napiszę np.random.seed(10)konkretny zestaw liczb, które otrzymam, pozostaną takie same, nawet jeśli wykonam tę samą linię po 10 latach, chyba że algorytm się zmieni.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.