ordenar - numeros aleatorios enteros python
¿Cómo puedo recuperar la semilla actual del generador de números aleatorios de NumPy? (3)
Lo siguiente importa NumPy y establece la semilla.
import numpy as np
np.random.seed(42)
Sin embargo, no estoy interesado en establecer la semilla, sino más en leerla. random.get_state()
no parece contener la semilla. La documentation no muestra una respuesta obvia.
¿Cómo recupero la semilla actual utilizada por numpy.random
, suponiendo que no la configuré manualmente?
Quiero usar la semilla actual para llevarla a la siguiente iteración de un proceso.
Comprueba el primer elemento de la matriz devuelta por np.random.get_state()
, me parece exactamente la semilla aleatoria.
La respuesta corta es que simplemente no se puede (al menos no en general).
El Mersenne Twister RNG utilizado por numpy tiene 2 19937 -1 posibles estados internos, mientras que un único entero de 64 bits tiene solo 2 64 valores posibles. Por lo tanto, es imposible asignar cada estado RNG a una semilla entera única.
Puede obtener y establecer el estado interno del RNG directamente usando np.random.get_state
y np.random.set_state
. La salida de get_state
es una tupla cuyo segundo elemento es una matriz (624,)
de enteros de 32 bits. Esta matriz tiene bits más que suficientes para representar todos los estados internos posibles del RNG (2 624 * 32 > 2 19937 -1).
La tupla devuelta por get_state
se puede utilizar como una semilla para crear secuencias reproducibles de números aleatorios. Por ejemplo:
import numpy as np
# randomly initialize the RNG from some platform-dependent source of entropy
np.random.seed(None)
# get the initial state of the RNG
st0 = np.random.get_state()
# draw some random numbers
print(np.random.randint(0, 100, 10))
# [ 8 76 76 33 77 26 3 1 68 21]
# set the state back to what it was originally
np.random.set_state(st0)
# draw again
print(np.random.randint(0, 100, 10))
# [ 8 76 76 33 77 26 3 1 68 21]
He editado esta respuesta en gran medida después de encontrar algunos más detalles sobre el problema en cuestión. Tal como está ahora, espero que sirva como una aclaración a la respuesta de ali_m, y como una importante corrección a la respuesta de Dong Justin.
Estos son mis hallazgos:
- Después de establecer la semilla aleatoria usando
np.random.seed(X)
, puede encontrarla de nuevo usandonp.random.get_state()[1][0]
. - Sin embargo, será de poca utilidad para usted.
El resultado de las siguientes secciones de código le mostrará por qué ambas declaraciones son correctas.
Declaración 1: puede encontrar la semilla aleatoria usando np.random.get_state()[1][0]
.
Si configura la semilla aleatoria usando np.random.seed(123)
, puede recuperar el estado aleatorio como una tupla usando state = np.random.get_state()
. A continuación se muestra una mirada más de cerca al state
(estoy usando el Explorador de variables en Spyder). Estoy usando una captura de pantalla ya que el uso de print(state)
inundará su consola debido al tamaño de la matriz en el segundo elemento de la tupla.
Puede ver fácilmente 123
como el primer número en la matriz contenida en el segundo elemento. Y usar seed = np.random.get_state()[1][0]
te dará 123
. ¿Perfecto? No del todo, porque:
Declaración 2: Sin embargo, será de poca utilidad para usted:
Sin embargo, puede parecerlo al principio, porque podría usar np.random.seed(123)
, recuperar el mismo número con seed = np.random.get_state()[1][0]
, restablecer la semilla con np.random.seed(444)
, y luego (aparentemente) lo volvió al escenario 123 con np.random.seed(seed)
. Pero entonces ya sabrá cuál era su semilla al azar antes, por lo que no tendría que hacerlo de esa manera. La próxima sección del código también mostrará que no puede tomar el primer número de ningún estado aleatorio usando np.random.get_state()[1][0]
y espera recrear ese escenario exacto. Tenga en cuenta que lo más probable es que np.random.seed(None)
cerrar y reiniciar por completo su kernel (o llamar a np.random.seed(None)
) para poder ver esto.
El siguiente fragmento utiliza np.random.randint()
para generar 5 enteros aleatorios entre -10 y 10, así como para almacenar información sobre el proceso:
Fragmento 1
# 1. Imports
import pandas as pd
import numpy as np
# 2. set random seed
#seedSet = None
seedSet = 123
np.random.seed(seedSet)
# 3. describe random state
state = np.random.get_state()
state5 = np.random.get_state()[1][:5]
seedState = np.random.get_state()[1][0]
# 4. generate random numbers
random = np.random.randint(-10, 10, size = 5)
# 5. organize and present findings
df = pd.DataFrame.from_dict({''seedSet'':seedSet, ''seedState'':seedState, ''state'':state, ''random'':random})
print(df)
Observe que la columna llamada seedState
es igual que el primer número en state
. Pude haberlo impreso como un número independiente, pero quería mantener todo en el mismo lugar. También note que, seedSet = 123
, y np.random.seed(seedSet)
hasta ahora han sido comentados. Y debido a que no se ha establecido una semilla aleatoria, sus números serán diferentes a los míos. Pero eso no es lo importante aquí, sino la consistencia interna de tus resultados:
Salida 1:
random seedSet seedState state
0 2 None 1558056443 1558056443
1 -1 None 1558056443 1808451632
2 4 None 1558056443 730968006
3 -4 None 1558056443 3568749506
4 -6 None 1558056443 3809593045
En este caso particular, seed = np.random.get_state()[1][0]
es igual a 1558056443
. Y siguiendo la lógica de la respuesta de Dong Justins (así como mi propia respuesta antes de esta edición), puede establecer el valor aleatorio con np.random.seed(1558056443)
y obtener el mismo estado aleatorio. El siguiente fragmento mostrará que no puedes :
Fragmento 2
# 1. Imports
import pandas as pd
import numpy as np
# 2. set random seed
#seedSet = None
seedSet = 1558056443
np.random.seed(seedSet)
# 3. describe random state
#state = np.random.get_state()
state = np.random.get_state()[1][:5]
seedState = np.random.get_state()[1][0]
# 4. generate random numbers
random = np.random.randint(-10, 10, size = 5)
# 5. organize and present findings
df = pd.DataFrame.from_dict({''seedSet'':seedSet, ''seedState'':seedState, ''state'':state, ''random'':random})
print(df)
Salida 2:
random seedSet seedState state
0 8 1558056443 1558056443 1558056443
1 3 1558056443 1558056443 1391218083
2 7 1558056443 1558056443 2754892524
3 -8 1558056443 1558056443 1971852777
4 4 1558056443 1558056443 2881604748
¿Ver la diferencia? np.random.get_state()[1][0]
es idéntico para la Salida 1 y la Salida 2, pero el resto de la salida no es (lo más importante es que los números aleatorios no son los mismos). Entonces, como ya he dicho ali_m claramente:
Por lo tanto, es imposible asignar cada estado RNG a una semilla entera única.