はじめに
ベイズ推定では、事後分布 \(p(\theta | D)\) からのサンプリングが中心的な課題です。しかし、多くの場合この分布は解析的に扱えず、直接サンプリングもできません。
**マルコフ連鎖モンテカルロ(MCMC)**法は、目標分布を定常分布とするマルコフ連鎖を構築し、そこからサンプルを生成する手法です。十分長い連鎖を走らせることで、事後分布からの近似サンプルが得られます。
マルコフ連鎖の基礎
マルコフ連鎖は、現在の状態のみに依存して次の状態が決まる確率過程です。
\[P(X_{t+1} | X_1, \ldots, X_t) = P(X_{t+1} | X_t) \tag{1}\]MCMCの目的は、目標分布 \(\pi(\theta)\) を定常分布とするマルコフ連鎖を設計することです。定常分布とは、連鎖が十分長く走った後に収束する分布であり、**詳細釣り合い条件(detailed balance)**を満たす遷移確率 \(T(\theta' | \theta)\) を設計すれば保証されます。
\[\pi(\theta) T(\theta' | \theta) = \pi(\theta') T(\theta | \theta') \tag{2}\]メトロポリス・ヘイスティングス法
アルゴリズム
- 初期値 \(\theta_0\) を設定
- 提案分布 \(q(\theta' | \theta_t)\) から候補 \(\theta'\) を生成
- 受容確率を計算:
- 確率 \(\alpha\) で \(\theta_{t+1} = \theta'\)、それ以外は \(\theta_{t+1} = \theta_t\)
- ステップ2-4を繰り返す
提案分布が対称(\(q(\theta' | \theta) = q(\theta | \theta')\))の場合、受容確率は次のように簡略化されます(メトロポリス法)。
\[\alpha = \min\left(1, \frac{\pi(\theta')}{\pi(\theta_t)}\right) \tag{4}\]重要な性質として、\(\pi(\theta)\) の正規化定数を知る必要がありません。ベイズ推定では \(p(\theta | D) \propto p(D | \theta) p(\theta)\) の非正規化密度のみで計算可能です。
Python実装
正規分布の事後分布からサンプリングする例です。
import numpy as np
import matplotlib.pyplot as plt
def metropolis_hastings(log_target, initial, n_samples, proposal_std=1.0):
"""メトロポリス・ヘイスティングス法"""
samples = [initial]
current = initial
accepted = 0
for _ in range(n_samples):
# 提案分布(ガウスランダムウォーク)
proposal = current + np.random.normal(0, proposal_std)
# 対数受容確率
log_alpha = log_target(proposal) - log_target(current)
# 受容/棄却
if np.log(np.random.random()) < log_alpha:
current = proposal
accepted += 1
samples.append(current)
acceptance_rate = accepted / n_samples
return np.array(samples), acceptance_rate
# --- 目標分布: 混合ガウス分布 ---
def log_target(x):
"""対数目標密度: 0.3*N(-2,1) + 0.7*N(3,0.5)"""
from scipy.special import logsumexp
log_p1 = np.log(0.3) - 0.5 * (x + 2)**2
log_p2 = np.log(0.7) - (x - 3)**2 # sigma=0.5 → 1/(2*0.25)=2
return logsumexp([log_p1, log_p2])
# --- 実行 ---
np.random.seed(42)
samples, acc_rate = metropolis_hastings(log_target, initial=0.0,
n_samples=50000, proposal_std=1.5)
print(f"受容率: {acc_rate:.3f}")
# バーンイン期間を除去
burn_in = 5000
samples = samples[burn_in:]
# --- 可視化 ---
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# トレースプロット
axes[0].plot(samples[:2000], alpha=0.5, linewidth=0.5)
axes[0].set_xlabel('Iteration')
axes[0].set_ylabel('Sample value')
axes[0].set_title('Trace Plot')
axes[0].grid(True, alpha=0.3)
# ヒストグラム vs 真の分布
x = np.linspace(-6, 6, 200)
true_pdf = 0.3 * np.exp(-0.5 * (x + 2)**2) / np.sqrt(2*np.pi) + \
0.7 * np.exp(-0.5 * ((x - 3)/0.5)**2) / (0.5 * np.sqrt(2*np.pi))
axes[1].hist(samples, bins=100, density=True, alpha=0.5, label='MCMC samples')
axes[1].plot(x, true_pdf, 'r-', linewidth=2, label='True density')
axes[1].set_xlabel('x')
axes[1].set_ylabel('Density')
axes[1].set_title('Histogram vs True Distribution')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
ギブスサンプリング
多次元の場合、各変数を条件付き分布から順番にサンプリングする手法です。2変数 \((\theta_1, \theta_2)\) の場合:
- \(\theta_1^{(t+1)} \sim p(\theta_1 | \theta_2^{(t)}, D)\)
- \(\theta_2^{(t+1)} \sim p(\theta_2 | \theta_1^{(t+1)}, D)\)
条件付き分布が既知の場合(共役事前分布など)に特に有効です。メトロポリス・ヘイスティングス法の特殊ケースであり、受容率は常に1です。
実用上の注意点
バーンイン
マルコフ連鎖の初期値の影響を除去するため、最初の数千サンプル(バーンイン期間)を捨てます。
受容率の調整
提案分布の標準偏差が大きすぎると受容率が低下し、小さすぎると探索が遅くなります。最適な受容率は約23.4%(多次元の場合)とされています。
自己相関と間引き
連続するサンプルは相関を持ちます。独立なサンプルが必要な場合は間引き(thinning)を行います。
関連記事
- ベイズ線形回帰の基礎 - MCMCを使わない解析的なベイズ推定を解説しています。
- クロスエントロピー法:モンテカルロ最適化の実践的手法 - モンテカルロ法を最適化に応用したCEMとの関連を理解できます。
- 粒子フィルタのPython実装 - 逐次モンテカルロ法(SMC)であり、MCMCと密接に関連しています。
- ベイズ最適化の基礎とPython実装 - MCMCで推定した事後分布をベイズ最適化に活用できます。
参考文献
- Metropolis, N., et al. (1953). “Equation of State Calculations by Fast Computing Machines”. The Journal of Chemical Physics, 21(6), 1087-1092.
- Hastings, W. K. (1970). “Monte Carlo Sampling Methods Using Markov Chains and Their Applications”. Biometrika, 57(1), 97-109.
- Gelman, A., et al. (2013). Bayesian Data Analysis (3rd ed.). Chapman and Hall/CRC. Chapters 11-12.