mots quotidiens. | |
Daichi Mochihashi (持橋大地) daichi <at> ism.ac.jp | by hns, version 2.10-pl1. |
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Neal(2003)のスライスサンプリングはMCMC法の一種で, MH法と異なり, ルベーグ積分のように横に確率密度をスライスして, そこから一様分布でサンプリングすることで, 確率密度全体からの効率的なサンプリングを可能にします。
もし, パラメータの範囲が [st,ed] の範囲と決まっていればスライスサンプリングは簡単で,
ただしこれはパラメータの範囲が [st,ed] で有界な場合で, そうでない場合は使えません。参考にしたコードが, この範囲を手で [0,25] のように書いてあったのですが, それには若干疑問があったので少し考えてみたところ, 実は常に [0,1] の範囲からの スライスサンプリングとして実現できることに気づきました。 後で書くように, この辺の話の専門家であるエジンバラの Iain Murray にメールして 聞いてみたところ, 関連のある話はあるが, そのものはまだ誰も特に言っていない ようです。
基本的なアイデアは, たとえばパラメータが正の実数全て(R+)を範囲として取る場合,
(0,1)->R+への対応付けを考えて, パラメータを実数xではなく, (0,1) の範囲の数 p として表すことです。
たとえば, p∈(0,1)について x = p / (1-p) ととれば, このxは正の実数上をすべて動きます。
逆にxが決まれば, 対応する p は p = x / (1+x) として求まります。
そうすれば (0,1) の範囲の一様分布からサンプリングすれば良いじゃん!
というわけですが, ナイーブにそれをやっても動かない, ということに試してみてから気付きました。理由は簡単で,
∫0∞f(x)dx からサンプリングしているので, 上の変換のヤコビアンが必要, ということです。
上の変換の場合, 計算すると dx/dp = 1/(1-p)^2 なのがわかるので,
dx = 1/(1-p)^2 dp と密度を変換してやれば大丈夫です。
この方法で, p(x) ∝ exp(-x(x-1)(x-2)(x-3.4)) という密度からサンプリングした
ものが一番上の図で, ほぼ完全にもとの確率密度を再現していることがわかります。
ポイントは, 内部的には (0,1) の範囲でサンプリングしている, ということです。
パラメータが実数の場合は, (0,1)に値をとるシグモイド関数 y = 1/(1+exp(-x)) の逆関数を考えると, x = -log(1/p - 1) ととればよいことがわかります。 x = p/(1-p) の場合と合わせて, xとpの対応関係をグラフにしたものがこちら。
x = p/(1-p) | x = -log(1/p - 1) |
p(x)∝exp(-(x-1000)^2/10) | 同左, 拡大図 |
#include "slice.h" double f (double x, void *arg) { return - x * (x - 1) * (x - 2) * (x - 3.4); } { double x = 1; for (i = 0; i < N; i++) { x = slice_sample (x, f, NULL); printf("%.4lf\n", x); } }C++のコードを下に置いておきますので, ご興味のある方はお使い下さい。 この話は考えてみると trivial かも知れませんが, 僕は聞いたことがないので, どこかにノートでまとめてみると良いのかもしれません。 Iain Murrayによると, 関連した話は Skilling の話にあるそうで, 実際にMacKayの ITILAに二進法によるスライスサンプリングの実装の話が書いてあるのですが, そちらは unit interval を前提としたものではなく, ヤコビアンの計算もしていない ようです。ので, 上の方法は一般性がある方法なのではないか, と思っています。
タイトル一覧 |