Como amostrar de uma distribuição normal com média e variação conhecidas usando uma linguagem de programação convencional?

36

Eu nunca tive um curso de estatística, então espero estar perguntando no lugar certo aqui.

Suponha que eu tenha apenas dois dados descrevendo uma distribuição normal: a média e a variação . Eu quero usar um computador para amostrar aleatoriamente essa distribuição, de modo que eu respeite essas duas estatísticas.σ 2μσ2

É bastante óbvio que eu posso lidar com a média simplesmente normalizando em torno de 0: basta adicionar a cada amostra antes de gerar a amostra. Mas não vejo como gerar programaticamente amostras para respeitar .μσ2

Meu programa estará em uma linguagem de programação convencional; Não tenho acesso a nenhum pacote estatístico.

Fixee
fonte
Seu idioma possui gerador de números aleatórios? Este gerador é apenas de distribuição uniforme ou também pode ser gerado a partir de distribuição normal?
precisa saber é o seguinte
@ttnphns: Praticamente toda linguagem de computador vem com um gerador de números aleatórios. Eles são geradores extremamente uniformes em algum domínio finito.
Fixee

Respostas:

33

Se você pode amostrar de uma determinada distribuição com média 0 e variação 1, poderá facilmente amostrar a partir de uma transformação de escala-local dessa distribuição, que possui e variância . Se é uma amostra de uma distribuição média de 0 e variância 1, então é uma amostra com médiaμσ2x

σx+μ
e variância σ 2 . Portanto, tudo o que você precisa fazer é dimensionar a variável pelo desvio padrão σ (raiz quadrada da variância)antes deadicionar a média μ .μσ2σμ

Como você realmente obtém uma simulação de uma distribuição normal com média 0 e variação 1 é uma história diferente. É divertido e interessante saber como implementar essas coisas, mas se você usa um pacote estatístico ou uma linguagem de programação, recomendo que você obtenha e use uma função ou biblioteca adequada para a geração de números aleatórios. Se desejar orientação sobre qual biblioteca usar, adicione informações específicas sobre a (s) linguagem (s) de programação que você está usando.

Editar: À luz dos comentários, algumas outras respostas e o fato de que o Fixee aceitou essa resposta, darei mais alguns detalhes sobre como se pode usar transformações de variáveis ​​uniformes para produzir variáveis ​​normais.

  • Um método, já mencionado em um comentário de VitalStatistix , é o método Box-Muller que pega duas variáveis ​​aleatórias uniformes independentes e produz duas variáveis ​​aleatórias normais independentes. Um método semelhante que evita o cálculo de duas funções transcendentais sin e cos à custa de mais algumas simulações foi postado como resposta pela francogrex .
  • Um método completamente geral é a transformação de uma variável aleatória uniforme pela função de distribuição inversa. Se é distribuído uniformemente em [ 0 , 1 ], então Φ - 1 ( U ) possui uma distribuição normal padrão. Embora não exista uma fórmula analítica explícita para Φ - 1 , ela pode ser calculada por aproximações numéricas precisas. A implementação atual em R (verifiquei pela última vez) usa essa ideia. O método é conceitualmente muito simples, mas requer uma implementação precisa de Φ - 1 , que provavelmente não é tão difundida quanto as (outras) funções transcendentaisU[0,1]
    Φ1(U)
    Φ1Φ1log , pecado e cos .
  • Várias respostas mencionam a possibilidade de usar o teorema do limite central para aproximar a distribuição normal como uma média de variáveis ​​aleatórias uniformes. Isso geralmente não é recomendado. Argumentos apresentados, como combinar a média 0 e a variância 1, e considerações de apoio à distribuição não são convincentes. No Exercício 2.3, em "Introduzindo Métodos de Monte Carlo com R", de Christian P. Robert e George Casella, esse gerador é chamado de antiquado e a aproximação é chamada de muito pobre .
  • Há um número desconcertante de outras idéias. Capítulo 3 e, em particular, Seção 3.4, em "A Arte da Programação por Computador", vol. 2 de Donald E. Knuth é uma referência clássica na geração de números aleatórios. Brian Ripley escreveu Geração de variáveis ​​aleatórias por computador: um tutorial , que pode ser útil. O livro mencionado por Robert e Casella, ou talvez o Capítulo 2 em seu outro livro, "Métodos estatísticos de Monte Carlo", também é recomendado.

No final do dia, um método implementado corretamente não é melhor que o gerador de números pseudo-aleatórios uniformes usado. Pessoalmente, prefiro confiar em bibliotecas para fins especiais que acredito serem confiáveis. Quase sempre confio nos métodos implementados no R diretamente no R ou através da API no C / C ++. Obviamente, isso não é uma solução para todos, mas não estou familiarizado o suficiente com outras bibliotecas para recomendar alternativas.

NRH
fonte
(+1) Boas respostas e conselhos para o PO.
cardeal
18
2log(U1)cos(2πU2)
2log(U1)sin(2πU2)
2
@Vital: Não é um comentário desnecessário; uma boa. A transformação Box-Muller é provavelmente a mais fácil de programar, com poucas chances de inadvertidamente fazer algo ruim. Não é o mais rápido , mas é competitivo o suficiente. Dito isto, o uso de uma biblioteca de códigos estabelecida provavelmente é ainda mais seguro, principalmente porque o local onde é mais provável que você cometa um passo em falso é como as entradas variáveis ​​aleatórias uniformes são geradas!
cardeal
@Vital: Obrigado, é isso que eu estava procurando. Se você deseja converter seu comentário em uma resposta, eu o aprovaria com prazer.
Fixee
11
@VitalStatistix, é um ótimo comentário e parece que era isso que o OP estava procurando. Por que não transformá-lo em resposta e talvez elaborá-lo um pouco sobre a idéia geral de usar transformações de variáveis ​​aleatórias uniformes. Hesitei em fazer isso pelo motivo que o cardeal menciona principalmente porque não sei se o gerador de uniforme padrão de qualquer idioma é um bom gerador.
NRH
10

Este é realmente um comentário sobre a resposta de Michael Lew e o comentário de Fixee, mas é postado como resposta porque não tenho reputação neste site para comentar.

[0,1]61

E[i=112Xi]=i=112E[Xi]=12×12=6
var[i=112Xi]=i=112var[Xi]=12×112=1.
i=112Xi610/12i=112Xi6[6,6]6
Dilip Sarwate
fonte
5

Além da resposta da NRH, se você ainda não tem como gerar amostras aleatórias a partir de uma "distribuição normal padrão" N (0,1), abaixo é uma maneira boa e simples (desde que você mencione que não possui uma estatística) pacote, as funções abaixo devem estar disponíveis na maioria das linguagens de programação padrão).

1. Gere u e v como dois números aleatórios distribuídos uniformemente no intervalo de -1 a 1 por
u = 2 r1 - 1ev = 2 r2 - 1

2.calculate w = u^2 + v^2se w> 1 voltar para 1

3.rode u * z e y = v * z com z= sqrt(-2ln(w)/w) Um código de amostra ficaria assim:

u = 2 * random() - 1;
v = 2 * random() - 1;
w = pow(u, 2) + pow(v, 2);
if (w < 1) {
    z = sqrt((-2 * log(w)) / w);
    x = u * z;
    y = v * z;
    }

então use o que MHR sugeriu acima para obter os desvios aleatórios de N(mu, sigma^2).

francogrex
fonte
Quando postei minha resposta acima, não percebi que o @vitalStatistix deu a você o algoritmo Box-Muller Transform. O que eu dou acima também é tão bom, suponho.
Francogrex #
2
Você poderia explicar o motivo da geração de variáveis ​​normais a partir de distribuição uniforme (exceto de uma perspectiva algorítmica) e não apenas o uso direto do pdf de uma distribuição Gaussiana / Normal? Ou é totalmente errado?
Arun
4
@Arun Uma razão: o método polar da Marsaglia é útil quando você tem apenas um RNG que gera desvios uniformes.
chl
11
@ Arun é a maneira mais fácil. Você também pode gerar diretamente do pdf usando, por exemplo, o método "rejeição de aceitação". Postei para você um exemplo simples no meu site (porque não há espaço suficiente na caixa de comentários aqui).
Francogrex #
4

A distribuição normal surge quando se soma muitos valores aleatórios de distribuição semelhante (quero dizer, similares um ao outro). Se você adicionar dez ou mais valores aleatórios distribuídos uniformemente, a soma será quase normalmente distribuída. (Adicione mais de dez se quiser que seja ainda mais normal, mas dez é suficiente para quase todos os fins.)

Diga que seus valores aleatórios uniformes são distribuídos uniformemente entre 0 e 1. A soma será então entre 0 e 10. Subtraia 5 da soma e a média da distribuição resultante será 0. Agora você divide o resultado pelo desvio padrão de a distribuição normal (quase) e multiplique o resultado pelo desvio padrão desejado. Infelizmente, não sei ao certo qual é o desvio padrão da soma de dez desvios aleatórios uniformes, mas se tivermos sorte, alguém nos dirá em um comentário!

Prefiro conversar com os alunos sobre a distribuição normal nesses termos, porque a utilidade da suposição de uma distribuição normal em muitos sistemas decorre inteiramente da propriedade de que as somas de muitas influências aleatórias levam a uma distribuição normal.

Michael Lew
fonte
Você está usando o limite central aqui (que um monte de variáveis ​​aleatórias iid soma uma variável aleatória normal). Não pensei nisso porque pensei que seria muito lento, mas você diz que 10 é suficiente ?! Isso é melhor do que computar um log e um pecado / cos e um sqrt!
Fixee 03/10
Além disso, a média do uniforme rv em [0,1] é 0,5 com variação 1/12. Se você soma 10, obtém uma média de 5 e variação 10/12 = 5/6.
Fixee 03/10
11
Do ponto de vista pedagógico, esse método fornece uma discussão e demonstração úteis e agradáveis. No entanto, eu desencorajaria fortemente qualquer pessoa a usar essa abordagem na prática.
cardeal
11
logsincos
11
@ Michael: Declarar que fornece a distribuição "correta" é um pouco exagerado, principalmente porque a distribuição aproximada tem suporte compacto e, em muitas aplicações, a pessoa se importa com a eficiência com que as variáveis ​​podem ser geradas. :) O ponto é que existem várias opções muito melhores disponíveis. Mas ainda acho que isso fornece algo útil pedagogicamente.
cardeal