O que faz numpy.random.seed (0)?


282

O que np.random.seedfaz no código abaixo de um tutorial do Scikit-Learn? Eu não estou muito familiarizado com o gerador de estado aleatório do NumPy, então eu realmente aprecio a explicação dos termos de um leigo.

np.random.seed(0)
indices = np.random.permutation(len(iris_X))

Respostas:


557

np.random.seed(0) torna previsíveis os números aleatórios

>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])
>>> numpy.random.seed(0) ; numpy.random.rand(4)
array([ 0.55,  0.72,  0.6 ,  0.54])

Com a redefinição inicial (sempre), o mesmo conjunto de números será exibido sempre.

Se a semente aleatória não for redefinida, números diferentes aparecerão a cada chamada:

>>> numpy.random.rand(4)
array([ 0.42,  0.65,  0.44,  0.89])
>>> numpy.random.rand(4)
array([ 0.96,  0.38,  0.79,  0.53])

(pseudo-) números aleatórios funcionam iniciando com um número (a semente), multiplicando-o por um número grande, adicionando um deslocamento e, em seguida, obtendo o módulo dessa soma. O número resultante é então usado como a semente para gerar o próximo número "aleatório". Quando você define a semente (sempre), faz o mesmo sempre, fornecendo os mesmos números.

Se você quiser números aparentemente aleatórios, não defina a semente. Se você possui um código que usa números aleatórios que deseja depurar, no entanto, pode ser muito útil definir a semente antes de cada execução, para que o código faça a mesma coisa toda vez que você o executar.

Para obter os números mais aleatórios para cada execução, ligue numpy.random.seed(). Isso fará com que numpy defina a semente como um número aleatório obtido de /dev/urandomou seu analógico do Windows ou, se nenhum deles estiver disponível, ele usará o relógio.

Para obter mais informações sobre o uso de sementes para gerar números pseudo-aleatórios, consulte a Wikipedia .


86
Esta resposta deve ser adicionada à documentação do numpy. Obrigado.
gorjanz

8
Além disso, quando você liga numpy.random.seed(None), "ele tenta ler os dados de / dev / urandom (ou o análogo do Windows), se disponível, ou propagar o relógio de outra forma".
9137 Jonathan

1
@ Jonathan Excelente ponto sobre numpy.random.seed(None). Atualizei a resposta com essas informações e um link para os documentos.
precisa saber é o seguinte

@ curio1729 A implementação pode variar de um sistema operativo para o seguinte, mas numpy tenta tornar os seus comandos, incluindo seed, compatíveis.
precisa saber é o seguinte

1
@ L3viathan Bom ponto! Para ser mais completo e preciso, eu deveria ter mencionado que um deslocamento é adicionado. Resposta atualizada. Para aqueles que querem mais detalhes, também adicionei um link para a discussão da wikipedia sobre geradores de números pseudo-aleatórios.
John1024 25/01

38

Se você definir np.random.seed(a_fixed_number)toda vez que chamar a outra função aleatória do numpy, o resultado será o mesmo:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10) 
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10) 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]
>>> np.random.seed(0) 
>>> print np.random.rand(4) 
[0.5488135  0.71518937 0.60276338 0.54488318]

No entanto, se você chamar apenas uma vez e usar várias funções aleatórias, os resultados ainda serão diferentes:

>>> import numpy as np
>>> np.random.seed(0) 
>>> perm = np.random.permutation(10)
>>> print perm 
[2 8 4 9 1 6 7 3 0 5]
>>> np.random.seed(0) 
>>> print np.random.permutation(10)
[2 8 4 9 1 6 7 3 0 5]
>>> print np.random.permutation(10) 
[3 5 1 2 9 8 0 6 7 4]
>>> print np.random.permutation(10) 
[2 3 8 4 5 1 0 6 9 7]
>>> print np.random.rand(4) 
[0.64817187 0.36824154 0.95715516 0.14035078]
>>> print np.random.rand(4) 
[0.87008726 0.47360805 0.80091075 0.52047748]

3
Existe uma função que pode ser chamada assim que a semente aleatória é definida para todas as np.randomchamadas subseqüentes até que a semente seja alterada? Ter que chamá-lo toda vez parece desnecessariamente detalhado e fácil de esquecer.
Lubed Up Slug

@LubedUpSlug, você pode decorá-los - pelo menos em alguns casos simples que testei, deve funcionar. def seed_first(fun, seed=0):| \tdef wrapped(*args, **kwargs):| \t\tnp.random.seed(seed)| \t\treturn fun(*args, **kwargs)| \treturn wrappede depois for m in np.random.__all__:| \tif m != 'seed':| \t\tsetattr(np.random, m, seed_first(getattr(np.random, m)))No entanto, isso pode levar a erros muito sutis e comportamento estranho a longo prazo. (Substitua \ t por quatro espaços e | por quebras de linha ...) #
Sebastian Höffner

1
@ SebastianHöffner obrigado pelo seu comentário. Minha pergunta foi um pouco equivocada, porque fiquei confusa com a frase "No entanto, se você chamar apenas uma vez e usar várias funções aleatórias, os resultados ainda serão diferentes:" Ligar np.random.seed()uma vez no início de um programa sempre produzirá o mesmo resultado para a mesma semente, uma vez que as chamadas subseqüentes às np.randomfunções mudarão deterministicamente a semente para as chamadas subseqüentes. Ligar np.random.seed()antes de cada chamada para np.randomfunções provavelmente produzirá resultados indesejados.
precisa

17

Como observado, numpy.random.seed (0) define a semente aleatória como 0, de modo que os números pseudo-aleatórios obtidos aleatoriamente começarão do mesmo ponto. Isso pode ser bom para depuração em alguns casos. NO ENTANTO, após algumas leituras, este parece ser o caminho errado, se você tiver threads porque não é seguro para threads.

das diferenças entre numpy-random-random-random-random-in-python :

Para numpy.random.seed (), a principal dificuldade é que não é seguro para threads - ou seja, não é seguro usá-lo se você tiver muitos threads de execução diferentes, porque não é garantido que funcione se dois threads diferentes estiverem sendo executados a função ao mesmo tempo. Se você não estiver usando threads e se puder razoavelmente esperar que não precisará reescrever seu programa dessa maneira no futuro, numpy.random.seed () deve ser bom para fins de teste. Se houver algum motivo para suspeitar que você possa precisar de threads no futuro, é muito mais seguro, a longo prazo, fazer o que é sugerido e criar uma instância local da classe numpy.random.Random. Até onde eu sei, random.random.seed () é seguro para threads (ou pelo menos, não encontrei nenhuma evidência em contrário).

exemplo de como fazer isso:

from numpy.random import RandomState
prng = RandomState()
print prng.permutation(10)
prng = RandomState()
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)
prng = RandomState(42)
print prng.permutation(10)

pode dar:

[3 0 4 6 8 2 1 9 7 5]

[1 6 9 0 2 7 8 3 5 4]

[8 1 5 0 7 2 9 4 3 6]

[8 1 5 0 7 2 9 4 3 6]

Por fim, observe que pode haver casos em que a inicialização para 0 (em oposição a uma semente que não possui todos os bits 0) pode resultar em distribuições não uniformes para algumas poucas primeiras iterações devido à maneira como o xor funciona, mas isso depende do algoritmo , e está além das minhas preocupações atuais e do escopo desta pergunta.


12

Eu tenho usado isso com muita frequência em redes neurais. É sabido que, quando começamos a treinar uma rede neural, inicializamos aleatoriamente os pesos. O modelo é treinado nesses pesos em um conjunto de dados específico. Após o número de épocas, você recebe um conjunto de pesos treinado.

Agora, suponha que você queira treinar novamente do zero ou passar o modelo para outras pessoas para reproduzir seus resultados, os pesos serão novamente inicializados com números aleatórios que geralmente serão diferentes dos anteriores. Os pesos treinados obtidos após o mesmo número de épocas (mantendo os mesmos dados e outros parâmetros) que os anteriores diferem. O problema é que seu modelo não é mais reproduzível, ou seja, toda vez que você o treina do zero, ele fornece diferentes conjuntos de pesos. Isso ocorre porque o modelo está sendo inicializado por diferentes números aleatórios todas as vezes.

E se, toda vez que você começar a treinar do zero, o modelo for inicializado com o mesmo conjunto de pesos aleatórios de inicialização? Nesse caso, seu modelo pode se tornar reproduzível. Isso é alcançado por numpy.random.seed (0). Ao mencionar seed () em um número específico, você sempre mantém o mesmo conjunto de números aleatórios.


3

Imagine que você está mostrando a alguém como codificar algo com vários números "aleatórios". Usando semente numpy, eles podem usar o mesmo número de semente e obter o mesmo conjunto de números "aleatórios".

Portanto, não é exatamente aleatório porque um algoritmo cospe os números, mas parece um monte gerado aleatoriamente.


0

Uma semente aleatória especifica o ponto inicial quando um computador gera uma sequência numérica aleatória.

Por exemplo, digamos que você queira gerar um número aleatório no Excel (Nota: o Excel define um limite de 9999 para a semente). Se você digitar um número na caixa Semente aleatória durante o processo, poderá usar o mesmo conjunto de números aleatórios novamente. Se você digitou "77" na caixa e digitou "77" na próxima vez em que executar o gerador de números aleatórios, o Excel exibirá o mesmo conjunto de números aleatórios. Se você digitar "99", obterá um conjunto de números totalmente diferente. Mas se você voltar a uma semente de 77, obterá o mesmo conjunto de números aleatórios com os quais começou.

Por exemplo, "pegue um número x, adicione 900 + x e subtraia 52". Para que o processo inicie, é necessário especificar um número inicial, x (a semente). Vamos pegar o número inicial 77:

Adicione 900 + 77 = 977 Subtraia 52 = 925 Seguindo o mesmo algoritmo, o segundo número "aleatório" seria:

900 + 925 = 1825 Subtrair 52 = 1773 Este exemplo simples segue um padrão, mas os algoritmos por trás da geração de números de computador são muito mais complicados


0

Todos os números aleatórios gerados após a configuração de um valor inicial específico são iguais em todas as plataformas / sistemas.



0
numpy.random.seed(0)
numpy.random.randint(10, size=5)

Isso produz a seguinte saída: array([5, 0, 3, 3, 7]) Novamente, se executarmos o mesmo código, obteremos o mesmo resultado.

Agora, se mudarmos o valor inicial de 0 para 1 ou outros:

numpy.random.seed(1)
numpy.random.randint(10, size=5)

Isso produz a seguinte saída: array([5 8 9 5 0])mas agora a saída não é a mesma como acima.


0

Todas as respostas acima mostram a implementação de np.random.seed() código. Vou tentar o meu melhor para explicar brevemente por que isso realmente acontece. Computadores são máquinas projetadas com base em algoritmos predefinidos. Qualquer saída de um computador é o resultado do algoritmo implementado na entrada. Portanto, quando solicitamos que um computador gere números aleatórios, verifique se eles são aleatórios, mas o computador não os apresentou apenas aleatoriamente!

Então, quando escrevemos, np.random.seed(any_number_here)o algoritmo produzirá um conjunto específico de números que é exclusivo para o argumento any_number_here. É quase como um determinado conjunto de números aleatórios pode ser obtido se passarmos o argumento correto. Mas isso exigirá que saibamos como o algoritmo funciona, o que é bastante tedioso.

Assim, por exemplo, se eu escrever np.random.seed(10)o conjunto específico de números que obtiver, permanecerá o mesmo, mesmo que eu execute a mesma linha após 10 anos, a menos que o algoritmo seja alterado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.