7

次を使用してシミュレーションを実行するとしますfunction

fn1 <- function(N) {
  res <- c()
  for (i in 1:N) {
    x <- rnorm(2)
    res <- c(res, x[2]-x[1])
  }
  res
}

非常に大きいN場合、計算がハングしているように見えます。これを行うためのより良い方法はありますか?

(インスピレーション:https ://stat.ethz.ch/pipermail/r-help/2008-February/155591.html )

4

5 に答える 5

9

ループの効率は、データのベクトル全体をループするのではなく、基本的に一度に処理する適用関数を使用することで、Rで大幅に向上させることができます。上記のループの場合、各反復中に発生する2つの基本的な操作があります。

# A vector of two random numbers is generated
x <- rnorm( 2 )

# The difference between those numbers is calculated
x[2] - x[1]

この場合、適切な関数はですsapply()sapply()loopステートメントによって生成されたベクトルなどのオブジェクトのリストを操作し、1:N結果のベクトルを返します。

sapply( 1:N, function( i ){ x <- rnorm(2); return( x[2] - x[1] ) } )

インデックス値iは関数呼び出し中に使用可能であり、との間の値を連続して1取得することに注意してくださいN。ただし、この場合は必要ありません。

applyどこで使用できるかを認識する習慣を身につけることforは、非常に貴重なスキルです。並列計算用の多くのRライブラリは、apply関数を介したプラグアンドプレイの並列化を提供します。多くの場合、を使用すると、コードのリファクタリングをapply行わずに、マルチコアシステムでパフォーマンスを大幅に向上させることができます

于 2009-07-23T04:27:32.077 に答える
2

R の for ループは非常に遅いことで有名ですが、ここには別の問題があります。各反復で res に追加するよりも、結果ベクトル res を事前に割り当てた方がはるかに高速です。

以下では、上記のバージョンの速度を、単純に長さ N のベクトル res で始まり、ループ中に i 番目の要素を変更するバージョンと比較できます。

fn1 <- function(N) {
  res <- c()
  for (i in 1:N) {
     x <- rnorm(2)
     res <- c(res,x[2]-x[1])
  }
  res
}
fn2 <- function(N) {
  res <- rep(0,N)
  for (i in 1:N) {
     x <- rnorm(2)
     res[i] <- x[2]-x[1]
  }
  res
}
> N <- 50000
> system.time(res1 <- fn1(N))
   user  system elapsed 
  6.568   0.256   6.826 
> system.time(res2 <- fn2(N))
   user  system elapsed 
  0.452   0.004   0.496 

また、Sharpie が指摘しているように、R 関数apply(またはその関連関数、sapplyおよびlapply) を使用することで、これをわずかに高速化できます。

fn3 <- function(N) {
  sapply( 1:N, function( i ){ x <- rnorm(2); return( x[2] - x[1] ) } )
}
> system.time(res3 <- fn3(N))
   user  system elapsed 
  0.397   0.004   0.397 
于 2009-07-23T04:19:53.713 に答える
2

ループが不要な場合もあります。rnorm は (理論的には) iid サンプルを与えるので、次のようにして同じ結果 ( X-Y X と Y が N(0,1) の場合のサンプリング) が得られます。

res <- rnorm(N)-rnorm(N)
于 2009-07-24T07:31:41.667 に答える
0

おそらく、関数の最も効率的な置き換えは次のようになります。

fn <- function(n) rnorm(N,0,sqrt(2))

これは、iid 正規変量の差をとるよりも 2 倍高速です。ただし、より一般的には、単純なシミュレーションを実行することが目的の場合、ベクトル/配列の事前割り当てとネイティブ関数の呼び出しにより、プロセスが大幅に高速化されます。

統計的推定 (MCMC など) のためにモンテカルロ シミュレーションを実行する場合、R には多数のネイティブ パッケージがあります。一般的な確率的シミュレーションについては、私は R パッケージを認識していませんが、優れた Simpy ( http://simpy.sourceforge.net/ ) を試してみてください。

于 2009-07-27T15:00:44.440 に答える