Diferencias entre numpy.random y random.random en Python

100

Tengo un gran script en Python. Me inspiré en el código de otras personas, así que terminé usando el numpy.randommódulo 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.

¿Alguien puede 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.randomsolo tiene más métodos, pero no tengo claro en qué se diferencia la generación de los números aleatorios.

La razón por la que pregunto es porque necesito sembrar mi programa principal con fines de 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í por qué esto era una mala idea. Realmente agradecería que alguien me explicara por qué es así.

Laura
fuente

Respuestas:

120

¡Ya ha hecho muchas observaciones correctas!

A menos que desee sembrar ambos generadores aleatorios, probablemente sea más sencillo a largo plazo elegir un generador u otro. Pero si necesita usar ambos, entonces sí, también necesitará sembrarlos a ambos, porque generan números aleatorios de forma independiente entre sí.

Porque numpy.random.seed(), la principal dificultad es que no es seguro para subprocesos, es decir, no es seguro de usar si tiene muchos subprocesos de ejecución diferentes , porque no se garantiza que funcione si dos subprocesos diferentes están ejecutando la función al mismo tiempo. Si no está usando subprocesos, y si puede esperar razonablemente que no necesitará reescribir 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 subprocesos en el futuro, es mucho más seguro a largo plazo hacer lo sugerido y crear una instancia local de la numpy.random.Randomclase . Por lo que puedo decir, random.random.seed()es seguro para subprocesos (o al menos, no he encontrado ninguna evidencia de lo contrario).

La numpy.randombiblioteca contiene algunas distribuciones de probabilidad adicionales comúnmente utilizadas en la investigación científica, así como un par de funciones de conveniencia para generar matrices de datos aleatorios. La random.randombiblioteca 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 la secuencia del tornado de Mersenne para generar sus números aleatorios, y ambos son completamente deterministas; es decir, si conoce algunos bits clave de información, es posible predecir con absoluta certeza qué número vendrá después . Por esta razón, ni numpy.random ni random.random son adecuados para usos criptográficos serios . Pero debido a que la secuencia es muy larga, ambos están bien para generar números aleatorios en los casos en los que no le preocupe que las personas intenten realizar ingeniería inversa en sus datos. Esta es también la razón de la necesidad de sembrar el valor aleatorio: si comienza en el mismo lugar cada vez, ¡siempre obtendrá la misma secuencia de números aleatorios!

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

Hannele
fuente
14
Como nota lejanamente relacionada, a veces es necesario no usar ninguno , ya que el tornado de Mersenne no produce secuencias aleatorias de entropía suficientes para propósitos criptográficos (y algunos científicos inusuales). En esos raros casos, a menudo necesita Crypto.Random , que puede utilizar fuentes de entropía específicas del sistema operativo para generar secuencias aleatorias no deterministas de una calidad mucho mayor que la que está disponible random.randomsolo. Sin embargo, normalmente no necesitas esto.
SingleNegationElimination
Gracias Hannnele. ¡Tus ideas fueron realmente muy útiles! Resulta que no puedo usar SOLO un único generador de números aleatorios, (que debe ser numeroso ya que el azar no produce distribuciones binomiales) porque partes de mi programa llaman a otro programa que usa aleatorio. Tendré que sembrar los dos generadores.
Laura
2
"si sabe qué número tiene ahora, es posible predecir con absoluta certeza qué número vendrá después". Creo que esta declaración podría necesitar alguna aclaración. Lo que significa es que si conoces el estado interno del generador, puedes reproducir la secuencia, que es lo que haces cuando siembras el generador. Dada la salida de un solo número del generador, no puede predecir el siguiente 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.
Kaushik Ghose
12

De Python para análisis de datos , el módulo numpy.randomcomplementa Python randomcon funciones para generar de manera eficiente matrices completas de valores de muestra a partir de muchos tipos de distribuciones de probabilidad.

Por el contrario, el randommódulo incorporado de Python solo muestrea un valor a la vez, mientras que numpy.randompuede generar muestras muy grandes más rápido. Usando la función mágica de IPython, %timeituno puede ver qué módulo funciona 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
lmiguelvargasf
fuente
1
No es el caso de otros métodos. en comparación np.random.randint(2)con random.randrange(2)y NumPy fue más lento . NumPy: 1,25 us y Random: 891 ns. Y también la misma relación para np.random.rand()y random.random().
Shayan Amani
3

La fuente de la semilla y el perfil de distribución utilizado afectarán las salidas; si está buscando aleatoriedad criptgráfica, la siembra desde os.urandom () obtendrá bytes aleatorios casi reales de la charla del dispositivo (es decir, ethernet o disco) (es decir, / dev / random en BSD)

esto evitará que usted dé una semilla y genere números aleatorios deterministas. Sin embargo, las llamadas aleatorias le permiten ajustar los números a una distribución (lo que yo llamo aleatoriedad científica; eventualmente, todo lo que desea es una distribución de curva de campana de números aleatorios, numpy es mejor para ejecutar esto.

Entonces, sí, quédese con un generador, pero decida qué aleatorio desea: aleatorio, pero definitivamente a partir de una curva de distribución, o tan aleatorio como pueda obtener sin un dispositivo cuántico.

usted cad señor - tome eso
fuente
¡Muchas gracias Paul, tu respuesta fue realmente útil! No estoy buscando aleatoriedad criptográfica, estoy haciendo modelos matemáticos y los números pseudoaleatorios son suficientes para mí. Resulta que no puedo ceñirme a un generador como quería, ya que necesito numpy para la distribución binomial y mi programa llama a otro programa que usa aleatorio :(
Laura