重点サンプリング (1)
Pythonによるモンテカルロ法(2014/6/20)のつづき。今回は、重点サンプリング(importance sampling)の実験をしてみたい。重点サンプリングは、PRMLの11章にも出ている。重点サンプリングを使うと期待値のモンテカルロ積分をより効率的に(=少ないサンプル数で高精度に)計算できる。
記事が長くなりそうなので今回はイントロのみということでなぜ重点サンプリングが必要かという前置きだけ書き記しておきたい。
普通のモンテカルロ積分
モンテカルロ積分(2014/7/28)から続く何本かの記事でまとめたけど、下記の期待値の積分をサンプリングによって求めるのがここでの目的。
ここで、 は確率分布、 は任意の関数である。モンテカルロ積分では、確率分布fからm個のサンプル を生成し、上記の期待値の積分を次式で近似する。
このアルゴリズムは、サンプルを確率分布 から生成できるというのが前提になっている。しかし、 からサンプリングできなかったり、からのサンプルを使って近似値を計算すると非常に効率が悪い(=大量のサンプルを生成しないと近似精度が上がらない)ケースがあるというわけ。
効率が非常に悪いケース
たとえば、下の積分を通常のモンテカルロ積分で計算しようとすると非常に効率が悪い。
ここで、 は標準正規分布。上の式を期待値の積分の式に合わせて書き直すと
となる。ここで、I([条件]) は、条件を満たす範囲で1を返し、それ以外で0を返す関数とする。この期待値の積分を通常のモンテカルロ法で求めてみよう。
実行結果は、
scipy.integrate: 2.86651570352e-07 2.86652756236e-07 normal monte carlo integration: 0.0
となる。正しい答えは、2.8665e-07なのに0.0となってしまった。まあほとんど合ってるんだけど(笑)正確には違う。それは図示してみるとよくわかる。
図示してみると、一見、とはほとんど重なりがないので被積分関数 の全区間の積分は0でいいんでない?と思うかもしれないけど、図の丸で囲んだ部分を拡大してみるとちゃんと面積があるのだ!つまり、0ではない。
それでは、通常のモンテカルロ積分で積分が0になってしまう理由を考察してみよう。モンテカルロ積分では、(下の図の青色の正規分布)からサンプル を生成し、そのサンプル を の関数に通してから下式で和を取って積分の近似値を求める。
この際、上の図の黒い矢印の範囲から生成されたサンプル は、 となってしまうため最終的に積分の近似値の和の計算では使われないことになる。結局、積分の近似値の和の計算で実際に意味があるのは、 が0とならない上の図の赤い矢印の範囲のサンプルだけというわけ。
しかし、赤い矢印の範囲のサンプルが生成される確率はとてつもなく低い。なぜかというとサンプルは青色の正規分布に従って生成されるため正規分布の裾野の裾野のまた裾野くらいの赤い範囲のサンプルが生成される確率はほとんど0なのだ。よって、サンプルスクリプトのように サンプル程度生成しただけでは、赤い矢印の範囲のサンプルが生成される可能性はほぼなく、最終的な積分の近似値も0になってしまうというわけ。まあ、Nをものすごーく大きくすれば運良く赤い範囲のサンプルがいくつか生成されて、積分を近似できるようになるかもしれないけど効率はものすごーく悪くなってしまう。
PRMLの重点サンプリング 11.1.4 の節には次のような記述があった。この問題は高次元空間だとより深刻になるようだ。
我々の興味があるような確率分布では、しばしば 空間の比較的小さい領域に大きな確率が集中している。この場合、高次元の問題では、非常に小さな割合のサンプルだけが和に対して大きな寄与をするため、一様サンプリングはとても非効率的である。 が大きな領域、理想的には が大きな領域に入るサンプル点を本当は抽出したいのである。
(注)Rによるモンテカルロ法入門と記号の使い方が違うので混乱しやすい。PRMLでは、確率分布がp(本ブログではf)で任意の関数がf(本ブログではh)になっている。
先の例に当てはめると被積分関数 が他と比べて大きな値をとる5.0から6.0くらいの範囲のサンプルを本当に抽出したいのだが、が標準正規分布だとそれができない!というのが問題になる。
重点サンプリングは、この問題を解決するため欲しい範囲のサンプルを重点的にサンプリングできる重点関数というものを導入しましょうというアイデア。重点サンプリングを使うと上の積分も0にならず、真の値に近い与えが得られる。
長くなったので重点サンプリングの具体的な実装はまた次回!