一様乱数を用いて、ある確率分布に従う乱数を得る手法の1つ、逆関数法を見ていきます。
逆関数法の直感的説明

イメージは図のとおりです。からサンプリングしたいが、その手段がないとします。
は
の累積分布関数です。したがって、取る値の範囲は
]です。
は区間
]の一様分布とし、いま、
がサンプリングできたとします。ここで、紫の線で示すように
の逆関数
によって
が得られます。そしてこの
は
に従って分布する、というものです。サンプリングしたい関数
から累積分布関数を求め、さらにその逆関数が定まればサンプリングができるはずです。数学的な背景はなくとも直感的にもそんな気はします。確率密度が高いところで累積分布関数の傾きも大きくなるので、よりサンプリングされやすく、逆に確率密度の低いところでは累積分布関数の傾きは小さいのでサンプリングされにくくなります。ちなみに図の
は正規分布ですが、
はフリーハンドで書いているので適当です、、。
証明
比較的簡単です。
区間]の一様分布に従う確率変数を
とします。逆関数によって
が得られるとします。この
が、
を累積分布関数に持つ確率分布に従っていてほしいのです。そこで任意の実数
に対して、
がどのように表せるのかを確認します。
はつまり累積分布関数ですから、これが
であってほしいわけです。さて、
でしたから、
です。

そして、上図より、は
と置き換えられますから、
です。(累積分布関数は単調増加関数のため、大小が入れ替わることはありません)
ここで、が
]の一様分布に従うとき、以下が成り立ちます。
確率変数が
以下の確率は、一様分布なら
です。例えば
とすれば、一様分布が0.5以下を取る確率は0.5ですよね。この関係を用いれば、式(2)の右辺は、
と書けます。以上より、
となり、知りたかった累積分布関数は
であることがわかりました。累積分布関数と確率分布は1対1ですから、つまり
は
を累積分布関数に持つ確率分布に従っているといえます。
サンプリング実験
早速試してみます。サンプリングしたい確率分布をの指数分布とすると、その累積分布関数を求め、
これをについて解けば
です。一様分布からをサンプリングし、式(8)で変換すれば指数分布が求められるということです。試してみたところ、以下のグラフのようになり、確かに指数分布からサンプリングできていることが確認できました。
今回のコードです。
# 逆関数法 import numpy as np import matplotlib.pyplot as plt # サンプル数 N = 1000000 x = np.random.uniform(0, 1, N) y = -np.log(1-x) x2 = np.linspace(0, 5, 100) y2 = np.exp(-x2) plt.hist(y, normed=True, bins=50, alpha=0.5) plt.plot(x2, y2) plt.xlim(0,5) plt.show()