Implementando variável aleatória gaussiana usando uma variável aleatória uniforme

11

Estou tentando escrever uma função C ++ que retornará valores aleatórios gaussianos, considerando suas médias e variações.

Existe uma função de biblioteca rand(), que retorna números aleatórios entre 0e RAND_MAX. RAND_MAXnão possui um valor fixo, mas é garantido que será pelo menos . Seu PDF é uniforme.2151

Estou usando o Teorema do Limite Central para transformar isso rand()em uma variável gaussiana. O que estou fazendo exatamente é chamar rand()um horário especificado pelo usuário, somar seus valores de retorno e mudar sua média para a média especificada pelo usuário.

Gaussian PDF
Na plotagem acima, liguei para meu gerador aleatório gaussiano vezes e ploquei as frequências de seus valores de retorno. Como você vê, sua variação é enorme, pois é criada pela soma de muitos outros valores aleatórios.107

Ele retorna com êxito uma variável gaussiana com um PDF gaussiano e com o valor médio especificado. No entanto, o problema é sua variação. Estou parado neste momento, porque não sei como alterar sua variação para o valor especificado pelo usuário.

Este é o meu código (incompleto por enquanto; o parâmetro "Variação" é ignorado):

template <class T>
T Random::GetGaussian(T Mean /*= 0*/, T Variance /*= 1*/)
{
    T MeanOfSum = NUM_GAUSSIAN_SUMS / static_cast<T>(2);
    T Rand = 0;
    for (uint64_t i=0; i<NUM_GAUSSIAN_SUMS; i++)
    {
        Rand += static_cast<T>(rand()) / RAND_MAX;
    }
    return Rand - (MeanOfSum - Mean);
}

Suponha que NUM_GAUSSIAN_SUMSseja 100 e RAND_MAXseja 32767.

Eu quero mudar a variação da variável aleatória de acordo com o parâmetro da função. Minha pergunta é: como posso alterar a variação dessa variável aleatória? Como eu posso fazer isso?

hkBattousai
fonte
3
Existem maneiras melhores e mais rápidas do que o teorema do limite central para gerar variáveis ​​aleatórias gaussianas. Procure o método Box-Muller para um; um método em zigurate é considerado ainda melhor.
usar o seguinte
3
Antigamente, quando o tempo de execução era uma consideração importante, as pessoas somavam variáveis ​​aleatórias (não ) e subtraíam para obter uma aproximação simples de uma variável aleatória padrão e depois escalavam para obter uma variável aleatória . (Por que isso funciona, consulte a resposta de @ Hilmar). Para muitas aplicações, esse método simples funcionou muito bem, mas os valores estavam restritos ao intervalo e essa idéia simples foi deixada de lado quando o Six-Sigma se tornou um chavão. U ( 0 , 1 ) 100 6 N ( 0 , 1 ) Y = σ X + μ N ( μ , σ 2 ) ( μ - 6 σ , μ + 6 σ )12 U(0,1)1006N(0,1)Y=σX+μN(μ,σ2)(μ6σ,μ+6σ)
precisa
@DilipSarwate talvez você deve postar essas alternativas como uma resposta com uma justificação por que nós preferimos-lo
Ivo Flipse
@IvoFlipse A resposta à pergunta "Como faço para corrigir a variação depois de corrigir a média?" é essencialmente o que a resposta aceita por Hilmar diz, modificada pelos comentários: corrija a variação escalonando e corrija novamente a média, ou melhor ainda, não comece corrigindo a média primeiro, pois você precisará corrigir novamente mais tarde; corrija a variação primeiro escalando e depois corrija a média. O OP não indica que ele / ela está interessado em melhores métodos e nem sequer aprovou o link do nibot que ainda possui o código para o método Box-Muller. Então vou deixar as coisas como estão.
Dilip Sarwate

Respostas:

6

Seu algoritmo inicial cria uma variável aleatória que é distribuída uniformemente entre 0 e 1. A variação disso é 1/12. Se você somar NUM_GAUSSIAN_SUMSinstâncias disso, a variação será NUM_GAUSSIAN_SUMS/12. Para obter uma variação de destino V, é necessário multiplicar a variável aleatória somada por sqrt(V*12/NUM_GAUSSIAN_SUMS).

Como observação lateral, um modelo funcionará razoavelmente bem para flutuadores e duplos, mas haverá problemas numéricos significativos com qualquer tipo de ponto fixo.

Hilmar
fonte
5

como posso alterar a variação dessa variável aleatória?

Por multiplicação, é claro. A variação de , onde é a constante multiplicativa e é a variável aleatória, é a variância de .c X c 2 XcXcXc2X

Emre
fonte
Infelizmente, a média de é vezes a média de e, portanto, um dos parâmetros que o OP definiu antes de tentar corrigir a variação deve ser redefinido para o valor desejado. c XcXcX
Dilip Sarwate
1
Centralize, redimensione e restaure a média. Escalar uma variável aleatória centralizada não afetará a média (zero).
Emre
1

Existe ainda outra maneira!

Pense nisso, e se você quisesse alguma outra distribuição em oposição à gaussiana? Nesse caso, você realmente não poderia usar o teorema do limite central; como você resolve isso?

Existe uma maneira de converter variáveis ​​aleatórias uniformes em PDF arbitrário. Esse método é chamado de método de transformação inversa

Se estiver uniformemente distribuído no intervalo (0, 1), entãoU[01]

X=FX1(U)

tem o cdf .FX(x)

Portanto, tudo o que você precisa fazer é aplicar a função CDF inversa à variável que você recuperou da amostra do rv uniforme.

Além disso, diferentemente dos métodos anteriores - isso não exigirá nenhuma iteração e não dependerá de quantas iterações serão feitas para tornar os resultados mais próximos do Gaussian.

Aqui está uma das referências que fornece uma prova disso.

Dipan Mehta
fonte
3
> Existe ainda outra maneira! É verdade, mas irrelevante para a questão em consideração, que é especificamente sobre variáveis ​​aleatórias gaussianas. Nem o CDF gaussiano nem seu inverso podem ser expressos em termos elementares usando um número finito de operações e, portanto, o método sugerido não pode ser usado.
precisa