一様乱数から正規乱数を生成する(ボックス=ミュラー法)
この記事では ボックス=ミュラー法 というものを紹介します。
Pythonで確認してから、数学的な証明を行います。
証明では前回の記事で紹介した変数変換を使用します。
ボックス=ミュラー法(Box-Muller法)
ボックス=ミュラー法
上の一様分布上の独立な確率変数 [0,1] があるとき、 U_1, U_2 X = \sqrt{-2 \log{U_1}} \cos{2 \pi U_2} \\ Y = \sqrt{-2 \log{U_1}} \sin{2 \pi U_2} とすると
は独立に標準正規分布 X,Y に従う。 {\it N}(0, 1)
簡単に言うと 2つの独立な一様分布から2つの独立な標準正規分布を生成できる というものです。
これがあればもしPythonでnp.random.normal()
が使えなくなってもnp.random.uniform()
さえあれば正規分布に従う乱数を作れるということです。すごいですね!
Pythonで確認してみる
一様分布に上記の変換を施すと本当に正規分布になるのか確認してみましょう。
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
plt.style.use("seaborn")
font_cfg = {"fontsize": 14}
def box_muller(u_1, u_2):
"""ボックス=ミュラー法を適用する関数"""
X = np.sqrt(-2 * np.log(u_1)) * np.cos(2 * np.pi * u_2)
Y = np.sqrt(-2 * np.log(u_1)) * np.sin(2 * np.pi * u_2)
return X, Y
# 2つの独立な[0, 1]上の一様乱数を生成
U_1, U_2 = np.random.uniform(0, 1, (2, 100_000))
# ボックス=ミュラー法を適用
X, Y = box_muller(U_1, U_2)
# Plot
fig, axes = plt.subplots(2, 2, figsize=(9, 7), dpi=90)
# ヒストグラムの描画
for ax, d, s in zip(axes.ravel(), [U_1, U_2, X, Y], ["U_1", "U_2", "X", "Y"]):
ax.hist(d, bins=100, density=True)
ax.set_title(f"${s}$", **font_cfg)
# 一様分布と標準正規分布の確率密度の描画
arr = np.linspace(0, 1)
for ax in axes[0, :]:
ax.plot(arr, stats.uniform.pdf(arr), c="r", label="$U(0, 1)$")
ax.set_ylim(0, 1.3)
ax.legend(**font_cfg)
arr = np.linspace(-4, 4)
for ax in axes[1, :]:
ax.plot(arr, stats.norm.pdf(arr), c="r", label="$N(0, 1)$")
ax.legend(**font_cfg)
plt.tight_layout()
ここでは確認しませんが
これ、すごいですよね。対数やら三角関数を使うことで一様乱数が正規乱数に早変わりです。
初めて知ったときは驚きました。
Pythonで書くとこれだけの話なのですが、数学的に証明しようとすると少し大変です。
以降で実際に証明します。
ボックス=ミュラー法の証明
準備
証明に使う道具を簡単に紹介します。
-
2次元確率分布の変数変換
前回記事で紹介した変数変換を使用します。
確率変数 の同時確率(密度)関数を\ (X, Y) とし、\ f_{X,Y}(x, y)
と表されるとき、X = h_1(S, T), Y = h_2(S, T)
の同時確率(密度)関数(S, T) はf_{S,T}(s, t) f_{S,T}(s,t) = f_{X,Y}(h_1(s, t), h_2(s, t)) |J(s,t)| となる、というものです。
詳しくは前回の記事をご覧ください。
-
一様分布の確率密度関数
上の一様分布の確率密度関数は下記です。[a,b] f_x(x) = \begin{cases} 1 / (b - a) & (a \leq x \leq b) \\ 0 & ({\it otherwise}) \end{cases} 今回は
上の一様分布を変数変換していきます。[0, 1]
-
標準正規分布の確率密度関数
標準正規分布の確率密度関数は下記です。f_x(x) = \frac{1}{\sqrt{2 \pi}} e^{-x^2 / 2} 変数変換の結果、この式を2つ掛けたものが得られれば証明となります。
計算
問題を確認します。
上の一様分布からの独立な確率変数 [0,1] があるとき、 U_1, U_2 X = \sqrt{-2 \log{U_1}} \cos{2 \pi U_2} \\ Y = \sqrt{-2 \log{U_1}} \sin{2 \pi U_2} なる変数を施すと
は独立に標準正規分布 X,Y に従うことを示せ。 {\it N}(0, 1)
計算しやすくするために次のように2段階の変数変換に分けて考えます。
-
ステップ1
をU_1,U_2 r = \sqrt{-2 \log{U_1}} \\ \theta = 2 \pi U_2 と変数変換する。
-
ステップ2
先に求めた をr,\theta X = r \cos{\theta} \\ Y = r \sin{\theta} と変数変換する。
ステップ1
を U_1,U_2 r = \sqrt{-2 \log{U_1}} \\ \theta = 2 \pi U_2 と変数変換する。
となります。よってヤコビアンは
となります。これを変数変換の公式に入れて
となります。
(ややこしいですがヤコビアンの絶対値が残っただけです。)
これは
に従います。(
info:
は 0 \leq r \leq \infty より、 f_{U_1}(e^{-r^2 /2}) \neq 0 となるので、 0 \leq re^{-r^2 /2} \leq 1
これを変形することで得られます。
同様にしても得られます。 0 \leq x \leq 2\pi
ステップ2
ステップ1で得られた
先に求めた
を r,\theta X = r \cos{\theta} \\ Y = r \sin{\theta} と変数変換する。
まず、上の式を
より
です。
より
となります。
次に
となります。
最後に変数変換の公式にこれらを代入すると
となり、2つの標準正規分布のかけ算が得られました。
以上で
まとめ
この記事ではボックス=ミュラー法をPythonで確認し、数学的な証明も行いました。
統計検定1級取得のため勉強をしている中で出てきて面白かったことと、同じような勉強をしている方の参考になればと思い記事を書きました。
ちなみに統計検定1級の参考書としてよく使用される「現代数理統計学の基礎」の4章 演習問題 問8 もこのボックス=ミュラー法の証明です。
おまけ
「ステップ1」の計算の結果、
に従うことが確認できました。
前述のように、
一方、
つまり
となります。
なので、ボックス=ミュラー法は下記のような変換を行っていると解釈できます。
- 2つの独立な
上の一様分布から、指数分布と[0,1] 上の一様分布を生成する。[0,2\pi] - 指数分布の平方根と
上の一様分布から2つの独立な標準正規分布を生成する。[0,2\pi]
Discussion