webentwicklung-frage-antwort-db.com.de

Wie kann ich den aktuellen Startwert des NumPy-Zufallszahlengenerators abrufen?

Folgendes importiert NumPy und legt den Samen fest.

import numpy as np
np.random.seed(42)

Ich bin jedoch nicht daran interessiert, den Samen zu setzen, sondern ihn mehr zu lesen. random.get_state() scheint den Samen nicht zu enthalten. Die Dokumentation zeigt keine offensichtliche Antwort.

Wie rufe ich den aktuellen Ausgangswert von numpy.random ab, vorausgesetzt, ich habe ihn nicht manuell festgelegt

Ich möchte den aktuellen Samen verwenden, um ihn für die nächste Iteration eines Prozesses zu übernehmen.

38
Mast

Die kurze Antwort ist, dass Sie einfach nicht können (zumindest nicht generell).

Der von numpy verwendete Mersenne Twister RNG hat 219937-1 mögliche interne Zustände, während eine einzelne 64-Bit-Ganzzahl nur 2 hat64 mögliche Werte. Es ist daher unmöglich, jeden RNG-Status einem eindeutigen Ganzzahl-Seed zuzuordnen.

Sie can können den internen Status des RNG direkt mit np.random.get_state und np.random.set_state abrufen und setzen. Die Ausgabe von get_state ist ein Tuple, dessen zweites Element ein (624,)-Array von 32-Bit-Ganzzahlen ist. Dieses Array hat mehr als genug Bits, um jeden möglichen internen Zustand des RNG darzustellen (2624 * 32 > 219937-1).

Das von get_state zurückgegebene Tuple kann wie ein Seed verwendet werden, um reproduzierbare Folgen von Zufallszahlen zu erzeugen. Zum Beispiel:

import numpy as np

# randomly initialize the RNG from some platform-dependent source of entropy
np.random.seed(None)

# get the initial state of the RNG
st0 = np.random.get_state()

# draw some random numbers
print(np.random.randint(0, 100, 10))
# [ 8 76 76 33 77 26  3  1 68 21]

# set the state back to what it was originally
np.random.set_state(st0)

# draw again
print(np.random.randint(0, 100, 10))
# [ 8 76 76 33 77 26  3  1 68 21]
51
ali_m

Diese Antwort wurde bearbeitet, nachdem ich weitere Einzelheiten zu dem vorliegenden Problem herausgefunden hatte. Ich hoffe, dass dies in der jetzigen Form eine gute Erklärung für die Antwort von ALi_m und eine wichtige Korrektur für die Antwort von Dong Justin darstellt.

Das sind meine Erkenntnisse:

  1. Nachdem Sie den zufälligen Startwert mit np.random.seed(X) eingestellt haben, können Sie ihn mit np.random.get_state()[1][0] wiederfinden .
  2. Es wird Ihnen jedoch wenig nützen.

Die Ausgabe der folgenden Codeabschnitte zeigt, warum beide Anweisungen korrekt sind.


Anweisung 1 - Sie können den zufälligen Samen mit np.random.get_state()[1][0] finden.

Wenn Sie den Zufallsstartwert mit np.random.seed(123) festlegen, können Sie den Zufallsstatus als Tupel mit state = np.random.get_state() abrufen. Unten sehen Sie sich state genauer an (ich verwende den Variablen-Explorer in Spyder). Ich verwende einen Screenshot, da die Verwendung von print(state) Ihre Konsole aufgrund der Größe des Arrays im zweiten Element des Tupels überfluten wird.

enter image description here

Sie können leicht 123 Als die erste Zahl in dem im zweiten Element enthaltenen Array sehen. Und mit seed = np.random.get_state()[1][0] erhalten Sie 123. Perfekt? Nicht ganz, weil:

Statement 2 - Es wird Ihnen jedoch wenig nützen:

Dies scheint jedoch zunächst nicht der Fall zu sein, da Sie könntenp.random.seed(123) verwenden, dieselbe Zahl mit seed = np.random.get_state()[1][0] abrufen und den Startwert mit np.random.seed(444) und setzen Sie es dann (scheinbar) mit np.random.seed(seed) auf das Szenario 123 zurück. Aber dann wüsstest du schon vorher, wie dein zufälliger Startwert lautete , also musst du es nicht so machen. Der nächste Codeabschnitt zeigt auch, dass Sie mit np.random.get_state()[1][0] nicht die erste Zahl eines zufälligen Zustands nehmen können und damit rechnen, dass genau dieses Szenario erneut erstellt wird. Beachten Sie, dass Sie höchstwahrscheinlich Ihren Kernel herunterfahren und neu starten müssen vollständig (oder np.random.seed(None) aufrufen müssen, um dies zu sehen.

Das folgende Snippet verwendet np.random.randint(), um 5 zufällige Ganzzahlen zwischen -10 und 10 zu generieren und einige Informationen über den Prozess zu speichern:

Snippet 1

# 1. Imports
import pandas as pd
import numpy as np

# 2. set random seed
#seedSet = None
seedSet = 123
np.random.seed(seedSet)

# 3. describe random state
state = np.random.get_state()
state5 = np.random.get_state()[1][:5]
seedState = np.random.get_state()[1][0]

# 4. generate random numbers
random = np.random.randint(-10, 10, size = 5)

# 5. organize and present findings
df = pd.DataFrame.from_dict({'seedSet':seedSet, 'seedState':seedState, 'state':state, 'random':random})
print(df)

Beachten Sie, dass die Spalte mit dem Namen seedState der ersten Zahl unter state entspricht. Ich hätte es als eigenständige Nummer ausdrucken können, aber ich wollte alles am selben Ort aufbewahren. Beachten Sie auch, dass seedSet = 123 Und np.random.seed(seedSet) bisher auskommentiert wurden. Und weil kein zufälliger Startwert festgelegt wurde, weichen Ihre Zahlen von meinen ab. Aber darauf kommt es hier nicht an, sondern auf die interne Konsistenz Ihrer Ergebnisse:

Ausgang 1:

   random seedSet   seedState       state
0       2    None  1558056443  1558056443
1      -1    None  1558056443  1808451632
2       4    None  1558056443   730968006
3      -4    None  1558056443  3568749506
4      -6    None  1558056443  3809593045

In diesem speziellen Fall ist seed = np.random.get_state()[1][0] gleich 1558056443. Und wenn Sie der Logik von Dong Justins Antwort (und meiner eigenen Antwort vor dieser Bearbeitung) folgen, können Sie den Zufallsstartwert mit np.random.seed(1558056443) festlegen und denselben Zufallsstatus erhalten. Das nächste Snippet zeigt, dass Sie nicht können:

Snippet 2

# 1. Imports
import pandas as pd
import numpy as np

# 2. set random seed
#seedSet = None
seedSet = 1558056443
np.random.seed(seedSet)

# 3. describe random state
#state = np.random.get_state()
state = np.random.get_state()[1][:5]
seedState = np.random.get_state()[1][0]

# 4. generate random numbers
random = np.random.randint(-10, 10, size = 5)

# 5. organize and present findings
df = pd.DataFrame.from_dict({'seedSet':seedSet, 'seedState':seedState, 'state':state, 'random':random})
print(df)

Ausgang 2:

   random     seedSet   seedState       state
0       8  1558056443  1558056443  1558056443
1       3  1558056443  1558056443  1391218083
2       7  1558056443  1558056443  2754892524
3      -8  1558056443  1558056443  1971852777
4       4  1558056443  1558056443  2881604748

Sieh den Unterschied? np.random.get_state()[1][0] ist für Ausgang 1 und Ausgang 2 identisch, der Rest der Ausgabe ist jedoch nicht identisch (am wichtigsten ist, dass die Zufallszahlen nicht identisch sind). Also, wie ALi_m bereits klar festgestellt hat:

Es ist daher unmöglich, jeden RNG-Zustand einem eindeutigen Integer-Startwert zuzuordnen.

11
vestland

Überprüfen Sie das erste Element des Arrays, das von np.random.get_state() zurückgegeben wird. Es scheint mir der zufällige Samen.

0
Dong Justin