2

私はここで、C++ プログラムからStanルーチンを呼び出すことが可能である (そして私は簡単に解釈した) ことを読みました。

C++ でコーディングした複雑な対数尤度関数がいくつかありますが、Stan 言語を使用してそれらをコーディングする方法が本当にわかりません。既に C++ でコーディングした対数尤度関数を使用して、Stan でモンテカルロ ルーチンを呼び出すことは可能ですか? もしそうなら、これの例はありますか?

これは非常に自然なことのように思えますが、これを行う方法に関する例や指針が見つかりません。

4

2 に答える 2

2

あなたの質問は、リンク先の質問とは少し異なると思います。彼は完全な Stan プログラムを持っていて、それを C++ から駆動したいと考えていましたが、対数尤度を評価するために外部 C++ 関数を呼び出すことで、Stan プログラムの作成を回避できるかどうか尋ねています。ただし、Stan が処理できる形式でデータを渡したり、不明なパラメーター (およびそのサポート) を Stan に宣言したりする必要があるため、それではあまり効果がありません。スタン語の学習を回避する (または回避する必要がある)。

しかし、C++ 関数を Stan 言語に公開するのはかなり簡単です。基本的には、my_loglikelihood.hpp ファイルを の下の適切な場所${STAN_HOME}/lib/stan_math_${VERSION}/stan/math/に追加し、そのサブディレクトリ内の math.hpp ファイルに include ステートメントを追加して、${STAN_HOME}/src/stan/lang/function_signatures.h. その時点で、.stan プログラムは次のように単純に見えるかもしれ data { // declare data like y, X, etc. } parameters { // declare parameters like theta } model { // call y ~ my_logliklihood_log(theta, X) } ません。数分以上。Stan 言語は非常に C に似ているため、.stan ファイルを C++ ソース ファイルに簡単に解析できます。これは、回帰コンテキストでの条件付きガウス結果の対数尤度のために私が書いたスタン関数です。 functions { /** * Increments the log-posterior with the logarithm of a multivariate normal * likelihood with a scalar standard deviation for all errors * Equivalent to y ~ normal(intercept + X * beta, sigma) but faster * @param beta vector of coefficients (excluding intercept) * @param b precomputed vector of OLS coefficients (excluding intercept) * @param middle matrix (excluding ones) typically precomputed as crossprod(X) * @param intercept scalar (assuming X is centered) * @param ybar precomputed sample mean of the outcome * @param SSR positive precomputed value of the sum of squared OLS residuals * @param sigma positive value for the standard deviation of the errors * @param N integer equal to the number of observations */ void ll_mvn_ols_lp(vector beta, vector b, matrix middle, real intercept, real ybar, real SSR, real sigma, int N) { increment_log_prob( -0.5 * (quad_form_sym(middle, beta - b) + N * square(intercept - ybar) + SSR) / square(sigma) - # 0.91... is log(sqrt(2 * pi())) N * (log(sigma) + 0.91893853320467267) ); } } これは基本的に、C 構文である可能性があるものを Stan 言語の関数の本体にダンプしただけmodelで、.stan プログラムのブロックで呼び出すことができます。

要するに、C++ 関数を Stan 関数として書き直すのがおそらく最も簡単だと思います。ただし、対数尤度には、対応するスタン構文が現在存在しないエキゾチックなものが含まれている可能性があります。その場合、その C++ 関数を Stan 言語に公開し、理想的には stan-dev の下の GitHub の math および stan リポジトリにプル リクエストを作成して、他の人がそれを使用できるようにすることにフォールバックできます (ただし、その場合は、次のように記述する必要もあります)単体テスト、ドキュメントなど)。

于 2015-08-07T01:57:53.670 に答える
2

さらに見直して(私の以前の回答を受け入れないことをお勧めします)、これを試すことができます:正しい署名(および解析)を持つブロック内のユーザー定義関数を使用して.stanプログラムを作成しますfunctionsが、基本的には何もしません。このように functions { real foo_log(real[] y, vector beta, matrix X, real sigma) { return not_a_number(); // replace this after parsing to C++ } } data { int<lower=1> N; int<lower=1> K; matrix[N,K] X; real y[N]; } parameters { vector[K] beta; real<lower=0> sigma; } model { y ~ foo(beta, X, sigma); // priors here } 次に、CmdStan を使用してそのモデルをコンパイルします。これにより、中間ステップとして .hpp ファイルが生成されます。の本体内のその .hpp ファイルを編集してfoo_log、テンプレート化された C++ 関数を呼び出し、また、内容が定義されているヘッダー ファイルを #include します。次に、バイナリを再コンパイルして実行します。

それは実際にはうまくいくかもしれませんが、もしあなたがしていることは、ある程度広く役立つのであれば、C++ の内容を貢献していただけると幸いです。

于 2015-08-07T17:21:36.913 に答える