StanのMAP推定の収束判定についてのコードを読む
概要
Stanではoptimizing関数(R)/メソッド(Python)を使うことで尤度関数の最大化を実施することができます。デフォルトではL-BFGSアルゴリズムが使われているのですが、これに対する収束は幾つかのパラメータで制御されています。そのメモ記事です。
もし収束判定についてよく分かっていない場合、勾配を使った数値計算における収束判定については、ネットの記事だと九大の渡部先生が書いたものなんかが良いかと思います。
収束判定のパラメータ
PystanのAPIページによると、次の5つが挙げられています。StanはC++で書かれたコアライブラリを各言語のラッパーから呼び出す形式になっているので、特にRStanやJuliaStanでも、この部分に差はありません。
- tol_obj (float, optional) – For BFGS and LBFGS, default is 1e-12.
- tol_rel_obj (int, optional) – For BFGS and LBFGS, default is 1e4.
- tol_grad (float, optional) – For BFGS and LBFGS, default is 1e-8.
- tol_rel_grad (float, optional) – For BFGS and LBFGS, default is 1e7.
- tol_param (float, optional) – For BFGS and LBFGS, default is 1e-8.
Stanのコード
これらのパラメータがStanのコード中で使われているのは、次の部分となります。
ここでif文の判定に使われているPropertyが設定されているのは、次の部分になります。
ここで出されたシグナルの結果を受けて、次のコードで標準出力に収束判定についてのメッセージが出力されます。
コードより分かること
このコードを読んでみると、利用するパラメータのうち、tol_rel_objとtol_rel_gradが何故かやたら大きな値である理由が分かります。それぞれの値について、計算機イプシロンが掛けられているのです。自分のmacOSの環境ですと、C++のScalar(これはdouble型であるとコード中で定義されています)の計算機イプシロンは2.22045e-16と表示されました。なので、例えばtol_rel_gradの例になりますと、API側で入れる値は1e+7なのですが、実際の判定では2.22045E-13より小さかった場合に収束、と判定されていることが分かります。