2015-09-20 16 views
5

Bei der Suche nach Reproduzierbarkeit in Python-Code unter Verwendung von Zufallszahlengeneratoren scheint es der empfohlene Ansatz zu sein, separate RandomState-Objekte zu konstruieren. Leider können einige essentielle Pakete wie scipy.stats (nach bestem Wissen und Gewissen) nicht auf einen bestimmten RandomState eingestellt werden und verwenden nur den aktuellen Zustand von numpy.random. Meine aktuelle Problemumgehung ist einen Kontext-Manager zu verwenden, die den Zustand des RNG speichert und setzt es dann beim Verlassen wie folgt:Python: Gefahren des vorübergehenden Änderns der Zufallssaat mithilfe eines Kontextmanagers?

class FixedSeed: 
    def __init__(self, seed): 
     self.seed = seed 
     self.state = None 

    def __enter__(self): 
     self.state = rng.get_state() 
     np.random.seed(self.seed) 

    def __exit__(self, exc_type, exc_value, traceback): 
     np.random.set_state(self.state) 

Es gibt über viele Warnungen in der Dokumentation, die den Zustand in irgendeiner Weise zu ändern - Ist der obige Ansatz generell sicher? (In dem Sinne, dass die Änderung ist lokal auf den Kontext und dass der Rest meines Codes bleibt davon unberührt)

Antwort

2

Die numpy documentation Ansprüche:

set_state und GET_STATE nicht benötigt werden mit einem der zufällig zu arbeiten Verteilungen in NumPy. Wenn der interne Status manuell geändert wird, sollte der Benutzer genau wissen, was er tut.

das klingt erschreckend. Eine mögliche Interpretation dieser Warnung auf einer öffentlichen, dokumentierten Schnittstelle ist, dass "genau wissen" bedeutet "weiß, dass das erneute Seeding eines PRNG Willy-Nilly die Zufälligkeit stark reduziert". Aber Sie wissen, dass Sie die Zufälligkeit sehr spezifisch für den Zeitraum Ihres Kontextes reduzieren wollen.

Zur Unterstützung dieser Vermutung, schaute ich zu numpy/test_random.py welche enthält Code wie:

class TestSeed(TestCase): 
    def test_scalar(self): 
     s = np.random.RandomState(0) 
     assert_equal(s.randint(1000), 684) 
     s = np.random.RandomState(4294967295) 
     assert_equal(s.randint(1000), 419) 

weil es tun sie deterministische Ergebnisse benötigen. Beachten Sie, dass sie eine Instanz eines np.random.RandomState erstellen, aber ich konnte keinen Hinweis in dem Code finden, der set_state() irgendetwas brechen wird.

Im Zweifelsfall, schreiben Sie eine Test-Suite, die

  1. Seeds den Standard RNG auf einen festen Wert
  2. Prüft, ob die Standard-RNG liefert die gleichen sind, die erwarteten Werte jedes Mal
  3. Verwendet Ihre Kontext-Manager
  4. bestätigen, dass eine neue Sequenz von Werten erzeugt werden
  5. bestätigen, dass der ursprüngliche seeded RNG aus (1) setzt seine erwartete Sequenz auszusenden