この分布の乱数をシミュレートする方法を見つける


20

累積分布関数を使用して、分布からの擬似乱数をシミュレートするプログラムをRで作成しようとしています。

F(x)=1exp(axbp+1xp+1),x0

ここa,b>0,p(0,1)

私は逆変換サンプリングを試みましたが、逆は分析的に解決できないようです。この問題の解決策をご提案いただければ幸いです


1
完全な答えを得るのに十分な時間はありませんが、代わりに重要度サンプリングのアルゴリズムを確認できます。
chuse

1
それは私のデータのための合理的な仮定であるので、私は唯一の制約を定め、教科書の練習ではありません
セバスチャン

6
次に、分布を指数関数の完全な力に変えるよる「奇跡的な」正規化に驚かされますが、奇跡は起こります(わずかな確率で)。(p+1)1
西安

回答:


49

この演習には簡単な(そして私が追加できる場合はエレガントな)ソリューションがあります:は2つの生存分布の積のように見えるため、:( 分布は分布です この場合、は指数分布であり、は -thです指数分布のべき乗。1F(x)

(1F(x))=exp{axbp+1xp+1}=exp{ax}1F1(x)exp{bp+1xp+1}1F2(x)
F
X=min{X1,X2}X1F1,X2F2
F1E(a)F21/(p+1)E(b/(p+1))

関連するRコードは、取得するのと同じくらい簡単です

x=pmin(rexp(n,a),rexp(n,b/(p+1))^(1/(p+1))) #simulating an n-sample

そして、それは逆pdfとaccept-rejectの解像度よりも間違いなくはるかに高速です:

> 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 

驚くほど完璧なフィット感:

ここに画像の説明を入力してください


5
本当にクールなソリューション!
セバスチャン

14

逆変換はいつでも数値的に解くことができます。

以下では、非常に簡単な二分法検索を行います。与えられた入力確率(式に既にがあるのでを使用します)について、とからます。次に、までを2倍にします。最後に、その長さがより短く、その中点が満たすまで、間隔を繰り返し二等分します。qqpxL=0xR=1xRF(xR)>q[xL,xR]ϵxMF(xM)q

ECDF はと選択するのに十分に適合し、かなり高速です。単純な二分探索の代わりに、ニュートン型の最適化を使用することで、おそらくこれを高速化できます。Fab

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")

ECDF


10

accept-rejectによる直接解決の場合、多少複雑な問題があります。まず、単純な微分は、分布のpdfが 次に、 上限 3番目に、の2番目の項を考慮して、変数、つまり。その後、 は変数の変化のヤコビアンです。場合

f(x)=(a+bxp)exp{axbp+1xp+1}
f(x)=aeaxebxp+1/(p+1)1+bxpebxp+1/(p+1)eax1
f(x)g(x)=aeax+bxpebxp+1/(p+1)
gξ=xp+1x=ξ1/(p+1)
dxdξ=1p+1ξ1p+11=1p+1ξpp+1
Xの形式の密度を持ちますここで、は正規化定数、の密度は つまり、(i)は指数変量として分布し、(ii)定数は1に等しい。したがって、は、指数分布と指数の乗の均等に重み付けされた混合に等しくなりκbxpebxp+1/(p+1)κΞ=X1/(p+1)
κbξpp+1ebξ/(p+1)1p+1ξpp+1=κbp+1ebξ/(p+1)
ΞE(b/(p+1))κg(x)E(a)1/(p+1)E(b/(p+1))分布、重みを説明するために欠落した乗法定数を法として: との混合物としてシミュレートすることが簡単です。2
f(x)g(x)=2(12aeax+12bxpebxp+1/(p+1))
g

したがって、受け入れ-拒否アルゴリズムのRレンダリングは

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)}

n-サンプルの場合:

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の図です。

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.