問題
単純な2ガウス混合母集団のモデルパラメーターを近似します。ベイジアン手法をめぐる誇大宣伝を踏まえ、この問題についてベイジアン推論が従来のフィッティング手法よりも優れたツールであるかどうかを理解したいと思います。
これまでのところ、MCMCはこのおもちゃの例ではパフォーマンスが非常に低くなっていますが、おそらく見落としているだけかもしれません。コードを見てみましょう。
道具
私はpython(2.7)+ scipyスタック、lmfit 0.8およびPyMC 2.3を使用します。
分析を再現するためのノートはここにあります
データを生成する
最初にデータを生成してみましょう:
from scipy.stats import distributions
# Sample parameters
nsamples = 1000
mu1_true = 0.3
mu2_true = 0.55
sig1_true = 0.08
sig2_true = 0.12
a_true = 0.4
# Samples generation
np.random.seed(3) # for repeatability
s1 = distributions.norm.rvs(mu1_true, sig1_true, size=round(a_true*nsamples))
s2 = distributions.norm.rvs(mu2_true, sig2_true, size=round((1-a_true)*nsamples))
samples = np.hstack([s1, s2])
のヒストグラムはsamples
次のようになります。
「広いピーク」の場合、コンポーネントを目で確認するのは困難です。
古典的なアプローチ:ヒストグラムを当てはめる
最初に古典的なアプローチを試してみましょう。lmfitを使用すると、2ピークモデルを簡単に定義できます。
import lmfit
peak1 = lmfit.models.GaussianModel(prefix='p1_')
peak2 = lmfit.models.GaussianModel(prefix='p2_')
model = peak1 + peak2
model.set_param_hint('p1_center', value=0.2, min=-1, max=2)
model.set_param_hint('p2_center', value=0.5, min=-1, max=2)
model.set_param_hint('p1_sigma', value=0.1, min=0.01, max=0.3)
model.set_param_hint('p2_sigma', value=0.1, min=0.01, max=0.3)
model.set_param_hint('p1_amplitude', value=1, min=0.0, max=1)
model.set_param_hint('p2_amplitude', expr='1 - p1_amplitude')
name = '2-gaussians'
最後に、モデルをシンプレックスアルゴリズムで近似します。
fit_res = model.fit(data, x=x_data, method='nelder')
print fit_res.fit_report()
結果は次の画像です(赤い破線はフィットした中心です):
問題が少し難しい場合でも、適切な初期値と制約があれば、モデルはかなり合理的な推定値に収束しました。
ベイジアンアプローチ:MCMC
モデルはPyMCで階層的に定義します。centers
そしてsigmas
2つのセンター及び2つのガウスの2つのシグマを表すハイパーための事前確率分布です。alpha
最初の人口の割合であり、以前の分布はここではベータです。
カテゴリー変数は、2つの母集団から選択します。この変数はデータ(samples
)と同じサイズである必要があると私は理解しています。
最後mu
とtau
(それらが依存正規分布のパラメータを決定する決定論的変数でありcategory
、彼らはランダムに2つの集団のための2つの値の間で切り替えるように可変)。
sigmas = pm.Normal('sigmas', mu=0.1, tau=1000, size=2)
centers = pm.Normal('centers', [0.3, 0.7], [1/(0.1)**2, 1/(0.1)**2], size=2)
#centers = pm.Uniform('centers', 0, 1, size=2)
alpha = pm.Beta('alpha', alpha=2, beta=3)
category = pm.Categorical("category", [alpha, 1 - alpha], size=nsamples)
@pm.deterministic
def mu(category=category, centers=centers):
return centers[category]
@pm.deterministic
def tau(category=category, sigmas=sigmas):
return 1/(sigmas[category]**2)
observations = pm.Normal('samples_model', mu=mu, tau=tau, value=samples, observed=True)
model = pm.Model([observations, mu, tau, category, alpha, sigmas, centers])
次に、MCMCを非常に長い反復回数(私のマシンでは1e5、約60秒)で実行します。
mcmc = pm.MCMC(model)
mcmc.sample(100000, 30000)
また、ガウシアンの中心も収束しません。例えば:
ここで何が起こっているのでしょうか?私は何か間違ったことをしていますか、それともMCMCはこの問題に適していませんか?
MCMCメソッドは遅くなることは理解していますが、自明なヒストグラムフィットは母集団の解決において非常に優れているようです。
proposal_distribution
とproposal_sd
その理由を簡単に説明できますPrior
か?