Cree constantemente la misma matriz numérica aleatoria

89

Estoy esperando que otro desarrollador termine un fragmento de código que devolverá una matriz np de forma (100,2000) con valores de -1,0 o 1.

Mientras tanto, quiero crear aleatoriamente una matriz de las mismas características para poder comenzar con mi desarrollo y pruebas. El caso es que quiero que esta matriz creada aleatoriamente sea la misma cada vez, de modo que no esté probando contra una matriz que sigue cambiando su valor cada vez que vuelvo a ejecutar mi proceso.

Puedo crear mi matriz de esta manera, pero ¿hay alguna manera de crearla para que sea la misma cada vez? Puedo encurtir el objeto y despegarlo, pero me pregunto si hay otra forma.

r = np.random.randint(3, size=(100, 2000)) - 1
Idr
fuente

Respuestas:

84

Simplemente siembre el generador de números aleatorios con un valor fijo, p. Ej.

numpy.random.seed(42)

De esta forma, siempre obtendrás la misma secuencia de números aleatorios.

Sven Marnach
fuente
43
Alguien se coló en la numpy.random.seed()función cuando no estaba prestando atención. :-) Lo dejé intencionalmente fuera del módulo original. Recomiendo que las personas utilicen sus propias instancias RandomStatey pasen esos objetos.
Robert Kern
6
Robert es uno de los principales contribuyentes de numpy. Creo que deberíamos darle algo de peso a su opinión.
obsoleto
10
@deprecated: Estoy agradecido por el trabajo de Robert, pero su trabajo no reemplaza la justificación de la recomendación. Además, si numpy.random.seed()se desaconseja el uso de , esto debe mencionarse en la documentación . Aparentemente, otros colaboradores de NumPy no comparten la opinión de Robert. Sin ofender en absoluto, solo tengo curiosidad.
Sven Marnach
13
Esto es lo mismo que usar random.seedversus usar un random.Randomobjeto en la biblioteca estándar de Python. Si usa random.seedo numpy.random.seed, está sembrando todas las instancias aleatorias, tanto en su código como en cualquier código al que esté llamando o en cualquier código que se ejecute en la misma sesión que la suya. Si esas cosas dependen de que sean realmente aleatorias, entonces empiezas a tener problemas. Si implementa código que establece la semilla aleatoria, puede introducir una vulnerabilidad de seguridad.
asmeurer
3
@asmeurer Cualquiera que utilice un generador de números pseudoaleatorios por motivos de seguridad probablemente no sepa lo que está haciendo.
JAB
191

Crea tu propia instancia de numpy.random.RandomState()con tu semilla elegida. No lo utilice numpy.random.seed()excepto para trabajar con bibliotecas inflexibles que no le permiten pasar su propia RandomStateinstancia.

[~]
|1> from numpy.random import RandomState

[~]
|2> prng = RandomState(1234567890)

[~]
|3> prng.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])

[~]
|4> prng2 = RandomState(1234567890)

[~]
|5> prng2.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])
Robert Kern
fuente
7
¿Tiene alguna razón para su recomendación? ¿Qué pasa con numpy.random.seed()? Sé que no es seguro para subprocesos, pero es realmente conveniente si no necesita seguridad para subprocesos.
Sven Marnach
52
Es principalmente para formar buenos hábitos. Es posible que no necesite transmisiones independientes ahora, pero Sven-6-months-from-now might. Si escribe sus bibliotecas para usar los métodos directamente desde numpy.random, no podrá crear flujos independientes más adelante. También es más fácil escribir bibliotecas con la intención de controlar los flujos de PRNG. Siempre hay varias formas de ingresar a su biblioteca, y cada una de ellas debe tener una forma de controlar la semilla. Pasar objetos PRNG es una forma más limpia de hacerlo que confiar numpy.random.seed(). Desafortunadamente, este cuadro de comentarios es demasiado corto para contener más ejemplos. :-)
Robert Kern
25
Otra forma de describir el fundamento de Robert: usar numpy.random.seed usa una variable global para mantener el estado PRNG, y aquí se aplican las mismas razones estándar por las que las variables globales son malas.
Robie Basak
9
Si quieres que los PRNG sean independientes, no los siembres con nada. Úselo numpy.random.RandomState()sin argumentos. Esto sembrará el estado con valores únicos extraídos de las instalaciones de su sistema operativo para tales cosas ( /dev/urandomen máquinas UNIX y el equivalente de Windows allí). Si numpy.random.RandomState(1234567890)no le funciona, muestre exactamente lo que escribió y exactamente el mensaje de error que recibió.
Robert Kern
5
No es Buena idea. Úselo numpy.random.RandomState()sin argumentos para obtener los mejores resultados.
Robert Kern
3

Si está utilizando otras funciones que dependen de un estado aleatorio, no puede simplemente establecer una semilla general, sino que debe crear una función para generar su lista aleatoria de números y establecer la semilla como un parámetro de la función. Esto no molestará a ningún otro generador aleatorio en el código:

# Random states
def get_states(random_state, low, high, size):
    rs = np.random.RandomState(random_state)
    states = rs.randint(low=low, high=high, size=size)
    return states

# Call function
states = get_states(random_state=42, low=2, high=28347, size=25)
mari756h
fuente
3

Es importante comprender cuál es la semilla de un generador aleatorio y cuándo / cómo se establece en su código (consulte, por ejemplo, aquí para obtener una buena explicación del significado matemático de la semilla).

Para eso necesitas establecer la semilla haciendo:

random_state = np.random.RandomState(seed=your_favorite_seed_value)

Entonces es importante generar los números aleatorios de random_state y no de np.random. Es decir, deberías hacer:

random_state.randint(...)

en vez de

np.random.randint(...) 

que creará una nueva instancia de RandomState () y básicamente usará el reloj interno de su computadora para establecer la semilla.

t_sic
fuente
2

Solo quiero aclarar algo con respecto a la respuesta de @Robert Kern en caso de que no esté claro. Incluso si usa el RandomState, tendría que inicializarlo cada vez que llame a un método aleatorio numpy como en el ejemplo de Robert, de lo contrario obtendrá los siguientes resultados.

Python 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 19:07:31) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> prng = np.random.RandomState(2019)
>>> prng.randint(-1, 2, size=10)
array([-1,  1,  0, -1,  1,  1, -1,  0, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([-1, -1, -1,  0, -1, -1,  1,  0, -1, -1])
>>> prng.randint(-1, 2, size=10)
array([ 0, -1, -1,  0,  1,  1, -1,  1, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([ 1,  1,  0,  0,  0, -1,  1,  1,  0, -1])
Kirk Walla
fuente