カスタム分布からランダムサンプルを生成する


16

Rを使用してカスタムpdfからランダムサンプルを生成しようとしています。私のpdfは次のとおりです

fバツ(バツ=321バツ20バツ1

均一なサンプルを生成し、それをカスタム分布に変換しようとしました。これを行うには、分布の累積分布関数(Fバツバツ)を見つけ、それを均一なサンプル(あなたは)に設定し、xについて解きバツます。

Fバツバツ=Pr[バツバツ]=0x32(1y2)dy=32(xx33)

上記分布を有するランダムサンプルを生成するために、均一なサンプルを取得u[0,1]とを解くx

32(xx33)=u

私はそれを実装しましたRが、期待した分布が得られません。誰かが私の理解の欠陥を指摘できますか?

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
コーディングの間違いである必要があります。私はRを使用していないので、間違いを正確に言うことはできません-しかし、あなたのソリューションをコーディングしました(常に0と1の間にある3次多項式の中間根を取ることに注意してください)、そしてサンプルと予想される分布との間に良好な一致が得られました。ルートファインダーに問題がありますか?入手しているサンプルの何が問題になっていますか?
-jpillow

私はあなたのコードを試しましたが(これはあまり効率的ではありません)、期待通りの配布を得ました。
アニコ

@jpillowと@Aniko私の間違い。私が使用nsamples <- 1e6したとき、それは良いマッチでした。
アナンド

2
@Anand 1つの方法は、を観察し、観点からを直接計算できるようにすることです。バツ=2アークシンあなたは/3バツあなたは
whuber

回答:


11

あなたのコードが機能することがわかったように見えますが、@ Anikoはその効率を改善できると指摘しました。おそらく、最大の速度向上は、メモリを事前に割り当てることで得られるzので、ループ内でメモリを増やすことはありません。そのような何かz <- rep(NA, nsamples)がトリックを行う必要があります。vapply()明示的なループの代わりに(返される変数の型を指定する)を使用することで、わずかな速度向上が得られる場合があります(適用ファミリに大きなSOの質問があります)。

> 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

また;、各行の最後に必要はありません(MATLAB変換ですか?)。


詳細な回答と指摘をありがとうvapply。私はC/C++非常に長い間コーディングしてきましたが、それが;苦痛の理由です!
アナンド

1
+1 uniroot直接的なソリューションに置き換えると、さらに3桁高速になります。1秒あたり個の変量を取得するのに問題はないはずです。107
whuber
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.