Erstellen Sie konsistent dasselbe zufällige Numpy-Array


88

Ich warte darauf, dass ein anderer Entwickler einen Code fertigstellt, der ein np-Array mit einer Form (100.2000) mit Werten von entweder -1,0 oder 1 zurückgibt.

In der Zwischenzeit möchte ich zufällig ein Array mit denselben Merkmalen erstellen, damit ich einen Vorsprung bei meiner Entwicklung und beim Testen habe. Die Sache ist, dass ich möchte, dass dieses zufällig erstellte Array jedes Mal gleich ist, damit ich nicht gegen ein Array teste, dessen Wert sich jedes Mal ändert, wenn ich meinen Prozess erneut ausführe.

Ich kann mein Array so erstellen, aber es gibt eine Möglichkeit, es so zu erstellen, dass es jedes Mal gleich ist. Ich kann das Objekt einlegen und entfernen, frage mich aber, ob es einen anderen Weg gibt.

r = np.random.randint(3, size=(100, 2000)) - 1

Antworten:


82

Setzen Sie einfach den Zufallszahlengenerator mit einem festen Wert, z

numpy.random.seed(42)

Auf diese Weise erhalten Sie immer die gleiche Zufallszahlenfolge.


42
Jemand hat sich in die numpy.random.seed()Funktion eingeschlichen, als ich nicht aufgepasst habe . :-) Ich habe es absichtlich aus dem Originalmodul herausgelassen. Ich empfehle den Leuten, ihre eigenen Instanzen zu verwenden RandomStateund diese Objekte weiterzugeben.
Robert Kern

6
Robert leistet einen wichtigen Beitrag zu Numpy. Ich denke, wir sollten seiner Meinung etwas Gewicht geben.
veraltet

10
@deprecated: Ich bin dankbar für Roberts Arbeit, aber seine Arbeit ist kein Ersatz dafür, eine Begründung für die Empfehlung zu geben. Wenn von der Verwendung numpy.random.seed()abgeraten wird, sollte dies in der Dokumentation erwähnt werden . Anscheinend teilen andere Mitwirkende an NumPy Roberts Meinung nicht. Nichts für ungut, ich bin nur neugierig.
Sven Marnach

13
Dies entspricht der random.seedVerwendung eines random.RandomObjekts in der Python-Standardbibliothek. Wenn Sie random.seedoder verwenden numpy.random.seed, setzen Sie alle zufälligen Instanzen ein, sowohl in Ihrem Code als auch in jedem Code, den Sie aufrufen, oder in jedem Code, der in derselben Sitzung wie Ihre ausgeführt wird. Wenn diese Dinge davon abhängen, dass diese Dinge tatsächlich zufällig sind, treten Probleme auf. Wenn Sie Code bereitstellen, der den zufälligen Startwert festlegt, können Sie eine Sicherheitslücke einführen.
Asmeurer

3
@asmeurer Wer aus Sicherheitsgründen einen Pseudozufallszahlengenerator verwendet, weiß wahrscheinlich nicht, was er tut.
JAB

188

Erstellen Sie Ihre eigene Instanz von numpy.random.RandomState()mit Ihrem ausgewählten Samen. Verwenden Sie diese Option numpy.random.seed()nur, um unflexible Bibliotheken zu umgehen, mit denen Sie Ihre eigene RandomStateInstanz nicht weitergeben können.

[~]
|1> from numpy.random import RandomState

[~]
|2> prng = RandomState(1234567890)

[~]
|3> prng.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])

[~]
|4> prng2 = RandomState(1234567890)

[~]
|5> prng2.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])

7
Haben Sie Gründe für Ihre Empfehlung? Was ist los mit numpy.random.seed()? Ich weiß, dass es nicht threadsicher ist, aber es ist sehr praktisch, wenn Sie keine Thread-Sicherheit benötigen.
Sven Marnach

49
Es geht hauptsächlich darum, gute Gewohnheiten zu entwickeln. Möglicherweise benötigen Sie jetzt keine unabhängigen Streams, in Sven-6-Monaten jedoch möglicherweise. Wenn Sie Ihre Bibliotheken so schreiben, dass sie die Methoden direkt verwenden numpy.random, können Sie später keine unabhängigen Streams erstellen. Es ist auch einfacher, Bibliotheken mit der Absicht zu schreiben, PRNG-Streams zu steuern. Es gibt immer mehrere Möglichkeiten, Ihre Bibliothek zu betreten, und jede von ihnen sollte eine Möglichkeit haben, den Startwert zu steuern. Das Weitergeben von PRNG-Objekten ist eine sauberere Methode, als sich darauf zu verlassen numpy.random.seed(). Leider ist dieses Kommentarfeld zu kurz, um weitere Beispiele zu enthalten. :-)
Robert Kern

25
Eine andere Art, Roberts Argumentation zu beschreiben: Die Verwendung von numpy.random.seed verwendet eine globale Variable, um den PRNG-Status beizubehalten, und hier gelten dieselben Standardgründe, warum globale Variablen schlecht sind.
Robie Basak

9
Wenn Sie möchten, dass die PRNGs unabhängig sind, setzen Sie nichts ein. Verwenden Sie einfach numpy.random.RandomState()ohne Argumente. Dadurch wird der Status mit eindeutigen Werten versehen, die für solche Dinge aus Ihren Betriebssystemfunktionen stammen ( /dev/urandomauf UNIX-Computern und dem dortigen Windows-Äquivalent). Wenn numpy.random.RandomState(1234567890)dies bei Ihnen nicht funktioniert, zeigen Sie bitte genau an, was Sie eingegeben haben, und genau die Fehlermeldung, die Sie erhalten haben.
Robert Kern

4
Keine gute Idee. Verwenden Sie numpy.random.RandomState()ohne Argumente für die besten Ergebnisse.
Robert Kern

3

Wenn Sie andere Funktionen verwenden, die auf einem zufälligen Status basieren, können Sie nicht nur einen Gesamtsamen festlegen, sondern sollten stattdessen eine Funktion erstellen, um Ihre zufällige Liste von Zahlen zu generieren und den Startwert als Parameter der Funktion festzulegen. Dies wird keine anderen Zufallsgeneratoren im Code stören:

# Random states
def get_states(random_state, low, high, size):
    rs = np.random.RandomState(random_state)
    states = rs.randint(low=low, high=high, size=size)
    return states

# Call function
states = get_states(random_state=42, low=2, high=28347, size=25)

2

Es ist wichtig zu verstehen, was der Keim eines Zufallsgenerators ist und wann / wie er in Ihrem Code festgelegt ist (siehe z. B. hier für eine schöne Erklärung der mathematischen Bedeutung des Keims).

Dazu müssen Sie den Samen setzen, indem Sie Folgendes tun:

random_state = np.random.RandomState(seed=your_favorite_seed_value)

Es ist dann wichtig, die Zufallszahlen aus random_state und nicht aus np.random zu generieren. Dh du solltest tun:

random_state.randint(...)

anstatt

np.random.randint(...) 

Dadurch wird eine neue Instanz von RandomState () erstellt und im Grunde genommen die interne Uhr Ihres Computers verwendet, um den Startwert festzulegen.


2

Ich möchte nur etwas in Bezug auf die Antwort von @Robert Kern klarstellen, nur für den Fall, dass dies nicht klar ist. Selbst wenn Sie das verwenden RandomState, müssten Sie es jedes Mal initialisieren, wenn Sie eine numpy-Zufallsmethode wie in Roberts Beispiel aufrufen. Andernfalls erhalten Sie die folgenden Ergebnisse.

Python 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 19:07:31) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> prng = np.random.RandomState(2019)
>>> prng.randint(-1, 2, size=10)
array([-1,  1,  0, -1,  1,  1, -1,  0, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([-1, -1, -1,  0, -1, -1,  1,  0, -1, -1])
>>> prng.randint(-1, 2, size=10)
array([ 0, -1, -1,  0,  1,  1, -1,  1, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([ 1,  1,  0,  0,  0, -1,  1,  1,  0, -1])
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.