Mímisbrunnr知恵の泉

← シミュレーション 一覧

🎓 レベル:標準 | 重要度:B(推奨)

📎 前提:逆関数法 | 関連:代表的分布の生成(正規・指数・ポアソン)

要点(BLUF)

1. 変数変換法

逆関数法(逆関数法)が F1F^{-1} を必要としたのに対し、変数変換法は「ある分布のサンプルを関数 hh で写すと別の分布になる」性質を直接使います。Y=h(X)Y = h(X) の分布は、XX の密度と hh のヤコビアンから決まります(多次元なら detJ|\det J|)。

代表がBox–Muller 法です。標準正規分布は CDF の逆が初等関数で書けないので逆関数法が使えません。そこで、独立な2つの一様乱数 U1,U2U(0,1)U_1, U_2 \sim \mathcal{U}(0,1) から、独立な2つの標準正規 Z0,Z1Z_0, Z_1 を作ります。

Z0=2lnU1cos(2πU2),Z1=2lnU1sin(2πU2)Z_0 = \sqrt{-2\ln U_1}\,\cos(2\pi U_2), \qquad Z_1 = \sqrt{-2\ln U_1}\,\sin(2\pi U_2)

なぜ正規になるか(極座標の直観):2次元標準正規 (Z0,Z1)(Z_0, Z_1) を極座標 (R,Θ)(R, \Theta) で見ると、角度 Θ\Theta[0,2π)[0, 2\pi) 上の一様分布、半径の2乗 R2R^2 は平均2の指数分布(自由度2のカイ二乗)になります。だから Θ=2πU2\Theta = 2\pi U_2R=2lnU1R = \sqrt{-2\ln U_1}(指数分布を逆関数法で作る)とすれば、(RcosΘ,RsinΘ)(R\cos\Theta, R\sin\Theta) が2次元標準正規になる——これが Box–Muller の中身です。

import numpy as np

# 乱数シードを固定
rng = np.random.default_rng(5)

n = 500_000
u1 = rng.random(n)
u2 = rng.random(n)
radius = np.sqrt(-2 * np.log(u1))      # 半径 R
z0 = radius * np.cos(2 * np.pi * u2)   # 標準正規 その1
z1 = radius * np.sin(2 * np.pi * u2)   # 標準正規 その2
z = np.concatenate([z0, z1])

print(f"Box-Muller 平均 = {z.mean():.4f}  (理論 0)")
print(f"Box-Muller 標準偏差 = {z.std():.4f}  (理論 1)")
print(f"z0 と z1 の相関 = {np.corrcoef(z0, z1)[0,1]:.4f}  (理論 0)")

出力:

Box-Muller 平均 = -0.0007  (理論 0)
Box-Muller 標準偏差 = 0.9994  (理論 1)
z0 と z1 の相関 = 0.0020  (理論 0)

出力の意味:たった2つの一様乱数から、平均 0・標準偏差 1 の標準正規が2系列ぶん生成でき、しかも2系列は無相関(相関 0.002)。逆関数が書けない正規分布を、極座標変換という変数変換で見事に回避しています。一般の正規 N(μ,σ2)\mathcal{N}(\mu, \sigma^2)μ+σZ\mu + \sigma Z でずらせます。

2. 合成法(混合分布)

合成法は、目的分布が**混合(mixture)**の形

f(x)=kwkfk(x),wk0, kwk=1f(x) = \sum_{k} w_k\, f_k(x), \qquad w_k \ge 0,\ \sum_k w_k = 1

で書けるときに使います。手順は2段:(1) 重み wkw_k に従って成分 kk を選び、(2) 選んだ成分 fkf_k からサンプルする。各成分が引きやすければ、複雑な混合分布も簡単に生成できます。

import numpy as np

# 乱数シードを固定
rng = np.random.default_rng(8)

# 0.3*N(-2,0.5^2) + 0.7*N(3,1^2) の混合
n = 400_000
w = np.array([0.3, 0.7])
mu = np.array([-2.0, 3.0])
sd = np.array([0.5, 1.0])

comp = rng.choice(2, size=n, p=w)          # 成分を重みで選ぶ
x = rng.normal(mu[comp], sd[comp])         # 選んだ成分から生成

theory_mean = (w * mu).sum()
print(f"混合分布の平均(シミュ) = {x.mean():.4f}")
print(f"混合分布の平均(理論)   = {theory_mean:.4f}")
print(f"成分1の割合(シミュ) = {(comp==0).mean():.4f}  (目標 0.3)")

出力:

混合分布の平均(シミュ) = 1.5021
混合分布の平均(理論)   = 1.5000
成分1の割合(シミュ) = 0.2998  (目標 0.3)

出力の意味:混合分布の平均 0.3(2)+0.73=1.50.3\cdot(-2) + 0.7\cdot 3 = 1.5 がシミュ 1.5021 と一致。成分1が選ばれた割合も 0.2998 で目標 0.3 どおり。合成法は「複雑な分布を、単純な分布の重み付き選択に分解する」発想で、後の条件付き分布からの生成とも通じます。

3. 他手法との関係

数式の直観的意味

変数変換法は「確率を保ったまま、座標を測り直す」操作です。Box–Muller なら、平面上の正規分布を「角度(一様)×半径(指数)」という回しやすい座標に置き換え、その座標を一様・指数として作ってから直交座標に戻す。合成法は「全体の確率の山を、いくつかの小山に分け、まずどの小山かをサイコロで決めてから、その小山の中で引く」操作。どちらも「難しい分布を、作りやすい部品の組み合わせに翻訳する」という乱数生成の共通戦略の現れです。

⚠️ よくある誤解・落とし穴

対応シミュレーション参照

本文の Box–Muller(default_rng(5))と混合分布の合成法(default_rng(8))。

関連ノート