Campione da una distribuzione normale ma ignora tutti i valori casuali che non rientrano nell'intervallo specificato prima delle simulazioni.
Questo metodo è corretto, ma, come menzionato da @ Xi'an nella sua risposta, ci vorrebbe molto tempo quando l'intervallo è piccolo (più precisamente, quando la sua misura è piccola sotto la distribuzione normale).
Come ogni altra distribuzione, si potrebbe usare il metodo di inversione (chiamato anche campionamento di trasformazione inversa ), dove è la (funzione cumulativa della) distribuzione di interesse e . Quando è la distribuzione ottenuta troncando una parte della distribuzione su un intervallo , questo equivale al campione con .F−1(U)FU∼ Unif ( 0 , 1 )Fsol( a , b )sol- 1( U)U∼ Unif ( G ( a ) , G ( b ) )
Tuttavia, e questo è già menzionato da @ Xi'an in un commento, per alcune situazioni il metodo di inversione richiede una valutazione molto precisa della funzione quantile , e aggiungerei che richiede anche un rapido calcolo di . Quando è una distribuzione normale, la valutazione di è piuttosto lento, e non è molto preciso per valori di e fuori del "range" di .sol- 1sol- 1solsol-1un'Bsol
Simula una distribuzione troncata utilizzando il campionamento per importanza
Una possibilità è utilizzare il campionamento di importanza . Si consideri il caso della distribuzione gaussiana standard . Dimentica le notazioni precedenti, ora lascia che sia la distribuzione di Cauchy. I due requisiti sopra menzionati sono soddisfatti per : uno ha semplicemente e . Pertanto, la distribuzione troncata di Cauchy è facile da campionare con il metodo di inversione ed è una buona scelta della variabile strumentale per il campionamento di importanza della distribuzione normale troncata.N( 0 , 1 )solsolG ( q) = arctan( q)π+ 12sol- 1( q) = abbronzatura( π( q- 12) )
Dopo un po 'di semplificazioni, campionare e prendere equivale a prendere con :U∼ Unif ( G ( a ) , G ( b ) )sol- 1( U)abbronzatura( U')'∼ Unif ( arctan( a ) , arctan( b ) )
a <- 1
b <- 5
nsims <- 10^5
sims <- tan(runif(nsims, atan(a), atan(b)))
Ora si deve calcolare il peso per ciascun valore campionato , definito come il rapporto delle due densità fino alla normalizzazione, quindi possiamo prendere
ma potrebbe essere più sicuro prendere i pesi del log:Xioϕ ( x ) / g( x )
w ( x ) = exp( - x2/ 2)(1+ x2) ,
log_w <- -sims^2/2 + log1p(sims^2)
w <- exp(log_w) # unnormalized weights
w <- w/sum(w)
Il campione ponderato consente di stimare la misura di ogni intervallo sotto la distribuzione target, sommando i pesi di ciascun valore campionato che rientra nell'intervallo:( xio, w ( xio) )[ u , v ]
u <- 2; v<- 4
sum(w[sims>u & sims<v])
## [1] 0.1418
Ciò fornisce una stima della funzione cumulativa di destinazione. Possiamo rapidamente ottenerlo e tracciarlo con il spatsat
pacchetto:
F <- spatstat::ewcdf(sims,w)
# estimated F:
curve(F(x), from=a-0.1, to=b+0.1)
# true F:
curve((pnorm(x)-pnorm(a))/(pnorm(b)-pnorm(a)), add=TRUE, col="red")
# approximate probability of u<x<v:
F(v)-F(u)
## [1] 0.1418
Ovviamente, il campione è sicuramente un campione della distribuzione target, ma della distribuzione strumentale di Cauchy, e si ottiene un campione della distribuzione target eseguendo un ricampionamento ponderato , ad esempio usando il campionamento multinomiale:( xio)
msample <- rmultinom(1, nsims, w)[,1]
resims <- rep(sims, times=msample)
hist(resims)
mean(resims>u & resims<v)
## [1] 0.1446
Un altro metodo: campionamento rapido della trasformata inversa
Olver e Townsend hanno sviluppato un metodo di campionamento per un'ampia classe di distribuzione continua. È implementato nella libreria chebfun2 per Matlab e nella libreria ApproxFun per Julia . Ho scoperto di recente questa libreria e sembra molto promettente (non solo per il campionamento casuale). Fondamentalmente questo è il metodo di inversione, ma usando potenti approssimazioni del cdf e del cdf inverso. L'input è la funzione di densità target fino alla normalizzazione.
L'esempio è semplicemente generato dal seguente codice:
using ApproxFun
f = Fun(x -> exp(-x.^2./2), [1,5]);
nsims = 10^5;
x = sample(f,nsims);
Come verificato di seguito, fornisce una misura stimata dell'intervallo vicino a quello precedentemente ottenuto dal campionamento per importanza:[ 2 , 4 ]
sum((x.>2) & (x.<4))/nsims
## 0.14191