Il modo migliore per seminare N generatori di numeri casuali indipendenti da 1 valore


10

Nel mio programma ho bisogno di eseguire N thread separati ciascuno con il proprio RNG che viene utilizzato per campionare un set di dati di grandi dimensioni. Devo essere in grado di seminare l'intero processo con un singolo valore in modo da poter riprodurre i risultati.

È sufficiente aumentare semplicemente in sequenza il seme per ciascun indice?

Attualmente uso numpys' RandomStateche utilizza una pseudo-casuali generatore di numeri Mersenne Twister.

Snippet di codice qui sotto:

# If a random number generator seed exists
if self.random_generator_seed:
    # Create a new random number generator for this instance based on its
    # own index
    self.random_generator_seed += instance_index
    self.random_number_generator = RandomState(self.random_generator_seed)

In sostanza, inizio con un seed immesso dall'utente (se esiste) e per ogni istanza / thread aggiungo in sequenza l'indice (da 0 a N-1) dell'istanza in esecuzione. Non so se questa è una buona pratica o se esiste un modo migliore per farlo.


1
Sai in anticipo quanti valori pseudo casuali utilizzerà ogni thread - o almeno puoi ottenere una buona stima del limite superiore?
whuber

No, non posso. Campiona le regioni che vengono sommate fino a quando non si raggiunge una soglia. Le dimensioni delle regioni possono variare in modo significativo.
EricR

Risposte:


9

Non è una grande pratica, certamente. Ad esempio, considera cosa succede quando esegui due esecuzioni con seed root di 12345 e 12346. Ogni esecuzione avrà N-1stream in comune.

Le implementazioni di Mersenne Twister (incluso numpy.randome random) utilizzano in genere un PRNG diverso per espandere il seme intero nel vettore di stato grande (624 numeri interi a 32 bit) utilizzato da MT; questo è l'array di RandomState.get_state(). Un buon modo per fare quello che vuoi è eseguire quel PRNG, seminato con il tuo intero di input una volta, e ottenere N*624interi a 32 bit da esso. Dividi quel flusso in Nvettori di stato e usalo RandomState.set_state()per inizializzare esplicitamente ogni RandomStateistanza. Potrebbe essere necessario consultare le fonti C numpy.randomo _randomdalla libreria standard per ottenere quel PRNG (sono gli stessi). Non sono sicuro che qualcuno abbia implementato una versione autonoma di quel PRNG per Python.


Penso che questa potrebbe essere la migliore soluzione che ho sentito finora. Non penso che importi molto su come ho diviso il flusso, anche se corretto? Sembra molto più improbabile avere una sequenza duplicata su 624 numeri interi a 32 bit tra istanze, indipendentemente da come vengono scelti dal PRNG iniziale e dal seme.
EricR

1
In realtà, tornerò indietro un po '. Non mi è chiaro che l'inizializzatore PRNG sia progettato per avere arbitrariamente molti valori ricavati da esso. Considerare l'utilizzo di un altro PRNG di qualità (preferibilmente non correlato a MT) per generare il flusso di stato. Si può implementare un HMAC-DRBG (un PRNG che utilizza un HMAC come primitiva crittografica) usando relativamente semplicemente la libreria standard. La sicurezza crittografica non è un problema; solo la facilità di implementazione e qualità del bitstream. Dovrai assicurarti che non vengano realizzati vettori tutti zero, nella rarissima opportunità.
Robert Kern,

Oppure utilizza una delle RandomStateimplementazioni più recenti in sviluppo che utilizza un algoritmo con flussi impostabili. Cioè, si inizializza ogni RandomStateistanza con lo stesso seed e ID flusso diversi (semplicemente incrementato va bene) e si garantisce flussi indipendenti. pypi.python.org/pypi/randomstate
Robert Kern,

4

Una soluzione che viene utilizzato in elaborazione in parallelo è quello di utilizzare il generatore di numeri casuali , dove è il vostro seme, per -batches:Φ(u)uN

  1. generaΦ(u),ΦN(u),Φ2*N(u),...
  2. generaΦ2(u),Φ1+N(u),Φ1+2*N(u),...
  3. ...
  4. generaΦN-1(u),ΦN-1+N(u),ΦN-1+2*N(u),...

dove . In questo modo usi un singolo seme e le tue sequenze sono tutte uniformi e indipendenti.Φn(u)=Φ(Φn-1(u))


2

Ora esiste un pacchetto Python chiamato RandomGen che ha metodi per raggiungere questo obiettivo.

Esso supporta flussi indipendenti creati da un singolo seme, così come un protocollo di salto per i vecchi generatori di numeri casuali, come MT19937.


0

Alcune persone affermano che ci sono correlazioni nei numeri casuali generati da semi sequenziali. /programming/10900852/near-seeds-in-random-number-generation-may-give-similar-random-numbers Non sono sicuro di quanto sia vero.

Se sei preoccupato, perché non utilizzare un singolo generatore di numeri casuali per scegliere i semi per tutti gli altri generatori?


Semplicemente perché non voglio avere alcuna possibilità di generare casualmente lo stesso seme per più di 1 generatore. Ovviamente potrei fare un po 'di lavoro di programmazione per evitare che ciò accada, ma poi non so come sarebbe meglio che raccogliere semi in sequenza in primo luogo.
EricR

1
A quanto pare , le correlazioni sono possibili con i semi sequenziali ... Tuttavia, come l' articolo legato a quella risposta spettacoli dal Blog di John D Cook, utilizzando uno RNG per generare semi per altri generatori è di gran lunga peggio, perché si esegue nel problema di compleanno! Dice che la generazione casuale di 1000 semi senza segno a 16 bit ha una probabilità del 99,95% di sovrapporsi!
Praveen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.