Muestra de una distribución Normal pero ignora todos los valores aleatorios que caen fuera del rango especificado antes de las simulaciones.
Este método es correcto, pero, como lo mencionó @ Xi'an en su respuesta, tomaría mucho tiempo cuando el rango es pequeño (más precisamente, cuando su medida es pequeña bajo la distribución normal).
F- 1( U)FU∼ Unif ( 0 , 1 )Fsol( a , b )sol- 1( U) con U∼ Unif ( G ( a ) , G ( b ) ).
Sin embargo, y esto ya lo menciona @ Xi'an en un comentario, para algunas situaciones el método de inversión requiere una evaluación muy precisa de la función cuantilsol- 1, y agregaría que también requiere un cálculo rápido desol- 1. Cuandosol es una distribución normal, la evaluación de sol- 1 es bastante lento y no es muy preciso para valores de un y si fuera del "rango" de sol.
Simulate a truncated distribution using importance sampling
A possibility is to use importance sampling. Consider the case of the standard Gaussian distribution N(0,1). Forget the previous notations, now let G be the Cauchy distribution. The two above mentionned requirements are fulfilled for G : one simply has G(q)=arctan(q)π+12 and G−1(q)=tan(π(q−12)). Therefore, the truncated Cauchy distribution is easy to sample by the inversion method and it is a good choice of the instrumental variable for importance sampling of the truncated normal distribution.
After a bit of simplifications, sampling U∼Unif(G(a),G(b)) and taking G−1(U) is equivalent to take tan(U′) with U′∼Unif(arctan(a),arctan(b)):
a <- 1
b <- 5
nsims <- 10^5
sims <- tan(runif(nsims, atan(a), atan(b)))
Now one has to calculate the weight for each sampled value xi, defined as the ratio ϕ(x)/g(x) of the two densities up to normalization, hence we can take
w(x)=exp(−x2/2)(1+x2),
but it could be safer to take the log-weights:
log_w <- -sims^2/2 + log1p(sims^2)
w <- exp(log_w) # unnormalized weights
w <- w/sum(w)
The weighted sample (xi, w ( xyo) ) permite estimar la medida de cada intervalo [ u , v ] debajo de la distribución objetivo, sumando los pesos de cada valor muestreado que cae dentro del intervalo:
u <- 2; v<- 4
sum(w[sims>u & sims<v])
## [1] 0.1418
Esto proporciona una estimación de la función acumulativa objetivo. Podemos obtenerlo y trazarlo rápidamente con el spatsat
paquete:
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
Por supuesto, la muestra ( xyo)definitivamente no es una muestra de la distribución objetivo, sino de la distribución Cauchy instrumental, y uno obtiene una muestra de la distribución objetivo realizando un nuevo muestreo ponderado , por ejemplo utilizando el muestreo multinomial:
msample <- rmultinom(1, nsims, w)[,1]
resims <- rep(sims, times=msample)
hist(resims)
mean(resims>u & resims<v)
## [1] 0.1446
Otro método: muestreo de transformación inversa rápida
Olver y Townsend desarrollaron un método de muestreo para una amplia clase de distribución continua. Se implementa en la biblioteca chebfun2 para Matlab , así como en la biblioteca ApproxFun para Julia . Recientemente descubrí esta biblioteca y suena muy prometedora (no solo para el muestreo aleatorio). Básicamente, este es el método de inversión, pero utiliza aproximaciones potentes del cdf y el cdf inverso. La entrada es la función de densidad objetivo hasta la normalización.
La muestra se genera simplemente mediante el siguiente código:
using ApproxFun
f = Fun(x -> exp(-x.^2./2), [1,5]);
nsims = 10^5;
x = sample(f,nsims);
Como se verifica a continuación, produce una medida estimada del intervalo [ 2 , 4 ] cercano al obtenido previamente por muestreo de importancia:
sum((x.>2) & (x.<4))/nsims
## 0.14191