Kümülatif dağıtım işlevi ile bir dağıtımdan sahte rasgele sayılar simüle R bir program yazmaya çalışıyorum:
burada
Ters dönüşüm örneklemeyi denedim ama tersi analitik olarak çözülebilir görünmüyor. Bu soruna bir çözüm önerebilirseniz sevinirim
Kümülatif dağıtım işlevi ile bir dağıtımdan sahte rasgele sayılar simüle R bir program yazmaya çalışıyorum:
burada
Ters dönüşüm örneklemeyi denedim ama tersi analitik olarak çözülebilir görünmüyor. Bu soruna bir çözüm önerebilirseniz sevinirim
Yanıtlar:
Bu egzersize basit (ve ekleyebilirsem, zarif) bir çözüm var: iki hayatta kalma dağılımının bir ürünü gibi göründüğünden:
dağıtımı ,
Bu durumda , Üstel dağılımı ve , -th Üstel dağılımının gücü .
İlişkili R kodu alabildiği kadar basit
x=pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))) #simulating an n-sample
ve ters pdf ve kabul-reddetme kararlarından kesinlikle çok daha hızlıdır:
> n=1e6
> system.time(results <- Vectorize(simulate,"prob")(runif(n)))
utilisateur système écoulé
89.060 0.072 89.124
> system.time(x <- simuF(n,1,2,3))
utilisateur système écoulé
1.080 0.020 1.103
> system.time(x <- pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))))
utilisateur système écoulé
0.160 0.000 0.163
şaşırtıcı derecede mükemmel uyum ile:
Ters dönüşümü her zaman sayısal olarak çözebilirsiniz.
Aşağıda çok basit bir ikiye arama yapıyorum. Belirli bir girdi olasılığı ( formülünüzde zaten bir bulunduğundan kullanıyorum ), ve ile . Sonra olana kadar ikiye . Son olarak, yinelemeli aralığını iki eşit parçaya böler uzunluğu daha kısa olan kadar ve orta nokta tatmin .
ECDF senin uyan benim seçimler için yeterli iyi ve ve makul hızlı. Bunu basit ikiye ayırma yerine Newton tipi bir optimizasyon kullanarak hızlandırabilirsiniz.
aa <- 2
bb <- 1
pp <- 0.1
cdf <- function(x) 1-exp(-aa*x-bb*x^(pp+1)/(pp+1))
simulate <- function(prob,epsilon=1e-5) {
left <- 0
right <- 1
while ( cdf(right) < prob ) right <- 2*right
while ( right-left>epsilon ) {
middle <- mean(c(left,right))
value_middle <- cdf(middle)
if ( value_middle < prob ) left <- middle else right <- middle
}
mean(c(left,right))
}
set.seed(1)
results <- Vectorize(simulate,"prob")(runif(10000))
hist(results)
xx <- seq(0,max(results),by=.01)
plot(ecdf(results))
lines(xx,cdf(xx),col="red")
Kabul etme-reddetme yoluyla doğrudan çözümleme durumunda biraz kıvrıktır. İlk olarak, basit bir farklılaşma dağılımın
İkinci olarak,
üst var
Üçüncüsü, ikinci terimi göz önünde bulundurarak değişkenini alın , yani, . Sonra
, değişken değişiminin Jacobian'ıdır. Eğer
Kabul et reddetme algoritmasının R oluşturması
simuF <- function(a,b,p){
reepeat=TRUE
while (reepeat){
if (runif(1)<.5) x=rexp(1,a) else
x=rexp(1,b/(p+1))^(1/(p+1))
reepeat=(runif(1)>(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
(a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1))))}
return(x)}
ve bir n-numunesi için:
simuF <- function(n,a,b,p){
sampl=NULL
while (length(sampl)<n){
x=u=sample(0:1,n,rep=TRUE)
x[u==0]=rexp(sum(u==0),b/(p+1))^(1/(p+1))
x[u==1]=rexp(sum(u==1),a)
sampl=c(sampl,x[runif(n)<(a+b*x^p)*exp(-a*x-b*x^(p+1)/(p+1))/
(a*exp(-a*x)+b*x^p*exp(-b*x^(p+1)/(p+1)))])
}
return(sampl[1:n])}
A = 1, b = 2, p = 3 için bir örnek: