Vantaggi di Box-Muller rispetto al metodo CDF inverso per la simulazione della distribuzione normale?


15

Per simulare una distribuzione normale da un insieme di variabili uniformi, esistono diverse tecniche:

  1. L'algoritmo Box-Muller , in cui si campiona due varianze uniformi indipendenti su e le trasforma in due distribuzioni normali standard indipendenti tramite: Z 0 = (0,1)

    Z0=2lnU1cos(2πU0)Z1=2lnU1sin(2πU0)
  2. il metodo CDF , dove si può equiparare il normale cdf a una variabile Uniforme: F ( Z ) = U e derivare Z = F - 1 ( U )(F(Z))

    F(Z)=U
    Z=F1(U)

La mia domanda è: quale è dal punto di vista computazionale più efficiente? Penso che sia il secondo metodo, ma la maggior parte degli articoli che leggo usano Box-Muller - perché?

Informazioni aggiuntive:

L'inverso del normale CDF è noto e dato da:

F1(Z)=2erf1(2Z1),Z(0,1).

Quindi:

Z=F1(U)=2erf1(2U1),U(0,1).

1
Qual è l'inverso del normale cdf? Non può essere calcolato analiticamente, solo se il CDF originale è approssimato con la funzione lineare a tratti.
Artem Sobolev,

I due non sono strettamente correlati? Box Muller, credo, è un caso particolare per la generazione a 2 variabili.
ttnphns,

Ciao Barmaley, ho aggiunto alcune informazioni in più sopra. Il CDF inverso ha un'espressione - tuttavia l' deve essere calcolato dal punto di vista computazionale - quindi questo potrebbe essere il motivo per cui si preferisce il box Muller? Ho pensato che erf 1 sarebbe stato calcolato nelle tabelle di ricerca, proprio come sono i valori di sin e coseno ? Quindi non è molto più costoso dal punto di vista computazionale? Potrei sbagliarmi comunque. erf1erf1sincosine
user2350366

2
Esistono versioni di Box-Muller senza peccato e coseno.
Xi'an,

2
@Dilip Per applicazioni di precisione molto bassa, come la computer grafica, il seno e il coseno possono infatti essere ottimizzati utilizzando apposite tabelle di ricerca. Per le applicazioni statistiche, tuttavia, tale ottimizzazione non viene mai utilizzata. Alla fine non è davvero più difficile calcolare rispetto a log o sqrt , ma sui moderni sistemi informatici le funzioni elementari correlate a exp - comprese le funzioni di trig - tendono ad essere ottimizzate ( cos e log erano istruzioni di base su Intel 8087 chip!), Mentre erf non è disponibile o è stato codificato a un livello più alto (= più lento). erf1logsqrtexpcoslog
whuber

Risposte:


16

Da una prospettiva puramente probabilistica, entrambi gli approcci sono corretti e quindi equivalenti. Dal punto di vista algoritmico, il confronto deve considerare sia la precisione che i costi di calcolo.

Box-Muller si basa su un generatore uniforme e costa circa lo stesso di questo generatore uniforme. Come menzionato nel mio commento, puoi cavartela senza chiamate seno o coseno, se non senza il logaritmo:

  • genera fino a S = U 2 1 + U 2 21
    U1,U2iidU(1,1)
    S=U12+U221
  • prendi e definireX1=ZU1Z=2log(S)/S
    X1=ZU1, X2=ZU2

L'algoritmo di inversione generica richiede la chiamata al cdf normale inverso, ad esempio qnorm(runif(N))in R, che può essere più costoso di quanto sopra e, cosa più importante, può fallire nelle code in termini di precisione, a meno che la funzione quantile non sia ben codificata.

A seguire i commenti di whuber , il confronto di rnorm(N)ed qnorm(runif(N))è a vantaggio del cdf inverso, entrambi in fase di esecuzione:

> system.time(qnorm(runif(10^8)))
sutilisateur     système      écoulé
 10.137           0.120      10.251 
> system.time(rnorm(10^8))
utilisateur     système      écoulé
 13.417           0.060      13.472` `

e in termini di adattamento nella coda: inserisci qui la descrizione dell'immagine

A seguito di un commento di Radford Neal sul mio blog , voglio sottolineare che il valore predefinito rnormin R utilizza il metodo di inversione, quindi il confronto sopra riportato si riflette sull'interfaccia e non sul metodo di simulazione stesso! Per citare la documentazione R su RNG:

‘normal.kind’ can be ‘"Kinderman-Ramage"’, ‘"Buggy
 Kinderman-Ramage"’ (not for ‘set.seed’), ‘"Ahrens-Dieter"’,
 ‘"Box-Muller"’, ‘"Inversion"’ (the default), or ‘"user-supplied"’.
 (For inversion, see the reference in ‘qnorm’.)  The
 Kinderman-Ramage generator used in versions prior to 1.7.1 (now
 called ‘"Buggy"’) had several approximation errors and should only
 be used for reproduction of old results.  The ‘"Box-Muller"’
 generator is stateful as pairs of normals are generated and
 returned sequentially.  The state is reset whenever it is selected
 (even if it is the current normal generator) and when ‘kind’ is
 changed.

3
logΦ1Φ1X1X2Uio-1101

2
R 3.0.2rowSumsSqnorm(runif(N))InverseCDF[NormalDistribution[], #] &

1
Sono d'accordo, qnorm(runif(N))è addirittura del 20% più veloce dirnorm(N)
Xi'an

3
Φ1sincos

1
Per fare un confronto, usando un i7-3740QM @ 2.7Ghz e R 3.12, per le seguenti chiamate: RNGkind(kind = NULL, normal.kind = 'Inversion');At <- microbenchmark(A <- rnorm(1e5, 0, 1), times = 100L);RNGkind(kind = NULL, normal.kind = 'Box-Muller');Bt <- microbenchmark(B <- rnorm(1e5, 0, 1), times = 100L)ottengo l' mean 11.38363 median 11.18718inversione e mean 13.00401 median 12.48802per Box-Muller
Avraham
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.