Cosa fa numpy.random.seed (0)?


282

Cosa fa np.random.seednel codice seguente di un tutorial di Scikit-Learn? Non ho molta familiarità con le cose del generatore di stato casuale di NumPy, quindi apprezzerei molto la spiegazione dei termini di un profano.

np.random.seed(0)
indices = np.random.permutation(len(iris_X))

Risposte:


559

np.random.seed(0) rende prevedibili i numeri casuali

>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])
>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])

Con il seed reset (ogni volta), lo stesso set di numeri apparirà ogni volta.

Se il seed casuale non viene resettato, ad ogni invocazione compaiono numeri diversi :

>>> numpy.random.rand(4)
array([ 0.42,  0.65,  0.44,  0.89])
>>> numpy.random.rand(4)
array([ 0.96,  0.38,  0.79,  0.53])

I numeri (pseudo-) casuali funzionano iniziando con un numero (il seme), moltiplicandolo per un numero elevato, aggiungendo un offset, quindi prendendo il modulo di quella somma. Il numero risultante viene quindi utilizzato come seme per generare il successivo numero "casuale". Quando imposti il ​​seme (ogni volta), fa sempre la stessa cosa, dandoti gli stessi numeri.

Se vuoi numeri apparentemente casuali, non impostare il seme. Se si dispone di codice che utilizza numeri casuali che si desidera eseguire il debug, tuttavia, può essere molto utile impostare il seed prima di ogni esecuzione in modo che il codice faccia la stessa cosa ogni volta che lo si esegue.

Per ottenere i numeri più casuali per ogni corsa, chiama numpy.random.seed(). Questo farà sì che numpy imposti il ​​seed su un numero casuale ottenuto da /dev/urandomo dal suo analogo di Windows o, se nessuno di questi è disponibile, utilizzerà l'orologio.

Per ulteriori informazioni sull'uso dei semi per generare numeri pseudo-casuali, consultare Wikipedia .


86
Questa risposta dovrebbe essere aggiunta alla documentazione di numpy. Grazie.
Gorjanz,

8
Inoltre, quando chiami numpy.random.seed(None), "proverà a leggere i dati da / dev / urandom (o l'analogo di Windows) se disponibile o esegui il seed dall'orologio altrimenti".
Jonathan,

1
@Jonathan Ottimo punto in merito numpy.random.seed(None). Ho aggiornato la risposta con quelle informazioni e un link ai documenti.
Giovanni 1024,

@ curio1729 L'implementazione può variare da un sistema operativo all'altro ma numpy tenta di rendere i suoi comandi, incluso seed, compatibili.
Giovanni 1024,

1
@ L3viathan Ottimo punto! Per essere più completo e preciso, avrei dovuto menzionare che è stato aggiunto un offset. Risposta aggiornata. Per coloro che desiderano maggiori dettagli, ho anche aggiunto un link alla discussione di Wikipedia sui generatori di numeri pseudo-casuali.
Giovanni 1024

38

Se si imposta np.random.seed(a_fixed_number)ogni volta che si chiama l'altra funzione casuale del numpy, il risultato sarà lo stesso:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10) 
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]

Tuttavia, se lo chiami una volta sola e usi varie funzioni casuali, i risultati saranno comunque diversi:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10)
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> print np.random.permutation(10) 
[3 5 1 2 9 8 0 6 7 4]
>>> print np.random.permutation(10) 
[2 3 8 4 5 1 0 6 9 7]
>>> print np.random.rand(4) 
[0.64817187 0.36824154 0.95715516 0.14035078]
>>> print np.random.rand(4) 
[0.87008726 0.47360805 0.80091075 0.52047748]

3
Esiste una funzione che può essere chiamata una volta in modo tale che il seed casuale sia impostato per tutte le np.randomchiamate successive fino a quando il seed non viene modificato? Doverlo chiamare ogni volta sembra inutilmente prolisso e facile da dimenticare.
Lubed Up Slug

@LubedUpSlug puoi decorarli - almeno per alcuni semplici casi che ho testato dovrebbe funzionare. def seed_first(fun, seed=0):| \tdef wrapped(*args, **kwargs):| \t\tnp.random.seed(seed)| \t\treturn fun(*args, **kwargs)| \treturn wrappede quindi for m in np.random.__all__:| \tif m != 'seed':| \t\tsetattr(np.random, m, seed_first(getattr(np.random, m)))Tuttavia, questo potrebbe portare a bug molto sottili e comportamenti strani a lungo termine. (Sostituisci \ t con quattro spazi e | con interruzioni di riga ...)
Sebastian Höffner,

1
@ SebastianHöffner grazie per il tuo commento. La mia domanda era un po 'sbagliata perché ero confuso dalla frase "Tuttavia, se la chiami una volta sola e usi varie funzioni casuali, i risultati saranno comunque diversi:" Chiamare np.random.seed()una volta all'inizio di un programma produrrà sempre lo stesso risultato per lo stesso seed poiché le successive chiamate alle np.randomfunzioni cambieranno in modo deterministico il seed per le chiamate successive. Chiamare np.random.seed()prima di ogni chiamata a np.randomfunzioni probabilmente produrrà risultati indesiderati.
Lubed Up Slug,

17

Come notato, numpy.random.seed (0) imposta il seme casuale su 0, quindi i numeri pseudo casuali che ottieni da casuale inizieranno dallo stesso punto. Questo può essere utile per il debug in alcuni casi. TUTTAVIA, dopo alcune letture, questo sembra essere il modo sbagliato di farlo, se hai thread perché non è thread-safe.

dalle differenze tra numpy-random-e-random-random-in-python :

Per numpy.random.seed (), la difficoltà principale è che non è thread-safe - ovvero, non è sicuro da usare se si hanno molti thread di esecuzione diversi, perché non è garantito che funzioni se due thread diversi sono in esecuzione la funzione allo stesso tempo. Se non stai usando i thread e se puoi ragionevolmente aspettarti di non dover riscrivere il tuo programma in questo modo in futuro, numpy.random.seed () dovrebbe andare bene a scopo di test. Se c'è qualche motivo per sospettare che potresti aver bisogno di thread in futuro, è molto più sicuro nel lungo periodo fare come suggerito e creare un'istanza locale della classe numpy.random.Random. Per quanto ne so, random.random.seed () è thread-safe (o almeno non ho trovato prove del contrario).

esempio di come procedere:

from numpy.random import RandomState
prng = RandomState()
print prng.permutation(10)
prng = RandomState()
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)

può dare:

[3 0 4 6 8 2 1 9 7 5]

[1 6 9 0 2 7 8 3 5 4]

[8 1 5 0 7 2 9 4 3 6]

[8 1 5 0 7 2 9 4 3 6]

Infine, si noti che potrebbero esserci casi in cui l'inizializzazione su 0 (al contrario di un seme che non ha tutti i bit 0) può portare a distribuzioni non uniformi per alcune prime iterazioni a causa del modo in cui xor funziona, ma questo dipende dall'algoritmo e va oltre le mie attuali preoccupazioni e lo scopo di questa domanda.


12

L'ho usato molto spesso nelle reti neurali. È noto che quando iniziamo ad allenare una rete neurale inizializziamo casualmente i pesi. Il modello viene addestrato su questi pesi in un determinato set di dati. Dopo il numero di epoche vieni addestrato insieme di pesi.

Ora supponiamo che tu voglia allenarti di nuovo da zero o vuoi passare il modello ad altri per riprodurre i tuoi risultati, i pesi saranno nuovamente inizializzati su numeri casuali che per lo più saranno diversi da quelli precedenti. I pesi ottenuti ottenuti dopo lo stesso numero di epoche (mantenendo gli stessi dati e altri parametri) di quelli precedenti differiranno. Il problema è che il tuo modello non è più riproducibile, cioè ogni volta che lo alleni da zero ti fornisce diversi pesi. Questo perché il modello viene inizializzato da diversi numeri casuali ogni volta.

Cosa succede se ogni volta che si inizia l'allenamento da zero il modello viene inizializzato sullo stesso set di pesi di inizializzazione casuali? In questo caso il tuo modello potrebbe diventare riproducibile. Ciò è ottenuto da numpy.random.seed (0). Citando seed () su un determinato numero, ti stai sempre aggrappando allo stesso set di numeri casuali.


3

Immagina di mostrare a qualcuno come codificare qualcosa con un mucchio di numeri "casuali". Usando il seme numpy possono usare lo stesso numero di seme e ottenere lo stesso insieme di numeri "casuali".

Quindi non è esattamente casuale perché un algoritmo sputa i numeri ma sembra un gruppo generato casualmente.


0

Un seme casuale specifica il punto iniziale quando un computer genera una sequenza numerica casuale.

Ad esempio, supponiamo che tu voglia generare un numero casuale in Excel (Nota: Excel imposta un limite di 9999 per il seme). Se inserisci un numero nella casella Sementi casuali durante il processo, sarai in grado di utilizzare di nuovo lo stesso set di numeri casuali. Se hai digitato "77" nella casella e hai digitato "77" alla successiva esecuzione del generatore di numeri casuali, Excel visualizzerà lo stesso set di numeri casuali. Se digiti "99", otterrai un set di numeri completamente diverso. Ma se torni a un seme di 77, otterrai lo stesso set di numeri casuali con cui hai iniziato.

Ad esempio, "prendi un numero x, aggiungi 900 + x, quindi sottrai 52". Per avviare il processo, è necessario specificare un numero iniziale, x (il seme). Prendiamo il numero di partenza 77:

Aggiungi 900 + 77 = 977 Sottrai 52 = 925 Seguendo lo stesso algoritmo, il secondo numero "casuale" sarebbe:

900 + 925 = 1825 Sottrai 52 = 1773 Questo semplice esempio segue uno schema, ma gli algoritmi alla base della generazione del numero di computer sono molto più complicati


0

Tutti i numeri casuali generati dopo aver impostato un particolare valore seed sono uguali su tutte le piattaforme / sistemi.



0
numpy.random.seed(0)
numpy.random.randint(10, size=5)

Questo produce il seguente output: array([5, 0, 3, 3, 7]) Ancora una volta, se eseguiamo lo stesso codice otterremo lo stesso risultato.

Ora se cambiamo il valore del seme da 0 a 1 o altri:

numpy.random.seed(1)
numpy.random.randint(10, size=5)

Questo produce il seguente output: array([5 8 9 5 0])ma ora l'output non è lo stesso di sopra.


0

Tutte le risposte sopra mostrano l'implementazione di np.random.seed()in code. Farò del mio meglio per spiegare brevemente perché effettivamente accade. I computer sono macchine progettate sulla base di algoritmi predefiniti. Qualsiasi output da un computer è il risultato dell'algoritmo implementato sull'input. Quindi, quando chiediamo a un computer di generare numeri casuali, siamo sicuri che siano casuali ma il computer non li ha inventati casualmente!

Quindi quando scriviamo np.random.seed(any_number_here)l'algoritmo produrrà un particolare set di numeri che è unico per l'argomento any_number_here. È quasi come ottenere un determinato insieme di numeri casuali se passiamo l'argomento corretto. Ma questo ci richiederà di sapere come funziona l'algoritmo che è abbastanza noioso.

Quindi, per esempio, se scrivo np.random.seed(10)il particolare insieme di numeri che ottengo rimarrà lo stesso anche se eseguo la stessa riga dopo 10 anni, a meno che l'algoritmo non cambi.

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.