Was macht numpy.random.seed (0)?

281

Was macht np.random.seedder folgende Code aus einem Scikit-Learn-Tutorial? Ich bin nicht sehr vertraut mit NumPys Zeug zum Zufallszustandsgenerator, daher würde ich die Erklärung eines Laien für diese Begriffe wirklich begrüßen.

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

Antworten:

552

np.random.seed(0) macht die Zufallszahlen vorhersehbar

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

Beim Zurücksetzen des Startwerts (jedes Mal) wird jedes Mal derselbe Satz von Zahlen angezeigt.

Wenn der zufällige Startwert nicht zurückgesetzt wird, werden bei jedem Aufruf unterschiedliche Zahlen angezeigt:

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

(Pseudo-) Zufallszahlen beginnen mit einer Zahl (dem Startwert), multiplizieren sie mit einer großen Zahl, addieren einen Versatz und nehmen dann Modulo dieser Summe. Die resultierende Zahl wird dann als Startwert verwendet, um die nächste "Zufallszahl" zu erzeugen. Wenn Sie den Startwert festlegen (jedes Mal), wird jedes Mal dasselbe ausgeführt, und Sie erhalten die gleichen Zahlen.

Wenn Sie scheinbar zufällige Zahlen möchten, setzen Sie den Startwert nicht. Wenn Sie Code haben, der Zufallszahlen verwendet, die Sie debuggen möchten, kann es jedoch sehr hilfreich sein, den Startwert vor jedem Lauf festzulegen, damit der Code bei jeder Ausführung dasselbe tut.

Rufen Sie an, um die meisten Zufallszahlen für jeden Lauf zu erhalten numpy.random.seed(). Dies führt dazu, dass numpy den Startwert auf eine Zufallszahl setzt, die von /dev/urandomoder seinem Windows-Analogon erhalten wurde, oder, falls keine davon verfügbar ist, die Uhr verwendet.

Weitere Informationen zur Verwendung von Seeds zur Erzeugung von Pseudozufallszahlen finden Sie in Wikipedia .

John1024
quelle
86
Diese Antwort sollte der Dokumentation von numpy hinzugefügt werden. Danke dir.
Gorjanz
8
Wenn Sie aufrufen numpy.random.seed(None), wird "versucht, Daten aus / dev / urandom (oder dem Windows-Analogon) zu lesen, falls verfügbar, oder andernfalls aus der Uhr".
Jonathan
1
@ Jonathan Ausgezeichneter Punkt über numpy.random.seed(None). Ich habe die Antwort mit diesen Informationen und einem Link zu den Dokumenten aktualisiert.
John1024
@ curio1729 Die Implementierung kann von Betriebssystem zu Betriebssystem unterschiedlich sein, aber numpy versucht, seine Befehle einschließlich seedkompatibel zu machen.
John1024
1
@ L3viathan Guter Punkt! Um vollständiger und genauer zu sein, hätte ich erwähnen sollen, dass ein Versatz hinzugefügt wird. Antwort aktualisiert. Für diejenigen, die mehr Details wünschen, habe ich auch einen Link zu Wikipedia's Diskussion über Pseudozufallszahlengeneratoren hinzugefügt.
John1024
38

Wenn Sie die Einstellung np.random.seed(a_fixed_number)jedes Mal festlegen, wenn Sie die andere Zufallsfunktion des Numpys aufrufen, ist das Ergebnis dasselbe:

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

Wenn Sie es jedoch nur einmal aufrufen und verschiedene Zufallsfunktionen verwenden, sind die Ergebnisse immer noch unterschiedlich:

>>> 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]
Zhun Chen
quelle
3
Gibt es eine Funktion, die einmal aufgerufen werden kann, sodass für alle nachfolgenden np.randomAufrufe ein zufälliger Startwert festgelegt wird, bis der Startwert geändert wird? Es jedes Mal anrufen zu müssen, erscheint unnötig ausführlich und leicht zu vergessen.
Lubed Up Slug
@LubedUpSlug können Sie sie dekorieren - zumindest für einige einfache Fälle, die ich getestet habe, sollte es funktionieren. def seed_first(fun, seed=0):| \tdef wrapped(*args, **kwargs):| \t\tnp.random.seed(seed)| \t\treturn fun(*args, **kwargs)| \treturn wrappedund dann for m in np.random.__all__:| \tif m != 'seed':| \t\tsetattr(np.random, m, seed_first(getattr(np.random, m)))Dies könnte jedoch auf lange Sicht zu sehr subtilen Fehlern und seltsamem Verhalten führen. (Ersetzen Sie \ t durch vier Leerzeichen und | durch Zeilenumbrüche ...)
Sebastian Höffner
1
@ SebastianHöffner danke für deinen Kommentar. Meine Frage war ein wenig falsch, weil ich durch den Satz verwirrt war: "Wenn Sie ihn jedoch nur einmal aufrufen und verschiedene Zufallsfunktionen verwenden, sind die Ergebnisse immer noch unterschiedlich:" Ein np.random.seed()einmaliger Aufruf zu Beginn eines Programms führt immer zum gleichen Ergebnis für denselben Startwert, da die nachfolgenden Aufrufe von np.randomFunktionen den Startwert für nachfolgende Aufrufe deterministisch ändern. Ein Aufruf np.random.seed()vor jedem np.randomFunktionsaufruf führt wahrscheinlich zu unerwünschten Ergebnissen.
Geschmierte Schnecke
17

Wie bereits erwähnt, setzt numpy.random.seed (0) den zufälligen Startwert auf 0, sodass die Pseudozufallszahlen, die Sie zufällig erhalten, am selben Punkt beginnen. Dies kann in einigen Fällen zum Debuggen hilfreich sein. Nach einigem Lesen scheint dies jedoch der falsche Weg zu sein, wenn Sie Threads haben, da diese nicht threadsicher sind.

von Unterschieden zwischen numpy-random-und-random-random-in-Python :

Bei numpy.random.seed () besteht die Hauptschwierigkeit darin, dass es nicht threadsicher ist - das heißt, es ist nicht sicher zu verwenden, wenn Sie viele verschiedene Ausführungsthreads haben, da es nicht garantiert funktioniert, wenn zwei verschiedene Threads ausgeführt werden die Funktion zur gleichen Zeit. Wenn Sie keine Threads verwenden und davon ausgehen können, dass Sie Ihr Programm in Zukunft nicht mehr auf diese Weise neu schreiben müssen, sollte numpy.random.seed () zu Testzwecken in Ordnung sein. Wenn Grund zu der Annahme besteht, dass Sie in Zukunft möglicherweise Threads benötigen, ist es auf lange Sicht viel sicherer, die vorgeschlagenen Schritte auszuführen und eine lokale Instanz der Klasse numpy.random.Random zu erstellen. Soweit ich das beurteilen kann, ist random.random.seed () threadsicher (oder zumindest habe ich keine gegenteiligen Beweise gefunden).

Beispiel dafür:

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)

kann geben:

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

Beachten Sie schließlich, dass es Fälle geben kann, in denen die Initialisierung auf 0 (im Gegensatz zu einem Startwert, der nicht alle Bits 0 enthält) aufgrund der Funktionsweise von xor zu ungleichmäßigen Verteilungen für einige wenige erste Iterationen führen kann. Dies hängt jedoch vom Algorithmus ab und ist jenseits meiner gegenwärtigen Sorgen und des Umfangs dieser Frage.

ntg
quelle
12

Ich habe dies sehr oft in neuronalen Netzen verwendet. Es ist bekannt, dass wir zu Beginn des Trainings eines neuronalen Netzwerks die Gewichte zufällig initialisieren. Das Modell wird anhand dieser Gewichte an einem bestimmten Datensatz trainiert. Nach der Anzahl der Epochen erhalten Sie trainierte Gewichte.

Angenommen, Sie möchten erneut von Grund auf trainieren oder das Modell an andere weitergeben, um Ihre Ergebnisse zu reproduzieren. Die Gewichte werden erneut mit Zufallszahlen initialisiert, die sich größtenteils von früheren unterscheiden. Die erhaltenen trainierten Gewichte nach der gleichen Anzahl von Epochen (wobei dieselben Daten und andere Parameter beibehalten werden) wie zuvor werden unterschiedlich sein. Das Problem ist, dass Ihr Modell nicht mehr reproduzierbar ist. Jedes Mal, wenn Sie Ihr Modell von Grund auf neu trainieren, erhalten Sie unterschiedliche Gewichtssätze. Dies liegt daran, dass das Modell jedes Mal durch unterschiedliche Zufallszahlen initialisiert wird.

Was ist, wenn das Modell jedes Mal, wenn Sie mit dem Training von Grund auf neu beginnen, mit demselben Satz zufälliger Initialisierungsgewichte initialisiert wird? In diesem Fall könnte Ihr Modell reproduzierbar werden. Dies wird durch numpy.random.seed (0) erreicht. Wenn Sie seed () für eine bestimmte Zahl erwähnen, halten Sie immer an denselben Zufallszahlen fest.

Ein Santosh
quelle
3

Stellen Sie sich vor, Sie zeigen jemandem, wie man etwas mit einer Reihe von "Zufallszahlen" codiert. Durch die Verwendung von Numpy Seed können sie dieselbe Startnummer verwenden und denselben Satz von "Zufallszahlen" erhalten.

Es ist also nicht gerade zufällig, weil ein Algorithmus die Zahlen ausspuckt, aber es sieht aus wie ein zufällig generierter Haufen.

cjHerold
quelle
0

Ein zufälliger Startwert gibt den Startpunkt an, an dem ein Computer eine Zufallszahlenfolge generiert.

Angenommen, Sie möchten eine Zufallszahl in Excel generieren (Hinweis: Excel legt ein Limit von 9999 für den Startwert fest). Wenn Sie während des Vorgangs eine Zahl in das Feld "Zufälliger Startwert" eingeben, können Sie denselben Satz von Zufallszahlen erneut verwenden. Wenn Sie "77" in das Feld und beim nächsten Ausführen des Zufallszahlengenerators "77" eingegeben haben, zeigt Excel denselben Satz von Zufallszahlen an. Wenn Sie "99" eingeben, erhalten Sie einen völlig anderen Satz von Zahlen. Wenn Sie jedoch zu einem Startwert von 77 zurückkehren, erhalten Sie die gleichen Zufallszahlen, mit denen Sie begonnen haben.

Beispiel: "Nehmen Sie eine Zahl x, addieren Sie 900 + x und subtrahieren Sie dann 52." Damit der Prozess gestartet werden kann, müssen Sie die Startnummer x (den Startwert) angeben. Nehmen wir die Startnummer 77:

Addiere 900 + 77 = 977 Subtrahiere 52 = 925 Nach dem gleichen Algorithmus wäre die zweite "Zufallszahl":

900 + 925 = 1825 Subtrahieren 52 = 1773 Dieses einfache Beispiel folgt einem Muster, aber die Algorithmen zur Erzeugung von Computernummern sind viel komplizierter

sunidhi mittal
quelle
0

Alle Zufallszahlen, die nach dem Festlegen eines bestimmten Startwerts generiert werden, sind auf allen Plattformen / Systemen gleich.

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

Dies erzeugt die folgende Ausgabe: array([5, 0, 3, 3, 7]) Wenn wir wieder denselben Code ausführen, erhalten wir dasselbe Ergebnis.

Wenn wir nun den Startwert 0 auf 1 oder andere ändern:

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

Dies erzeugt die folgende Ausgabe: array([5 8 9 5 0])aber jetzt ist die Ausgabe nicht die gleiche wie oben.

Humayun Ahmad Rajib
quelle
0

Alle obigen Antworten zeigen die Implementierung von np.random.seed() In-Code. Ich werde mein Bestes geben, um kurz zu erklären, warum es tatsächlich passiert. Computer sind Maschinen, die auf vordefinierten Algorithmen basieren. Jede Ausgabe von einem Computer ist das Ergebnis des auf der Eingabe implementierten Algorithmus. Wenn wir also einen Computer auffordern, Zufallszahlen zu generieren, stellen Sie sicher, dass diese zufällig sind, aber der Computer hat sie nicht nur zufällig erfunden!

Wenn wir also schreiben, gibt np.random.seed(any_number_here)der Algorithmus einen bestimmten Satz von Zahlen aus, der für das Argument eindeutig ist any_number_here. Es ist fast so, als ob ein bestimmter Satz von Zufallszahlen erhalten werden kann, wenn wir das richtige Argument übergeben. Dazu müssen wir jedoch wissen, wie der Algorithmus funktioniert, was ziemlich langwierig ist.

Wenn ich zum Beispiel np.random.seed(10)den bestimmten Satz von Zahlen schreibe, den ich erhalte, bleibt er auch dann gleich, wenn ich nach 10 Jahren dieselbe Zeile ausführe, sofern sich der Algorithmus nicht ändert.

WadeWilson
quelle