Implementare una variabile casuale gaussiana usando una variabile casuale uniforme


11

Sto cercando di scrivere una funzione C ++ che restituirà valori casuali gaussiani, dati i loro mezzi e varianze.

C'è una funzione di libreria rand(), che restituisce numeri casuali tra 0e RAND_MAX. RAND_MAXnon ha un valore fisso, ma è garantito che sarà almeno . Il suo PDF è uniforme.2151

Sto usando il Teorema del limite centrale per trasformare questo rand()in una variabile gaussiana. Quello che sto facendo esattamente è chiamare gli rand()orari specificati dall'utente, quindi sommare i loro valori di ritorno, quindi spostare la sua media sulla media specificata dall'utente.

PDF gaussiano
Nel grafico sopra, ho chiamato il mio generatore casuale gaussiano per volte, e ho tracciato le frequenze dei suoi valori di ritorno. Come vedi, la sua varianza è enorme, poiché è creata dalla somma di molti altri valori casuali.107

Restituisce correttamente una variabile gaussiana con un PDF gaussiano e con il valore medio specificato. Tuttavia, il problema è la sua varianza. Sono bloccato a questo punto, perché non so come modificarne la varianza con il valore specificato dall'utente.

Questo è il mio codice (per il momento incompleto; il parametro "Varianza" viene ignorato):

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);
}

Supponiamo che NUM_GAUSSIAN_SUMSsia 100 e RAND_MAX32767.

Voglio cambiare la varianza della variabile casuale in base al parametro della funzione. La mia domanda è: come posso cambiare la varianza di questa variabile casuale? Come posso farlo?


3
Esistono modi migliori e più rapidi del teorema del limite centrale per la generazione di variabili casuali gaussiane. Cerca il metodo Box-Muller per uno; si dice che un metodo ziggurat sia ancora migliore.
Dilip Sarwate,


3
Nei tempi antichi in cui i tempi di esecuzione erano una considerazione importante, le persone sommavano variabili casuali (non ) e sottraevano per ottenere una semplice approssimazione a una normale variabile casuale, quindi ridimensionavano per ottenere una variabile casuale . (Per questo motivo, vedi la risposta di @ Hilmar). Per molte applicazioni questo semplice metodo ha funzionato molto bene, ma i valori sono stati limitati all'intervallo e questa semplice idea è stata abbandonata a margine quando Six-Sigma è diventato una parola d'ordine. 12 U(0,1)1006N(0,1)Y=σX+μN(μ,σ2)(μ6σ,μ+6σ)
Dilip Sarwate,

@DilipSarwate forse dovresti pubblicare quelle alternative come risposta con una giustificazione del perché preferiremmo
Ivo Flipse

@IvoFlipse La risposta alla domanda "Come faccio a correggere la varianza dopo aver corretto la media?" è essenzialmente ciò che dice la risposta accettata da Hilmar, modificata dai commenti: correggi la varianza ridimensionando e poi correggendo la media, o meglio ancora, non iniziare fissando prima la media poiché dovrai correggere nuovamente più tardi; correggi prima la varianza ridimensionando e poi correggi la media. L'OP non indica di essere interessato a metodi migliori e di non aver nemmeno votato il link di Nibot che ha anche il codice per il metodo Box-Muller. Quindi lascerò le cose come sono.
Dilip Sarwate,

Risposte:


6

Il tuo algoritmo iniziale crea una variabile casuale distribuita uniformemente tra 0 e 1. La varianza è 1/12. Se sommi le NUM_GAUSSIAN_SUMSistanze di ciò, la varianza sarà NUM_GAUSSIAN_SUMS/12. Per arrivare a una varianza target V, è necessario moltiplicare la variabile casuale sommata con sqrt(V*12/NUM_GAUSSIAN_SUMS).

Come nota a margine, un modello funzionerà abbastanza bene per float e doppi ma ci saranno significativi problemi numerici con qualsiasi tipo di punto fisso.


5

come posso cambiare la varianza di questa variabile casuale?

Per moltiplicazione, ovviamente. La varianza di , dove è la costante moltiplicativa e è la variabile casuale, è la varianza di .cXcXc2X


cXcX

1
Centra, ridimensiona, quindi ripristina la media. Il ridimensionamento di una variabile casuale centrata non influirà sulla media (zero).
Emre,

1

C'è ancora un altro modo!

Pensaci, e se volessi qualche altra distribuzione rispetto a Gaussian? In tal caso non si potrebbe davvero usare il teorema del limite centrale; come lo risolvi?

C'è un modo per convertire una variabile casuale uniforme in PDF arbitrario. Questo metodo è chiamato metodo di trasformazione inversa

U[0-1]

X=FX-1(U)

FX(X)

Quindi, tutto ciò che devi fare è applicare la funzione CDF inversa alla variabile che hai recuperato dal campione dell'universo uniforme.

Inoltre, a differenza dei metodi precedenti, ciò non richiederà alcuna iterazione e non dipenderà da quante iterazioni verranno prese per chiudere i risultati al gaussiano.

Ecco uno dei riferimenti che ne fornisce una prova.


3
> C'è ancora un altro modo! Vero, ma irrilevante per la domanda in esame che riguarda specificamente le variabili casuali gaussiane. Né il CDF gaussiano né il suo inverso possono essere espressi in termini elementari usando un numero finito di operazioni, quindi il metodo suggerito non può essere usato.
Dilip Sarwate,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.