2011-08-11 21 views
62

Tengo un gran script en Python. Me inspiré en el código de otras personas, así que terminé usando el módulo numpy.random para algunas cosas (por ejemplo, para crear una matriz de números aleatorios tomados de una distribución binomial) y en otros lugares utilizo el módulo random.random.Diferencias entre numpy.random y random.random en Python

¿Puede alguien decirme las principales diferencias entre los dos? Al mirar la página web del documento para cada uno de los dos, me parece que numpy.random tiene más métodos, pero no tengo claro cómo la generación de los números aleatorios es diferente.

La razón por la que pregunto es porque necesito sembrar mi programa principal para depuración. Pero no funciona a menos que use el mismo generador de números aleatorios en todos los módulos que estoy importando, ¿es correcto?

Además, leí aquí, en otra publicación, una discusión sobre NO usar numpy.random.seed(), pero realmente no entendía por qué esta era una mala idea. Realmente apreciaría que alguien me explique por qué este es el caso.

Respuesta

75

¡Ya ha hecho muchas observaciones correctas!

A menos que desee sembrar los dos generadores aleatorios, es probable que a la larga sea más simple elegir un generador u otro.

Para numpy.random.seed(), la principal dificultad es que no es hilo de seguridad - es decir, no es seguro de usar si usted tiene many different threads of execution, porque no se garantiza que funcione si dos hilos diferentes están ejecutando la función a la vez . Si no está utilizando subprocesos, y si razonablemente puede esperar que no necesite volver a escribir su programa de esta manera en el futuro, numpy.random.seed() debería estar bien. Si hay alguna razón para sospechar que puede necesitar hilos en el futuro, a la larga es mucho más seguro hacer lo que se sugiere y al make a local instance of the numpy.random.Random class. Por lo que puedo decir, random.random.seed() es seguro para subprocesos (o al menos, no he encontrado ninguna evidencia de lo contrario).

La biblioteca numpy.random contiene algunas distribuciones de probabilidad más comúnmente utilizadas en la investigación científica, así como un par de funciones de conveniencia para generar matrices de datos aleatorios. La biblioteca random.random es un poco más liviana, y debería estar bien si no está haciendo investigación científica u otro tipo de trabajo en estadística.

De lo contrario, ambos usan el Mersenne twister sequence para generar sus números aleatorios, y ambos son completamente deterministas, es decir, si conoce algunas partes clave de información, es posible predecir con absoluta certeza what number will come next. Por esta razón, ninguno es adecuado para ningún serious cryptographic uses. Pero debido a que la secuencia es muy larga, ambas están bien para generar números aleatorios en los programas cotidianos. Esta es también la razón de la necesidad de sembrar el valor aleatorio: si comienzas en el mismo lugar cada vez, siempre obtendrás la misma secuencia de números aleatorios.

Como nota al margen, si haces necesitan aleatoriedad nivel de cifrado, se debe utilizar el módulo secrets, o algo así Crypto.Random si está utilizando una versión anterior de Python que Python 3.6.

+9

Como nota alejadas, a veces es NECESARIO utilizar * ni *, ya que el tornado Mersenne no produce secuencias aleatorias de entropía suficiente para criptográfica (y algunos propósitos científicos inusuales). En esos raros casos, a menudo necesita [Crypto.Random] (https://www.dlitz.net/software/pycrypto/apidoc/Crypto.Random.random-module.html), que puede usar fuentes de entropía específicas del sistema operativo. para generar secuencias aleatorias no deterministas de calidad mucho más alta que la disponible en 'random.random' solo. Sin embargo, usualmente no necesitas esto. – SingleNegationElimination

+0

Gracias Hannnele. ¡Tus ideas fueron realmente muy útiles! Resulta que no puedo salir usando SOLAMENTE un solo generador de números aleatorios, (que debe ser numpy ya que al azar no produce distribuciones binomiales) porque partes de mi programa llaman a otro programa que usa al azar. Tendré que sembrar los dos generadores. – Laura

+1

"si sabe qué número tiene ahora, es posible predecir con certeza absoluta qué número vendrá después". Creo que esta afirmación podría necesitar alguna aclaración. Lo que quiere decir es que si conoce el * estado interno * del generador, puede reproducir la secuencia, que es lo que hace cuando siembra el generador. Dado un solo número de salida del generador, no puede predecir el próximo número. El período es tan grande que probablemente necesitaría una secuencia larga de números antes de poder calcular dónde se encuentra en la secuencia pseudoaleatoria y así predecir la siguiente. –

3

La fuente de la semilla y el perfil de distribución utilizados afectarán a las salidas, si está buscando la aleatoriedad criptológica, la siembra desde el sistema operativo.urandom() obtendrá bytes aleatorios casi reales de la conversación del dispositivo (es decir, ethernet o disco) (es decir,/dev/random en BSD)

Esto evitará que proporcione una semilla y genere así números aleatorios deterministas. Sin embargo, las llamadas aleatorias le permiten ajustar los números a una distribución (lo que yo llamo azar científico). Eventualmente todo lo que desea es una distribución de números aleatorios, numpy es mejor para delivered.

SO yes, stick con un generador, pero decide lo aleatorio que usted quiere - al azar, pero defitniely partir de una curva distrubtuion, o tan al azar como usted puede conseguir sin un dispositivo cuántico

+0

Muchas gracias Paul, ¡tu respuesta fue realmente útil! No busco la aleatoriedad criptográfica, estoy haciendo modelos matemáticos y los números pseudoaleatorios son suficientes para mí. Resulta que no puedo mantener un generador como quería, ya que necesito un numpy para la distribución binomial y mi programa llama a otro programa que usa al azar :( – Laura

3

de Python for Data Analysis, el módulo numpy.random complementa el pitón random con funciones de manera eficiente. generando matrices enteras de valores de muestra de muchos tipos de distribuciones de probabilidad.

Por el contrario, el módulo integrado random de Python solo muestra un valor a la vez, mientras que numpy.random puede generar una muestra muy grande más rápido. Usando IPython función mágica %timeit uno puede ver qué módulo realiza más rápido:

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