正規分布をシミュレートするための逆CDF法に対するBox-Mullerの利点は?


15

一様変数のセットから正規分布をシミュレートするには、いくつかの手法があります。

  1. ボックスミュラーアルゴリズム 1つのサンプル二つの独立した均一に変量した、(0,1):を介して二つの独立した標準正規分布に変換し

    Z0=2lnU1cos(2πU0)Z1=2lnU1sin(2πU0)
  2. CDF法。通常の累積分布関数を均一変量と同等にすることができます: F Z = UでZ = F 1U を導きます (F(Z))

    F(Z)=U
    Z=F1(U)

私の質問は次のとおりです。どちらが計算的に効率的ですか?私は後者の方法だと思うでしょう-しかし、私が読んだ論文のほとんどはBox-Mullerを使用しています-なぜですか?

追加情報:

通常のCDFの逆数は次のように認識され、与えられます

F1(Z)=2erf1(2Z1),Z(0,1).

したがって、

Z=F1(U)=2erf1(2U1),U(0,1).

1
通常のcdfの逆は何ですか?元のCDFが区分的線形関数で近似される場合にのみ、分析的に計算できません。
アルテムソボレフ

この2つは密接に関連していませんか?Box Mullerは、2変量生成の特定のケースだと思います。
ttnphns

こんにちはBarmaley、上記の情報を追加しました。逆CDFには式がありますが、は計算的に計算する必要があります。そのため、ボックスミュラーが好ましいのでしょうか。私が想定し ERF 1は、参照テーブルに計算されるの値のような多くの余弦ていますか?したがって、それほど計算的に高価ではありませんか?私は間違っているかもしれません。erf1erf1sincosine
-user2350366

2
正弦および余弦のないBox-Mullerのバージョンがあります。
西安

2
@Dilipコンピュータグラフィックスなどの非常に低精度のアプリケーションでは、適切なルックアップテーブルを使用してサインとコサインを最適化できます。ただし、統計アプリケーションでは、このような最適化は使用されません。最終的には、logsqrtよりも実際に計算するのは難しくありませんが、現代のコンピューティングシステムでは、trig関数を含むexpに関連する基本関数が最適化される傾向があります(coslogはIntelに戻る基本的な命令でした8087チップ!)、erfは利用できないか、より高い(=遅い)レベルでコーディングされています。erf1logsqrtexpcoslog
whuber

回答:


16

純粋に確率論的な観点から見ると、両方のアプローチは正しいため、同等です。アルゴリズムの観点から、比較では精度と計算コストの両方を考慮する必要があります。

Box-Mullerは均一な発電機に依存しており、この均一な発電機とほぼ同じコストです。私のコメントで述べたように、サインやコサインの呼び出しがなくても、対数がなければ逃げることができます。

  • 生成まで、S = U 2 1 + U 2 21
    U1,U2iidU(1,1)
    S=U12+U221
  • Z = √を取るおよびX1=ZU1を定義Z=2log(S)/S
    X1=ZU1, X2=ZU2

一般的な反転アルゴリズムでは、例えばqnorm(runif(N))R の逆正規cdfを呼び出す必要があります。これは、上記よりもコストがかかり、さらに重要なことに、分位関数が適切にコーディングされていない限り、精度の点で失敗する可能性があります。

行われたコメントに従ってくださいwhuber、の比較rnorm(N)qnorm(runif(N))逆CDFの利点である、両方の実行時間で:

> system.time(qnorm(runif(10^8)))
sutilisateur     système      écoulé
 10.137           0.120      10.251 
> system.time(rnorm(10^8))
utilisateur     système      écoulé
 13.417           0.060      13.472` `

そして、尾にフィットするという点で: enter image description here

私のブログでのRadford Nealのコメントに続いてrnorm、R のデフォルトは反転法を使用しているため、上記の比較はシミュレーション法ではなくインターフェースに反映されていることを指摘したいと思います!RNGに関するRドキュメントを引用するには:

‘normal.kind’ can be ‘"Kinderman-Ramage"’, ‘"Buggy
 Kinderman-Ramage"’ (not for ‘set.seed’), ‘"Ahrens-Dieter"’,
 ‘"Box-Muller"’, ‘"Inversion"’ (the default), or ‘"user-supplied"’.
 (For inversion, see the reference in ‘qnorm’.)  The
 Kinderman-Ramage generator used in versions prior to 1.7.1 (now
 called ‘"Buggy"’) had several approximation errors and should only
 be used for reproduction of old results.  The ‘"Box-Muller"’
 generator is stateful as pairs of normals are generated and
 returned sequentially.  The state is reset whenever it is selected
 (even if it is the current normal generator) and when ‘kind’ is
 changed.

3
(1)調子はどうですか logΦ1Φ1 has to be implemented shows otherwise; on most platforms there is an order of magnitude difference in timing.) (2) Box-Mueller is far slower than generating uniform variates on many systems. (3) Your method generates only nonnegative values of X1 and X2. You probably intended for the Ui to be uniform between 1 and 1 rather than 0 and 1.
whuber

2
On my system, running R 3.0.2, the Box-Mueller method (without sine and cosine and coded using rowSums to compute S very quickly) is nevertheless 75% slower than qnorm(runif(N)). When running Mathematica 9, Box-Mueller is ten times faster than the direct InverseCDF[NormalDistribution[], #] &. The point is that the answer depends on the capabilities of the computational platform (as well as one's coding skills). This accords with what you say in the first paragraph but might cause readers to re-interpret the rest of your answer.
whuber

1
I agree, qnorm(runif(N)) is even 20% faster than rnorm(N)
Xi'an

3
+1 for the new information. (Actually, your original post was worth upvoting in its own right.) I would like to re-emphasize, though, that the conclusions can change on a different platform. For instance, I would definitely use Box-Mueller if coding in C, Fortran, or Assembly language, where I would have access to extremely fast implementations of algebraic and elementary transcendental functions which would be much faster than any implementation of Φ1, even an approximate one. Since sin and cos would be so efficient, I would use them rather than rejection sampling, too.
whuber

1
For comparison, using an i7-3740QM @ 2.7Ghz and R 3.12, for the following calls: RNGkind(kind = NULL, normal.kind = 'Inversion');At <- microbenchmark(A <- rnorm(1e5, 0, 1), times = 100L);RNGkind(kind = NULL, normal.kind = 'Box-Muller');Bt <- microbenchmark(B <- rnorm(1e5, 0, 1), times = 100L) I get mean 11.38363 median 11.18718 for inversion and mean 13.00401 median 12.48802 for Box-Muller
Avraham
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.