Generazione di campioni casuali da una distribuzione personalizzata


16

Sto cercando di generare campioni casuali da un pdf personalizzato utilizzando R. Il mio pdf è:

fX(x)=32(1x2),0x1

Ho generato campioni uniformi e poi ho provato a trasformarlo nella mia distribuzione personalizzata. L'ho fatto trovando il cdf della mia distribuzione ( ) e impostandolo sul campione uniforme ( ) e risolvendo per .FX(x)ux

FX(x)=Pr[Xx]=0x32(1y2)dy=32(xx33)

Per generare un campione casuale con la distribuzione precedente, ottieni un campione uniforme u[0,1] e risolvi per x in

32(xx33)=u

L'ho implementato Re non ottengo la distribuzione prevista. Qualcuno può sottolineare il difetto nella mia comprensione?

nsamples <- 1000;
x <- runif(nsamples);

f <- function(x, u) { 
  return(3/2*(x-x^3/3) - u);
}

z <- c();
for (i in 1:nsamples) {
  # find the root within (0,1) 
  r <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root;
  z <- c(z, r);
}

1
Deve essere un errore di codifica. Non uso R, quindi non posso dire quale sia esattamente l'errore, ma ho appena codificato la tua soluzione (avendo cura di prendere la radice media del polinomio cubico, che si trova sempre tra 0 e 1), e Ottengo un buon accordo tra i campioni e la distribuzione prevista. Potrebbe essere un problema con il tuo root finder? Cosa c'è di sbagliato con i campioni che stai ricevendo?
jpillow,

Ho provato il tuo codice (che non è molto efficiente, tra l'altro) e ottengo la distribuzione prevista.
Aniko,

@jpillow e @Aniko Il mio errore. Quando l'ho usato nsamples <- 1e6è stata una buona partita.
Anand,

2
@Anand Un modo è osservare che , consentendo il calcolo diretto di in termini di . x=2sin(arcsin(u)/3)xu
whuber

Risposte:


11

Sembra che tu abbia capito che il tuo codice funziona, ma @Aniko ha sottolineato che potresti migliorarne l'efficienza. Il tuo più grande guadagno di velocità verrebbe probabilmente dalla pre-allocazione della memoria in zmodo da non farla crescere in un ciclo. Qualcosa del genere z <- rep(NA, nsamples)dovrebbe fare il trucco. È possibile ottenere un piccolo guadagno di velocità dall'uso vapply()(che specifica il tipo di variabile restituito) invece di un ciclo esplicito (c'è una grande domanda SO sulla famiglia di applicazione).

> nsamples <- 1E5
> x <- runif(nsamples)
> f <- function(x, u) 1.5 * (x - (x^3) / 3) - u
> z <- c()
> 
> # original version
> system.time({
+ for (i in 1:nsamples) {
+   # find the root within (0,1) 
+   r <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root
+   z <- c(z, r)
+ }
+ })
   user  system elapsed 
  49.88    0.00   50.54 
> 
> # original version with pre-allocation
> z.pre <- rep(NA, nsamples)
> system.time({
+ for (i in 1:nsamples) {
+   # find the root within (0,1) 
+   z.pre[i] <- uniroot(f, c(0,1), tol = 0.0001, u = x[i])$root
+   }
+ })
   user  system elapsed 
   7.55    0.01    7.78 
> 
> 
> 
> # my version with sapply
> my.uniroot <- function(x) uniroot(f, c(0, 1), tol = 0.0001, u = x)$root
> system.time({
+   r <- vapply(x, my.uniroot, numeric(1))
+ })
   user  system elapsed 
   6.61    0.02    6.74 
> 
> # same results
> head(z)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738
> head(z.pre)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738
> head(r)
[1] 0.7803198 0.2860108 0.5153724 0.2479611 0.3451658 0.4682738

E non ti serve la ;fine di ogni riga (sei un MATLAB convertito?).


Grazie per la risposta dettagliata e per la segnalazione vapply. Ho programmato C/C++per molto tempo e questa è la ragione della ;sofferenza!
Anand,

1
uniroot107
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.