¿Qué hace numpy.random.seed (0)?


282

¿Qué hace np.random.seeden el siguiente código de un tutorial de Scikit-Learn? No estoy muy familiarizado con el generador de estado aleatorio de NumPy, por lo que realmente agradecería la explicación de esto por parte de un laico.

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

Respuestas:


559

np.random.seed(0) hace que los números aleatorios sean predecibles

>>> 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 el reinicio inicial (cada vez), aparecerá el mismo conjunto de números cada vez.

Si la semilla aleatoria no se restablece, aparecen diferentes números con cada invocación:

>>> 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])

Los números (pseudo-) aleatorios funcionan comenzando con un número (la semilla), multiplicándolo por un número grande, agregando un desplazamiento y luego tomando el módulo de esa suma. El número resultante se utiliza como semilla para generar el siguiente número "aleatorio". Cuando establece la semilla (cada vez), hace lo mismo cada vez, dándole los mismos números.

Si desea números aparentemente aleatorios, no establezca la semilla. Sin embargo, si tiene un código que utiliza números aleatorios que desea depurar, puede ser muy útil establecer la semilla antes de cada ejecución para que el código haga lo mismo cada vez que lo ejecute.

Para obtener los números más aleatorios para cada ejecución, llame al numpy.random.seed(). Esto hará que numpy establezca la semilla en un número aleatorio obtenido de /dev/urandomsu análogo de Windows o, si ninguno de los dos está disponible, usará el reloj.

Para obtener más información sobre el uso de semillas para generar números pseudoaleatorios, consulte wikipedia .


86
Esta respuesta debe agregarse a la documentación de numpy. Gracias.
gorjanz

8
Además, cuando llame numpy.random.seed(None), "intentará leer los datos de / dev / urandom (o el análogo de Windows) si está disponible o, si no, desde el reloj".
Jonathan

1
@ Jonathan Excelente punto sobre numpy.random.seed(None). Actualicé la respuesta con esa información y un enlace a los documentos.
John1024

@ curio1729 La implementación puede variar de un sistema operativo al siguiente, pero numpy intenta hacer que sus comandos, incluso seed, sean compatibles.
John1024

1
@ L3viathan Buen punto! Para ser más completo y preciso, debería haber mencionado que se agrega un desplazamiento. Respuesta actualizada Para aquellos que desean más detalles, también agregué un enlace a la discusión de wikipedia sobre generadores de números pseudoaleatorios.
John1024

38

Si configura np.random.seed(a_fixed_number)cada vez que llama a la otra función aleatoria de numpy, el resultado será el mismo:

>>> 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]

Sin embargo, si solo lo llama una vez y usa varias funciones aleatorias, los resultados seguirán siendo diferentes:

>>> 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
¿Existe una función que se pueda invocar una vez de modo que se establezca la inicialización aleatoria para todas las np.randomllamadas posteriores hasta que se modifique la inicialización? Tener que llamarlo cada vez parece innecesariamente detallado y fácil de olvidar.
Lubed Up Slug

@LubedUpSlug puedes decorarlos, al menos para algunos casos simples que probé debería funcionar. def seed_first(fun, seed=0):El | \tdef wrapped(*args, **kwargs):El | \t\tnp.random.seed(seed)El | \t\treturn fun(*args, **kwargs)El | \treturn wrappedy luego for m in np.random.__all__:| \tif m != 'seed':El | \t\tsetattr(np.random, m, seed_first(getattr(np.random, m)))Sin embargo, esto podría conducir a errores muy sutiles y comportamientos extraños a largo plazo. (Reemplace \ t con cuatro espacios y | con saltos de línea ...)
Sebastian Höffner el

1
@ SebastianHöffner gracias por tu comentario. Mi pregunta fue un poco equivocada porque estaba confundido por la oración "Sin embargo, si solo lo llama una vez y usa varias funciones aleatorias, los resultados seguirán siendo diferentes:" Llamar np.random.seed()una vez al comienzo de un programa siempre producirá el mismo resultado para la misma semilla ya que las llamadas posteriores a np.randomfunciones cambiarán determinísticamente la semilla para las llamadas posteriores. Llamar np.random.seed()antes de cada llamada a np.randomfunciones probablemente producirá resultados no deseados.
Lubed Up Slug

17

Como se señaló, numpy.random.seed (0) establece la semilla aleatoria en 0, por lo que los números pseudoaleatorios que obtienes de random comenzarán desde el mismo punto. Esto puede ser bueno para la depuración en algunos casos. SIN EMBARGO, después de leer un poco, esta parece ser la manera incorrecta de hacerlo, si tiene hilos porque no es seguro.

de las diferencias entre numpy-random-y-random-random-in-python :

Para numpy.random.seed (), la principal dificultad es que no es seguro para subprocesos, es decir, no es seguro de usar si tiene muchos subprocesos diferentes de ejecución, porque no se garantiza que funcione si se ejecutan dos subprocesos diferentes La función al mismo tiempo. Si no está utilizando subprocesos, y si puede esperar razonablemente que no necesitará volver a escribir su programa de esta manera en el futuro, numpy.random.seed () debería estar bien para fines de prueba. 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 hacer una instancia local de la clase numpy.random.Random. Por lo que puedo decir, random.random.seed () es seguro para subprocesos (o al menos, no he encontrado ninguna evidencia de lo contrario).

ejemplo de cómo hacer esto:

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)

puede dar:

[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]

Por último, tenga en cuenta que puede haber casos en los que la inicialización a 0 (a diferencia de una semilla que no tiene todos los bits 0) puede dar lugar a distribuciones no uniformes para algunas primeras iteraciones debido a la forma en que funciona xor, pero esto depende del algoritmo , y está más allá de mis preocupaciones actuales y del alcance de esta pregunta.


12

Lo he usado muy a menudo en redes neuronales. Es bien sabido que cuando comenzamos a entrenar una red neuronal, inicializamos aleatoriamente los pesos. El modelo está entrenado en estos pesos en un conjunto de datos en particular. Después de varias épocas, se entrena un conjunto de pesas.

Ahora suponga que desea entrenar nuevamente desde cero o desea pasar el modelo a otros para reproducir sus resultados, los pesos se inicializarán nuevamente a números aleatorios que en su mayoría serán diferentes de los anteriores. Los pesos entrenados obtenidos después del mismo número de épocas (manteniendo los mismos datos y otros parámetros) como antes serán diferentes. El problema es que su modelo ya no es reproducible, es decir, cada vez que entrena su modelo desde cero, le proporciona diferentes conjuntos de pesas. Esto se debe a que el modelo se inicializa con diferentes números aleatorios cada vez.

¿Qué sucede si cada vez que comienza a entrenar desde cero, el modelo se inicializa con el mismo conjunto de pesos de inicialización aleatoria? En este caso, su modelo podría volverse reproducible. Esto se logra mediante numpy.random.seed (0). Al mencionar seed () a un número en particular, siempre se aferra al mismo conjunto de números aleatorios.


3

Imagine que le está mostrando a alguien cómo codificar algo con un montón de números "aleatorios". Al usar semilla numpy, pueden usar el mismo número de semilla y obtener el mismo conjunto de números "aleatorios".

Entonces, no es exactamente aleatorio porque un algoritmo escupe los números pero parece un grupo generado aleatoriamente.


0

Una semilla aleatoria especifica el punto de inicio cuando una computadora genera una secuencia de números aleatorios.

Por ejemplo, supongamos que desea generar un número aleatorio en Excel (Nota: Excel establece un límite de 9999 para la semilla). Si ingresa un número en el cuadro Semilla aleatoria durante el proceso, podrá volver a utilizar el mismo conjunto de números aleatorios. Si escribió "77" en el cuadro y escribió "77" la próxima vez que ejecute el generador de números aleatorios, Excel mostrará el mismo conjunto de números aleatorios. Si escribe "99", obtendrá un conjunto de números completamente diferente. Pero si regresa a una semilla de 77, obtendrá el mismo conjunto de números aleatorios con los que comenzó.

Por ejemplo, "tome un número x, agregue 900 + x, luego reste 52". Para que comience el proceso, debe especificar un número inicial, x (la semilla). Tomemos el número inicial 77:

Sumar 900 + 77 = 977 Restar 52 = 925 Siguiendo el mismo algoritmo, el segundo número "aleatorio" sería:

900 + 925 = 1825 Restar 52 = 1773 Este ejemplo simple sigue un patrón, pero los algoritmos detrás de la generación de números de computadora son mucho más complicados


0

Todos los números aleatorios generados después de establecer un valor semilla particular son los mismos en todas las plataformas / sistemas.



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

Esto produce el siguiente resultado: array([5, 0, 3, 3, 7]) De nuevo, si ejecutamos el mismo código obtendremos el mismo resultado.

Ahora, si cambiamos el valor semilla de 0 a 1 u otros:

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

Esto produce el siguiente resultado: array([5 8 9 5 0])pero ahora el resultado no es el mismo que el anterior.


0

Todas las respuestas anteriores muestran la implementación de np.random.seed()en el código. Haré todo lo posible para explicar brevemente por qué sucede realmente. Las computadoras son máquinas que están diseñadas en base a algoritmos predefinidos. Cualquier salida de una computadora es el resultado del algoritmo implementado en la entrada. Entonces, cuando solicitamos que una computadora genere números aleatorios, ¡seguro que son aleatorios, pero la computadora no solo los obtuvo al azar!

Entonces, cuando escribimos, np.random.seed(any_number_here)el algoritmo generará un conjunto particular de números que es único para el argumento any_number_here. Es casi como si se pudiera obtener un conjunto particular de números aleatorios si pasamos el argumento correcto. Pero esto requerirá que sepamos cómo funciona el algoritmo, lo cual es bastante tedioso.

Entonces, por ejemplo, si escribo np.random.seed(10)el conjunto particular de números que obtengo seguirá siendo el mismo, incluso si ejecuto la misma línea después de 10 años, a menos que el algoritmo cambie.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.