10

Metropolis-Hastings アルゴリズムを使用して、C または C++ コードを R コードに組み込み、MCMC プログラムを高速化する方法についてアドバイスを求めています。私は MCMC アプローチを使用して、さまざまな共変量が与えられた場合に、個人が第三者 (裁判官) によって社会的地位階層の特定のランクに割り当てられる可能性をモデル化しています。各個人の社会的地位の評価に基づいて、個人のグループ (4 つの村にまたがる約 80 人) をランク付けします。したがって、各裁判官に対して、階層内の各個人の位置の判断に対応するランクのベクトルがあります。

これをモデル化するために、ランクを割り当てるとき、裁判官は個人の効用の潜在的な尺度uの相対値に基づいて決定を下していると仮定します。これを考えると、特定の裁判官によって生成されたランクのベクトルrは、ランク付けされた個人の有用性を表す観測されていないベクトルuの関数であると仮定できます。ここで、 uの値がk 番目に高い個人は、 k番目のランクが割り当てられます。関心のある共変量を使用してuを多変量正規分布変数としてモデル化し、モデルによって生成されたuの分布を考慮して、観測された順位の尤度を決定します。

最大で 5 つの共変量の効果を推定することに加えて、審査員と項目の間の分散を表すハイパーパラメーターも推定します。したがって、チェーンの反復ごとに、多変量正規密度を約 8 ~ 10 倍推定します。その結果、5000 回の反復には最大 14 時間かかる場合があります。明らかに、5000 回以上実行する必要があるため、プロセスを劇的に高速化する手段が必要です。これを踏まえて、私の質問は次のとおりです。

(i) C または C++ でチェーンのすべてではないにしても、一部を実行することで最高の速度向上が得られると仮定するのは正しいですか?

(ii) 質問 1 の答えが「はい」の場合、どうすればよいでしょうか? たとえば、すべての R 関数を保持したまま、単純に C または C++ でループを実行する方法はありますか?つまり、C から R 関数を呼び出してからループを実行できますか?

(iii) 私が本当に知りたいのは、C または C++ コードを自分のプログラムに組み込むための最善の方法だと思います。

4

6 に答える 6

18

最初に、遅い R バージョンが正しいことを確認してください。R コードのデバッグは、C コードのデバッグよりも簡単かもしれません。やった?偉大な。これで、比較できる正しいコードが得られました。

次に、何が時間を取っているかを調べます。Rprof を使用してコードを実行し、何が時間を取っているかを確認します。一度継承したコードに対してこれを行ったところ、t() 関数で 90% の時間を費やしていることがわかりました。これは、プログラマーが行列 A を持っていて、無数の場所で t(A) を実行していたためです。最初に 1 つの tA=t(A) を実行し、すべての t(A) を tA に置き換えました。労力をかけずに大幅なスピードアップ。最初にコードをプロファイリングします。

これで、ボトルネックが見つかりました。Rで高速化できるコードですか?ベクトル化できるのはループですか? それを行う。ゴールド スタンダードの正しいコードに対して結果を確認します。いつも。はい、乱数に依存するアルゴリズムを比較するのは難しいことを知っているので、シードを同じに設定して、もう一度やり直してください。

まだ十分に速くありませんか?さて、おそらく、C、C++、または Fortran で、または本当にやりたい場合は GPU コードで、パーツ (一般に、最も低いレベルのパーツ、およびプロファイリングに最も時間がかかったパーツ) を書き直す必要があるかもしれません。

繰り返しますが、コードが正しい R コードと同じ答えを出していることを実際に確認してください。本当にチェックしてください。この段階で、一般的な方法のどこかにバグが見つかった場合は、正しい R コードであると思われるものと最新バージョンでそれらを修正し、すべてのテストを再実行します。多くの自動テストを作成します。それらを頻繁に実行します。

コードのリファクタリングについて読んでください。これをリファクタリングと呼ぶのは、コードを書き直すことを上司に伝えると、上司は「なぜ最初に正しく記述しなかったのか?」と言うからです。コードをリファクタリングしていると言うと、彼らは「うーん... 良い」と言うでしょう。これは実際に起こります。

他の人が言ったように、Rcpp は勝利でできています。

于 2012-02-10T13:11:18.890 に答える
4

R、C++、およびRcppを使用した完全な例は、Darren Wilkinson のブログのこの投稿に触発されたこのブログ投稿で提供されています (彼にはさらにフォローアップがあります)。この例は、ディレクトリ内のRcppの最近のリリースにも含まれており、すぐに使用できるはずです。 RcppGibbs

于 2012-02-10T17:35:43.230 に答える
3

このトピックについて正確に説明しているブログ投稿があります。

http://darrenjw.wordpress.com/2011/07/31/faster-gibbs-sampling-mcmc-from-within-r/

(この投稿は、Dirk が参照している私の投稿よりも関連性があります)。

于 2012-02-10T18:39:15.227 に答える
2

C または C++ を統合する現在の最良の方法は、Dirk Eddelbuettel の Rcpp パッケージだと思います。彼のウェブサイトで多くの情報を見つけることができます。また、YouTubeで公開されている Google での興味深い講演もあります。

于 2012-02-10T12:16:05.177 に答える
2

このプロジェクトをチェックしてください: https://github.com/armstrtw/rcppbugs

また、R/Fin 2012 トークへのリンクは次のとおりです: https://github.com/downloads/armstrtw/rcppbugs/rcppbugs.pdf

于 2012-05-24T13:20:50.413 に答える
0

MCMC サンプラーの各ステップをベンチマークし、ボトルネックを特定することをお勧めします。それぞれの完全な条件または MH ステップを関数に入れる場合、R コンパイラ パッケージを使用すると、5% から 10% の速度向上が得られます。次のステップは、RCPP を使用することです。

尤度関数が与えられた MH アルゴリズムを使用して 1 つのドローを生成する汎用の RCPP 関数があれば、本当にいいと思います。

ただし、RCPP では、R 言語しか知らない場合、いくつかのことが難しくなります。非標準のランダム分布 (特に切り捨てられたもの) と配列の使用です。そこでは、C プログラマーのように考える必要があります。

多変量法線は、実際には R の大きな問題です。Dmvnorm は非常に非効率的で遅いです。Dmnorm の方が高速ですが、一部のモデルでは dmvnorm よりも NaN の方が高速です。

どちらも共分散行列の配列を取らないため、多くの場合、コードをベクトル化することは不可能です。ただし、共通の共分散と手段がある限り、ベクトル化することができます。これは、速度を上げるための R っぽい戦略です (そして、C で行うことの反対です)。

于 2012-02-12T01:33:59.567 に答える