Crie consistentemente a mesma matriz numpy aleatória

89

Estou esperando outro desenvolvedor terminar um trecho de código que retornará um array np de forma (100,2000) com valores de -1,0 ou 1.

Nesse ínterim, desejo criar aleatoriamente uma matriz com as mesmas características para poder começar meu desenvolvimento e teste. O fato é que eu quero que esse array criado aleatoriamente seja o mesmo todas as vezes, de modo que não teste em um array que fica mudando seu valor cada vez que executo novamente meu processo.

Posso criar meu array assim, mas há uma maneira de criá-lo de forma que seja sempre o mesmo. Posso conservar o objeto e retirá-lo, mas estou me perguntando se há outra maneira.

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

Respostas:

82

Simplesmente semeie o gerador de números aleatórios com um valor fixo, por exemplo

numpy.random.seed(42)

Dessa forma, você sempre obterá a mesma sequência de números aleatórios.

Sven Marnach
fonte
43
Alguém entrou sorrateiramente na numpy.random.seed()função quando eu não estava prestando atenção. :-) Eu intencionalmente deixei de fora do módulo original. Eu recomendo que as pessoas usem suas próprias instâncias RandomStatee passando esses objetos.
Robert Kern
6
Robert é um dos principais contribuintes do numpy. Acho que devemos dar algum peso à opinião dele.
obsoleto
10
@deprecated: sou grato pelo trabalho de Robert, mas seu trabalho não substitui a justificativa para a recomendação. Além disso, se o uso de numpy.random.seed()for desencorajado, isso deve ser mencionado na documentação . Aparentemente, outros colaboradores do NumPy não compartilham da opinião de Robert. Sem querer ofender, estou apenas curioso.
Sven Marnach
13
Isso é o mesmo que usar random.seedvs. usar um random.Randomobjeto na biblioteca padrão do Python. Se você usar random.seedou numpy.random.seed, estará semeando todas as instâncias aleatórias, tanto em seu código quanto em qualquer código que esteja chamando ou qualquer código que seja executado na mesma sessão que a sua. Se essas coisas dependem de serem realmente aleatórias, você começa a ter problemas. Se você implantar o código que define a semente aleatória, pode introduzir uma vulnerabilidade de segurança.
asmeurer
3
@asmeurer Qualquer pessoa que use um gerador de números pseudo-aleatórios para fins de segurança provavelmente não sabe o que está fazendo.
JAB
191

Crie sua própria instância de numpy.random.RandomState()com a semente escolhida. Não use numpy.random.seed()exceto para contornar bibliotecas inflexíveis que não permitem que você contorne sua própria RandomStateinstância.

[~]
|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
fonte
7
Você tem alguma justificativa para sua recomendação? O que há de errado numpy.random.seed()? Eu sei que não é thread-safe, mas é muito conveniente se você não precisa de thread-safe.
Sven Marnach
52
É principalmente para formar bons hábitos. Você pode não precisar de streams independentes agora, mas Sven-6-meses-a-partir de agora pode. Se você escrever suas bibliotecas para usar os métodos diretamente numpy.random, não poderá criar fluxos independentes posteriormente. Também é mais fácil escrever bibliotecas com a intenção de controlar streams PRNG. Sempre existem várias maneiras de entrar em sua biblioteca, e cada uma delas deve ter uma maneira de controlar a semente. Passar objetos PRNG é uma maneira mais limpa de fazer isso do que confiar numpy.random.seed(). Infelizmente, esta caixa de comentário é muito curta para conter mais exemplos. :-)
Robert Kern
25
Outra maneira de descrever a lógica de Robert: usar numpy.random.seed usa uma variável global para manter o estado PRNG, e os mesmos motivos padrão pelos quais as variáveis ​​globais são ruins se aplicam aqui.
Robie Basak
9
Se você deseja que os PRNGs sejam independentes, não os semeie com nada. Basta usar numpy.random.RandomState()sem argumentos. Isso irá propagar o estado com valores exclusivos extraídos dos recursos do seu sistema operacional para tais coisas ( /dev/urandomem máquinas UNIX e o equivalente do Windows lá). Se numpy.random.RandomState(1234567890)não estiver funcionando para você, mostre exatamente o que você digitou e exatamente a mensagem de erro que recebeu.
Robert Kern
5
Não é uma boa ideia. Use numpy.random.RandomState()sem argumentos para obter os melhores resultados.
Robert Kern
3

Se você estiver usando outras funções que dependem de um estado aleatório, você não pode apenas definir uma semente geral, mas deve criar uma função para gerar sua lista aleatória de número e definir a semente como um parâmetro da função. Isso não perturbará nenhum outro gerador aleatório no 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
fonte
3

É importante compreender o que é a semente de um gerador aleatório e quando / como está definido no seu código (verifique por exemplo aqui para uma boa explicação do significado matemático da semente).

Para isso, você precisa definir a semente fazendo:

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

Então, é importante gerar os números aleatórios de random_state e não de np.random. Ou seja, você deve fazer:

random_state.randint(...)

ao invés de

np.random.randint(...) 

que criará uma nova instância de RandomState () e basicamente usará o relógio interno do computador para definir a semente.

t_sic
fonte
2

Eu só quero esclarecer algo em relação à resposta de @Robert Kern, caso isso não esteja claro. Mesmo se você usar o, RandomStatevocê terá que inicializá-lo toda vez que chamar um método aleatório numpy, como no exemplo de Robert, caso contrário, você obterá os seguintes 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
fonte