2016-04-25 18 views
11

Ho notato che è possibile inserire vari numeri all'interno di numpy.random.seed(), ad esempio numpy.random.seed(1), numpy.random.seed(101). Cosa significano i diversi numeri? Come scegli i numeri?Quali numeri posso inserire in numpy.random.seed()?

+1

Non importa in quanto determina solo quale sarà la successiva sequenza "casuale". Utile per il test, quindi i valori non variano da run-to-run. Di solito uso '42' ... – martineau

risposta

0

Fondamentalmente il numero garantisce la stessa "casualità" ogni volta.

Più correttamente, il numero è un seme, che può essere un numero intero, una matrice (o un'altra sequenza) di numeri interi di qualsiasi lunghezza o il valore predefinito (nessuno). Se seed è none, random cercherà di leggere i dati da/dev/urandom se disponibili o di fare un seed dall'orologio altrimenti.

Modifica: In tutta onestà, finché il tuo programma non è qualcosa che deve essere super sicuro, non dovrebbe importare quello che scegli. In questo caso, non utilizzare questi metodi: utilizzare os.urandom() o SystemRandom se si richiede un generatore di numeri pseudo casuali crittograficamente sicuro.

Il concetto più importante da comprendere qui è quello della pseudo-casualità. Una volta compresa questa idea, puoi determinare se il tuo programma ha davvero bisogno di un seed ecc. Ti consiglio di leggere here.

+4

Questa risposta mi sembra incompleta. Va bene per me scrivere "random.seed (random.random())"? 7 è meglio di 4? Sta solo andando a cancellare l'array? Fondamentalmente, cosa sta succedendo qui? "Come scegli il numero" sembra la linea più importante nella domanda, imo –

+0

@en_Knight - Ho appena tentato di fornire questo tipo di dettaglio nella mia risposta. –

0

Per comprendere il significato dei semi casuali, è necessario prima comprendere la sequenza numerica "pseudo-casuale" poiché i valori sono calcolati utilizzando un algoritmo deterministico.

Quindi è possibile pensare a questo numero come valore iniziale per calulare il numero successivo ottenuto dal generatore casuale. Mettere lo stesso valore qui farà sì che il tuo programma ottenga lo stesso valore "casuale" ogni volta, quindi il tuo programma diventa deterministico.

Come detto in questo post

essi (numpy.random e random.random) sia utilizzare la sequenza di Mersenne Twister per generare i loro numeri casuali, e sono entrambi completamente deterministica - cioè, se si conosce un paio chiave bit di informazioni, è possibile prevedere con assoluta certezza quale numero verrà dopo.

Se ti interessa davvero la casualità, chiedi all'utente di generare un po 'di rumore (alcune parole arbitrarie) o semplicemente di impostare l'ora del sistema come seme.

Se i codici funzionano su CPU Intel (o AMD con chip più recenti), suggerisco anche di controllare il pacchetto RdRand che utilizza l'istruzione cpu rdrand per raccogliere la casualità "vera" (hardware).

Refs:

  1. Random seed
  2. What is a seed in terms of generating a random number
+0

Questo sembra importante: "Se ti interessa veramente la casualità, chiedi all'utente di generare un po 'di rumore (alcune parole arbitrarie) o di mettere semplicemente il tempo del sistema come seme", ma penso di acquistarne solo la metà. Sembra che gli utenti possano scegliere "casualmente" parole comuni simili ogni volta - ppl non è eccezionale per essere casuali. Il tempo è un consiglio piuttosto solido. Ma non c'è abbastanza per me sapere cosa fare - ad esempio, in base a ciò che hai scritto sembra saggio per me continuare a reimpostare il seme in sessione per assicurare una casualità super imprevedibile, quando in realtà farlo sarebbe controproducente –

+0

Non ho suggerito che continuare a ripristinare sia buono. Al contrario, penso che dovresti impostare il seme ** solo una volta **. Il punto chiave è quello di impedire al malintenzionato di indovinare il tuo numero casuale. Se qualcuno riesce a indovinare il tuo seme per la prima volta, suppongo che sappia anche il resto. – gdlmx

+0

Non vedo alcun tag di sicurezza .. numpy è usato molto per la modellazione e la simulazione, e se questo è il caso, allora forse non ci interessiamo tanto agli aggressori quanto essere in grado di riprodurre i nostri esperimenti, giusto? Il mio commento su "continuare a reimpostare" non era quello che sostenevi esplicitamente * per * esso, ma che non ci sono molte informazioni qui su come funzionano effettivamente i semi. Imo, ci dovrebbero essere abbastanza informazioni per farmi sapere come impostare un seme e quali sono le cose cattive da fare, se la domanda chiede come scegliere un seme, e non c'è nulla qui per dissipare quell'errore comune, ad es. –

6

considerare un semplice generatore di numeri casuali:

Z[i] = (a*Z[i-1] + c) % m 

Qui, Z[i] è il ith numero casuale, a è il moltiplicatore e c è l'incremento - per le diverse combinazioni a, c e m si hanno diversi generatori.Questo è noto come linear congruential generator introdotto da Lehmer. Il resto di tale divisione, o modulo (%), genererà un numero compreso tra zero e m-1 e impostando U[i] = Z[i]/m otterrete numeri casuali tra zero e uno.

Come forse avrete notato, per iniziare questo processo generativo - per avere un Z[1] è necessario avere un Z[0] - un valore iniziale. Questo valore iniziale che avvia il processo è chiamato seme. Date un'occhiata a questo esempio:

enter image description here

Il valore iniziale, il seme è determinata come 7 per avviare il processo. Tuttavia, quel valore non viene utilizzato per generare un numero casuale. Invece, viene utilizzato per generare il primo Z.

La caratteristica più importante di un generatore di numeri pseudo-casuali sarebbe la sua imprevedibilità. Generalmente, finché non condividi il tuo seme, stai bene con tutti i semi, dato che i generatori oggi sono molto più complessi di questo. Tuttavia, come ulteriore passo puoi generare il seme anche casualmente. È possibile saltare i primi numeri n come un'altra alternativa.

Fonte principale: Law, A. M. (2007). Modellazione e analisi di simulazione. Tata McGraw-Hill.

+0

Mi piace questa risposta. Poche cose però: "la caratteristica più importante ... è l'imprevedibilità": potresti volere la riproducibilità algoritmica (perché stai facendo modellazione non di sicurezza) nel qual caso vuoi la prevedibilità opposta. Inoltre: come si genera un seme casualmente prima che abbiano un seme con cui generare numeri casuali? Prendi il timestamp dell'eccezione di overflow di ricorsione che è stata sollevata :)? Inoltre, numpy esplicitamente non usa quel generatore casuale - questo consiglio vale per il modulo random di Numpy, a cui è stato chiesto? –

+0

Concordo sul fatto che la riproducibilità è molto importante - è per questo che condividiamo i semi ma quella riproducibilità non significa esattamente prevedibilità, penso. I numeri avrebbero ancora le caratteristiche di uniformità e indipendenza. Non sarebbero previsti solo usando quei numeri. Potrebbero essere * calcolati * conoscendo il processo sottostante. – ayhan

+0

Per definire il seme: AFAIK molte applicazioni stanno usando qualcosa di simile a quello che hai descritto: i nanosecondi del tempo corrente mod qualche altra cosa, ecc. Python sta usando Mersenne-Twister, e non ne sono sicuro, ma probabilmente lo uso anche numpy https://en.wikipedia.org/wiki/Mersenne_Twister È diverso dai generatori congruenziali lineari, ma ha anche questo processo ricorsivo, fintanto che hai qualcosa chiamato seed per avviare un processo, la stessa logica dovrebbe applicarsi, IMHO. :) – ayhan

1

La risposta breve:

Ci sono tre modi per seed() un generatore di numeri casuali in numpy.random:

  • uso alcun argomento o utilizzare None - RNG si inizializza da generatore di numeri casuali del sistema operativo (che in genere è crittograficamente casuale)

  • utilizza un numero intero a 32 bit N - l'RNG lo utilizzerà per inizializzare il suo stato in base a una funzione deterministica (stesso seme → stesso stato)

  • utilizzare una sequenza array come di interi a 32 bit n , n , n , ecc - di nuovo, il RNG utilizzare questo per inizializzare suo stato basato su una funzione deterministica (stessi valori per seme → stesso stato). Questo dovrebbe essere fatto con una funzione di hash, anche se ci sono numeri magici nel codice sorgente e non è chiaro il motivo per cui stanno facendo quello che stanno facendo.

Se si desidera eseguire un'operazione ripetibile e semplice, utilizzare un singolo numero intero.

Se si desidera fare qualcosa di ripetibile ma improbabile che una terza parte indovini, utilizzare una tupla o un elenco o una matrice numpy contenente una sequenza di numeri interi a 32 bit. Ad esempio, è possibile utilizzare numpy.random con un seme di None per generare un gruppo di numeri interi a 32 bit (ad esempio, 32 di essi, che genererebbero un totale di 1024 bit) dall'RNG del SO, memorizzare in alcuni seed S che si salva in qualche luogo segreto, quindi usa quel seme per generare qualsiasi sequenza R di numeri pseudocasuali che desideri. Quindi è possibile ricreare successivamente tale sequenza ri-seminare con S di nuovo, e finché si mantiene il valore di S segreto (così come i numeri generati R), nessuno sarebbe in grado di riprodurre tale sequenza R. Se solo usa un solo numero intero, ci sono solo 4 miliardi di possibilità e qualcuno potrebbe potenzialmente provarle tutte.Potrebbe essere un po 'paranoico, ma potresti farlo.


Longer rispondere

Il modulo numpy.random utilizza l'Mersenne Twister algoritmo, che è possibile confermare se stessi in uno dei due modi:

  • sia guardando la documentazione per numpy.random.RandomState, di cui numpy.random utilizza un'istanza per le funzioni numpy.random.* (ma è anche possibile utilizzare un'istanza indipendente isolata di)

  • Guardando il source code in mtrand.pyx che utilizza qualcosa chiamato Pyrex per avvolgere un'implementazione C rapida e randomkit.c e initarray.c.

In ogni caso ecco cosa dice la documentazione numpy.random.RandomState su seed():

Compatibilità garanzia Un seme fissa e una serie fissa di chiamate a RandomState metodi utilizzando gli stessi parametri produrrà sempre lo stesso risultati fino all'errore di arrotondamento tranne quando i valori non erano corretti. I valori errati verranno corretti e la versione NumPy in cui è stata effettuata la correzione verrà annotata nella relativa docstring. L'estensione degli intervalli di parametri esistenti e l'aggiunta di nuovi parametri è consentita finché il comportamento precedente rimane invariato.

Parametri:
semi
: {None, int, array_like}, opzionale

seme utilizzato per inizializzare il generatore di numeri pseudo-casuali. Può essere un numero intero compreso tra 0 e 2 ** 32 - 1 compreso, una matrice (o altra sequenza) di tali numeri interi o None (impostazione predefinita). Se seed è None, allora RandomState proverà a leggere i dati da /dev/urandom (o l'analogo di Windows), se disponibile, o seminare l'orologio altrimenti.

Non dice come viene utilizzato il seme, ma se si scava nel codice sorgente si riferisce alla funzione init_by_array: (docstring eliso)

def seed(self, seed=None): 
    cdef rk_error errcode 
    cdef ndarray obj "arrayObject_obj" 
    try: 
     if seed is None: 
      with self.lock: 
       errcode = rk_randomseed(self.internal_state) 
     else: 
      idx = operator.index(seed) 
      if idx > int(2**32 - 1) or idx < 0: 
       raise ValueError("Seed must be between 0 and 2**32 - 1") 
      with self.lock: 
       rk_seed(idx, self.internal_state) 
    except TypeError: 
     obj = np.asarray(seed).astype(np.int64, casting='safe') 
     if ((obj > int(2**32 - 1)) | (obj < 0)).any(): 
      raise ValueError("Seed must be between 0 and 2**32 - 1") 
     obj = obj.astype('L', casting='unsafe') 
     with self.lock: 
      init_by_array(self.internal_state, <unsigned long *>PyArray_DATA(obj), 
       PyArray_DIM(obj, 0)) 

ed ecco cosa gli sguardi funzione init_by_array come:

extern void 
init_by_array(rk_state *self, unsigned long init_key[], npy_intp key_length) 
{ 
    /* was signed in the original code. RDH 12/16/2002 */ 
    npy_intp i = 1; 
    npy_intp j = 0; 
    unsigned long *mt = self->key; 
    npy_intp k; 

    init_genrand(self, 19650218UL); 
    k = (RK_STATE_LEN > key_length ? RK_STATE_LEN : key_length); 
    for (; k; k--) { 
     /* non linear */ 
     mt[i] = (mt[i]^((mt[i - 1]^(mt[i - 1] >> 30)) * 1664525UL)) 
      + init_key[j] + j; 
     /* for > 32 bit machines */ 
     mt[i] &= 0xffffffffUL; 
     i++; 
     j++; 
     if (i >= RK_STATE_LEN) { 
      mt[0] = mt[RK_STATE_LEN - 1]; 
      i = 1; 
     } 
     if (j >= key_length) { 
      j = 0; 
     } 
    } 
    for (k = RK_STATE_LEN - 1; k; k--) { 
     mt[i] = (mt[i]^((mt[i-1]^(mt[i-1] >> 30)) * 1566083941UL)) 
      - i; /* non linear */ 
     mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ 
     i++; 
     if (i >= RK_STATE_LEN) { 
      mt[0] = mt[RK_STATE_LEN - 1]; 
      i = 1; 
     } 
    } 

    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
    self->gauss = 0; 
    self->has_gauss = 0; 
    self->has_binomial = 0; 
} 

Questo essenzialmente "munges" il numero casuale stato in un non lineare, metodo hash simile utilizzando ciascun valore all'interno della sequenza disponibile di valori iniziali.

3

Ciò che viene normalmente chiamato sequenza di numeri casuali in realtà è una sequenza di numeri "pseudo-casuali" poiché i valori sono calcolati utilizzando un algoritmo deterministico e la probabilità non ha alcun ruolo reale.

Il "seme" è un punto di partenza per la sequenza e la garanzia è che se si inizia dallo stesso seme si otterrà la stessa sequenza di numeri.Questo è molto utile ad esempio per il debug (quando si cerca un errore in un programma è necessario essere in grado di riprodurre il problema e studiarlo, un programma non deterministico sarebbe molto più difficile eseguire il debug perché ogni corsa sarebbe diversa) .

Problemi correlati