14 votos

La mejor manera de sembrar N generadores de números aleatorios independientes a partir de 1 valor

En mi programa necesito ejecutar N hilos separados, cada uno con su propio RNG, que se utiliza para muestrear un gran conjunto de datos. Necesito poder sembrar todo este proceso con un único valor para poder reproducir los resultados.

¿Es suficiente con aumentar secuencialmente la semilla de cada índice?

Actualmente utilizo numpy 's RandomState que utiliza un generador de números pseudoaleatorios Mersenne Twister.

Fragmento de código a continuación:

# If a random number generator seed exists
if self.random_generator_seed:
    # Create a new random number generator for this instance based on its
    # own index
    self.random_generator_seed += instance_index
    self.random_number_generator = RandomState(self.random_generator_seed)

Esencialmente comienzo con una semilla introducida por el usuario (si existe) y para cada instancia / hilo añado secuencialmente el índice (0 a N-1) de la instancia que se está ejecutando. No sé si esto es una buena práctica o si hay una mejor manera de hacer esto.

1 votos

¿Sabes de antemano cuántos valores pseudoaleatorios utilizará cada hilo, o al menos puedes obtener una buena estimación del límite superior?

0 votos

No, no puedo. Muestrea regiones que se suman hasta que un umbral es él. El tamaño de las regiones puede variar considerablemente.

11voto

poo Puntos 1

No es una gran práctica, ciertamente. Por ejemplo, considere lo que sucede cuando hace dos ejecuciones con semillas raíz de 12345 y 12346. Cada ejecución tendrá N-1 corrientes en común.

Implementaciones de Mersenne Twister (incluyendo numpy.random y random ) suelen utilizar un PRNG diferente para expandir la semilla entera en el gran vector de estados (624 enteros de 32 bits) que utiliza MT; se trata de la matriz de RandomState.get_state() . Una buena manera de hacer lo que quieres es ejecutar ese PRNG, sembrado con tu entero de entrada una vez, y obtener N*624 enteros de 32 bits de la misma. Dividir ese flujo en N vectores de estado y utilizar RandomState.set_state() para inicializar explícitamente cada RandomState instancia. Es posible que tenga que consultar las fuentes C de numpy.random o _random de la biblioteca estándar para obtener ese PRNG (son lo mismo). No estoy seguro de si alguien ha implementado una versión independiente de ese PRNG para Python.

0 votos

Creo que esta puede ser la mejor solución que he escuchado hasta ahora. Sin embargo, no creo que importe mucho cómo dividir el flujo, ¿correcto? Parece mucho más improbable tener una secuencia duplicada en 624 enteros de 32 bits entre instancias sin importar cómo se elijan del PRNG inicial y la semilla.

1 votos

En realidad, voy a retroceder un poco. No me queda claro que el inicializador PRNG esté diseñado para que se extraigan de él tantos valores arbitrariamente. Considera usar otro PRNG de calidad (preferiblemente no relacionado con MT) para generar el flujo de estado. Se puede implementar un HMAC-DRBG (un PRNG que utiliza un HMAC como primitiva criptográfica) utilizando sólo la biblioteca estándar de forma relativamente sencilla. La seguridad criptográfica no es una preocupación; sólo la facilidad de implementación y la calidad del flujo de bits. Tendrás que asegurarte de que no se hagan vectores totalmente nulos, en el caso muy raro de que se produzca.

0 votos

O simplemente utilice uno de los nuevos RandomState implementaciones en desarrollo que utilizan un algoritmo que tiene flujos ajustables. Es decir, se inicializa cada RandomState con la misma semilla y diferentes IDs de flujo (simplemente incrementados está bien), y se garantizan flujos independientes. pypi.python.org/pypi/randomstate

4voto

Lev Puntos 2212

Una solución que se utiliza en procesamiento en paralelo es utilizar su generador aleatorio Φ(u)Φ(u) , donde uu es tu semilla, por NN -Los lotes:

  1. generar Φ(u),ΦN(u),Φ2N(u),...Φ(u),ΦN(u),Φ2N(u),...
  2. generar Φ2(u),Φ1+N(u),Φ1+2N(u),...Φ2(u),Φ1+N(u),Φ1+2N(u),...
  3. ...
  4. generar ΦN1(u),ΦN1+N(u),ΦN1+2N(u),...ΦN1(u),ΦN1+N(u),ΦN1+2N(u),...

donde Φn(u)=Φ(Φn1(u))Φn(u)=Φ(Φn1(u)) . De este modo, se utiliza una única semilla y las secuencias son todas uniformes e independientes.

2voto

Rav Puntos 306

Ahora existe un paquete de Python llamado RandomGen que tiene métodos para lograrlo.

Es soporta flujos independientes creados a partir de una única semilla, así como un protocolo de salto para generadores de números aleatorios más antiguos, como el MT19937.

0voto

user2514608 Puntos 11

Algunas personas afirman que existen correlaciones en los números aleatorios generados por las semillas secuenciales. https://stackoverflow.com/questions/10900852/near-seeds-in-random-number-generation-may-give-similar-random-numbers No estoy seguro de que eso sea cierto.

Si te preocupa, ¿por qué no utilizar un único generador de números aleatorios para elegir las semillas de todos los demás generadores?

0 votos

Simplemente porque no quiero tener ninguna posibilidad de generar aleatoriamente la misma semilla para más de 1 generador. Por supuesto que podría hacer algún trabajo de programación para evitar que esto suceda, pero entonces no sé cómo eso sería mejor que elegir las semillas secuencialmente en primer lugar.

1 votos

Al parecer, ...las correlaciones son posibles con las semillas secuenciales... Sin embargo, como el artículo ¡enlazado en esa respuesta del blog de John D Cook muestra, el uso de un RNG para generar semillas para otros generadores es mucho peor, porque te encuentras con el problema del cumpleaños! Dice que generar 1000 semillas de 16 bits sin signo de forma aleatoria tiene un 99,95% de posibilidades de solapamiento.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X