Melhor maneira de propagar N geradores de números aleatórios independentes de 1 valor

10

No meu programa, eu preciso executar N threads separados, cada um com seu próprio RNG, que é usado para provar um grande conjunto de dados. Eu preciso ser capaz de propagar todo esse processo com um único valor para poder reproduzir resultados.

É suficiente simplesmente aumentar sequencialmente a semente para cada índice?

Atualmente eu uso numpyo RandomStateque usa um gerador de números pseudo-aleatórios Mersenne Twister.

Trecho de código abaixo:

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

Basicamente, começo com uma semente inserida pelo usuário (se existir) e, para cada instância / thread, adiciono sequencialmente o índice (0 a N-1) da instância em execução. Não sei se isso é uma boa prática ou se existe uma maneira melhor de fazer isso.

EricR
fonte
11
Você sabe com antecedência quantos valores pseudo-aleatórios cada segmento usará - ou pelo menos você pode obter uma boa estimativa do limite superior?
whuber
Não, eu não posso. Ele mostra regiões que são somadas até que seja um limite. Os tamanhos das regiões podem variar significativamente.
EricR 02/09

Respostas:

9

Não é uma boa prática, certamente. Por exemplo, considere o que acontece quando você executa duas execuções com sementes de raiz 12345 e 12346. Cada execução terá N-1fluxos em comum.

As implementações do Mersenne Twister (incluindo numpy.randome random) geralmente usam um PRNG diferente para expandir a semente inteira no vetor de estado grande (624 inteiros de 32 bits) que o MT usa; essa é a matriz de RandomState.get_state(). Uma boa maneira de fazer o que você quer é executar esse PRNG, semeado com o número inteiro de entrada uma vez e obter N*624números inteiros de 32 bits. Divida esse fluxo em Nvetores de estado e use RandomState.set_state()para inicializar explicitamente cada RandomStateinstância. Pode ser necessário consultar as fontes C numpy.randomou _randomda biblioteca padrão para obter o PRNG (elas são iguais). Não tenho certeza se alguém implementou uma versão autônoma desse PRNG para Python.

Robert Kern
fonte
Acho que essa pode ser a melhor solução que ouvi até agora. Eu não acho que isso importe muito em como eu divido o fluxo, apesar de correto? Parece muito mais improvável ter uma sequência duplicada em números inteiros de 624 de 32 bits entre instâncias, independentemente de como elas são selecionadas no PRNG e na semente inicial.
EricR 02/09
11
Na verdade, eu vou voltar um pouco. Não está claro para mim que o inicializador PRNG foi projetado para ter arbitrariamente muitos valores extraídos dele. Considere usar outro PRNG de qualidade (de preferência não relacionado ao MT) para gerar o fluxo de estado. Pode-se implementar um HMAC-DRBG (um PRNG usando um HMAC como primitivo criptográfico) usando apenas a biblioteca padrão de maneira relativamente direta. A segurança criptográfica não é uma preocupação; apenas a facilidade de implementação e a qualidade do fluxo de bits. Você precisará garantir que nenhum vetor totalmente zero seja criado, muito raramente.
Robert Kern
Ou apenas use uma das RandomStateimplementações mais recentes no desenvolvimento que usa um algoritmo que possui fluxos configuráveis. Ou seja, você inicializa cada RandomStateinstância com a mesma semente e IDs de fluxo diferentes (apenas incrementado é bom) e tem fluxos independentes garantidos. pypi.python.org/pypi/randomstate
Robert Kern
4

Φ(você)vocêN

  1. Φ(você),ΦN(você),Φ2N(você),...
  2. Φ2(você),Φ1 1+N(você),Φ1 1+2N(você),...
  3. ...
  4. ΦN-1 1(você),ΦN-1 1+N(você),ΦN-1 1+2N(você),...

Φn(você)=Φ(Φn-1 1(você))

Xi'an
fonte
2

Agora existe um pacote Python chamado RandomGen que possui métodos para conseguir isso.

Ele suporta fluxos independentes criados a partir de uma única semente, bem como um protocolo de salto para geradores de números aleatórios mais antigos, como o MT19937.

Praveen
fonte
0

Algumas pessoas afirmam que existem correlações nos números aleatórios gerados por sementes seqüenciais. /programming/10900852/near-seeds-in-random-number-generation-may-give-similar-random-numbers Não sei ao certo se isso é verdade.

Se você está preocupado com isso, por que não usar um único gerador de números aleatórios para escolher as sementes para todos os outros geradores?

Aaron
fonte
Simplesmente porque eu não quero ter nenhuma chance de gerar aleatoriamente a mesma semente para mais de um gerador. É claro que eu poderia fazer algum trabalho de programação para impedir que isso acontecesse, mas não sei como isso seria melhor do que colher sementes sequencialmente em primeiro lugar.
EricR
11
Aparentemente , são possíveis correlações com sementes seqüenciais ... No entanto, como mostra o artigo vinculado nessa resposta do blog de John D Cook, usar um RNG para gerar sementes para outros geradores é muito pior, porque você encontra o problema do aniversário! Ele diz que gerar 1000 sementes não assinadas de 16 bits aleatoriamente tem 99,95% de chance de se sobrepor!
Praveen