Differenze tra numpy.random e random.random in Python


100

Ho un grande script in Python. Mi sono ispirato al codice di altre persone, quindi ho finito per utilizzare il numpy.randommodulo per alcune cose (ad esempio per creare un array di numeri casuali presi da una distribuzione binomiale) e in altri luoghi utilizzo il modulo random.random.

Qualcuno può dirmi le principali differenze tra i due? Guardando la pagina web del documento per ciascuno dei due, mi sembra che numpy.randomabbia solo più metodi, ma non sono chiaro in che modo la generazione dei numeri casuali sia diversa.

Il motivo per cui lo chiedo è perché devo eseguire il seeding del mio programma principale a scopo di debug. Ma non funziona a meno che non utilizzo lo stesso generatore di numeri casuali in tutti i moduli che sto importando, è corretto?

Inoltre, ho letto qui, in un altro post, una discussione sul NON utilizzo numpy.random.seed(), ma non ho davvero capito perché fosse una cattiva idea. Apprezzerei davvero se qualcuno mi spiegasse perché è così.

Risposte:


120

Hai già fatto molte osservazioni corrette!

A meno che non desideri eseguire il seeding di entrambi i generatori casuali, probabilmente è più semplice a lungo termine scegliere un generatore o l'altro. Ma se devi usarli entrambi, allora sì, dovrai anche iniziarli entrambi, perché generano numeri casuali indipendentemente l'uno dall'altro.

Infatti 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 eseguono la funzione contemporaneamente. Se non stai usando thread e se puoi ragionevolmente aspettarti che non avrai bisogno di riscrivere il tuo programma in questo modo in futuro, numpy.random.seed()dovrebbe andare bene. Se c'è qualche motivo per sospettare che tu possa aver bisogno di thread in futuro, è molto più sicuro a lungo termine fare come suggerito e creare un'istanza locale della numpy.random.Randomclasse . Per quanto ne so, random.random.seed()è thread-safe (o almeno, non ho trovato alcuna prova del contrario).

La numpy.randomlibreria contiene alcune distribuzioni di probabilità extra comunemente utilizzate nella ricerca scientifica, oltre a un paio di funzioni utili per la generazione di array di dati casuali. La random.randomlibreria è un po 'più leggera e dovrebbe andare bene se non stai facendo ricerca scientifica o altri tipi di lavoro in statistica.

Altrimenti, entrambi usano la sequenza del tornado di Mersenne per generare i loro numeri casuali, e sono entrambi completamente deterministici - cioè, se conosci alcune informazioni chiave, è possibile prevedere con assoluta certezza quale numero verrà dopo . Per questo motivo, né numpy.random né random.random è adatto per usi crittografici seri . Ma poiché la sequenza è molto molto lunga, entrambi vanno bene per generare numeri casuali nei casi in cui non sei preoccupato per le persone che cercano di decodificare i tuoi dati. Questa è anche la ragione per la necessità di inizializzare il valore casuale: se inizi nello stesso punto ogni volta, otterrai sempre la stessa sequenza di numeri casuali!

Come nota a margine, se non necessario livello di crittografia casualità, è necessario utilizzare il segreto del modulo, o qualcosa di simile Crypto.Random se si sta utilizzando una versione di Python prima di Python 3.6.


14
Come nota lontanamente correlata, a volte è necessario non usare nessuno dei due , poiché il tornado di Mersenne non produce sequenze casuali di entropia sufficienti per scopi crittografici (e alcuni insoliti scientifici). In questi rari casi, è spesso necessario Crypto.Random , che è in grado di utilizzare sorgenti di entropia specifiche del sistema operativo per generare sequenze casuali non deterministiche di qualità molto superiore a quella disponibile da random.randomsolo. Di solito non ne hai bisogno, però.
SingleNegationElimination

Grazie Hannnele. I tuoi approfondimenti sono stati davvero molto utili! Risulta che non posso farla franca usando SOLO un singolo generatore di numeri casuali, (che deve essere numpy poiché random non produce distribuzioni binomiali) perché parti del mio programma chiamano un altro programma che utilizza random. Dovrò seminare i due generatori.
Laura

2
"se sai quale numero hai adesso, è possibile prevedere con assoluta certezza quale numero verrà dopo". Penso che questa affermazione potrebbe richiedere alcuni chiarimenti. Ciò che significa è che se conosci lo stato interno del generatore puoi riprodurre la sequenza, che è ciò che fai quando semini il generatore. Dato un singolo numero in uscita dal generatore non è possibile prevedere il numero successivo. Il periodo è così grande che probabilmente avresti bisogno di una lunga sequenza di numeri prima di poter calcolare dove ti trovi sulla sequenza pseudo-casuale e quindi prevedere quella successiva.
Kaushik Ghose

12

Da Python per l'analisi dei dati , il modulo numpy.randomintegra Python randomcon funzioni per generare in modo efficiente interi array di valori campione da molti tipi di distribuzioni di probabilità.

Al contrario, il randommodulo integrato di Python campiona solo un valore alla volta, mentre numpy.randompuò generare campioni molto grandi più velocemente. Usando la funzione magica di IPython %timeitsi può vedere quale modulo funziona più velocemente:

In [1]: from random import normalvariate
In [2]: N = 1000000

In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
1 loop, best of 3: 963 ms per loop

In [4]: %timeit np.random.normal(size=N)
10 loops, best of 3: 38.5 ms per loop

1
Non è il caso di altri metodi. rispetto np.random.randint(2)a random.randrange(2)e NumPy era più lento . NumPy: 1.25 us e Random: 891 ns. E anche la stessa relazione per np.random.rand()e random.random().
Shayan Amani,

3

La fonte del seme e il profilo di distribuzione utilizzato influenzeranno gli output: se stai cercando casualità crittografica, il seeding da os.urandom () otterrà byte casuali quasi reali dal chatter del dispositivo (cioè ethernet o disco) (cioè / dev / random su BSD)

questo ti eviterà di dare un seme e quindi di generare numeri casuali deterministici. Tuttavia, le chiamate casuali ti consentono di adattare i numeri a una distribuzione (ciò che io chiamo casualità scientifica - alla fine tutto ciò che vuoi è una distribuzione a campana di numeri casuali, numpy è il migliore per fornire questo.

Quindi sì, resta con un generatore, ma decidi cosa casuale vuoi: casuale, ma sicuramente da una curva di distrubtuion, o casuale come puoi ottenere senza un dispositivo quantistico.


Grazie mille Paolo, la tua risposta è stata davvero utile! Non cerco casualità crittografica, sto realizzando modelli matematici e mi bastano numeri pseudo-casuali. Si scopre che non posso attenermi a un generatore come volevo poiché ho bisogno di numpy per la distribuzione binomiale e il mio programma chiama un altro programma che usa casuale :(
Laura
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.