我编写了一个 PyMC 模型,用于使用(类似于这个问题中的那个)将 3 个法线拟合到数据中。
import numpy as np
import pymc as mc
import matplotlib.pyplot as plt
n = 3
ndata = 500
# simulated data
v = np.random.randint( 0, n, ndata)
data = (v==0)*(10+ 1*np.random.randn(ndata)) \
+ (v==1)*(-10 + 2*np.random.randn(ndata)) \
+ (v==2)*3*np.random.randn(ndata)
# the model
dd = mc.Dirichlet('dd', theta=(1,)*n)
category = mc.Categorical('category', p=dd, size=ndata)
precs = mc.Gamma('precs', alpha=0.1, beta=0.1, size=n)
means = mc.Normal('means', 0, 0.001, size=n)
@mc.deterministic
def mean(category=category, means=means):
return means[category]
@mc.deterministic
def prec(category=category, precs=precs):
return precs[category]
obs = mc.Normal('obs', mean, prec, value=data, observed = True)
model = mc.Model({'dd': dd,
'category': category,
'precs': precs,
'means': means,
'obs': obs})
M = mc.MAP(model)
M.fit()
# mcmc sampling
mcmc = mc.MCMC(model)
mcmc.use_step_method(mc.AdaptiveMetropolis, model.means)
mcmc.use_step_method(mc.AdaptiveMetropolis, model.precs)
mcmc.sample(100000,burn=0,thin=10)
tmeans = mcmc.trace('means').gettrace()
tsd = mcmc.trace('precs').gettrace()**-.5
plt.plot(tmeans)
#plt.errorbar(range(len(tmeans)), tmeans, yerr=tsd)
plt.show()
我从中采样数据的分布明显重叠,但有 3 个明显不同的峰(见下图)。将 3 个法线拟合到此类数据应该是微不足道的,我希望它能够在 99% 的 MCMC 运行中产生我从 (-10, 0, 10) 采样的平均值。
我期望的结果示例。这发生在十分之二的案例中。
10 个案例中有 6 个发生意外结果的示例。这很奇怪,因为在 -5 上,数据中没有峰值,所以我不能真正达到采样可能陷入的严重局部最小值(从 (-5,-5) 到 (-6,-4)应该提高合身性,等等)。
(自适应 Metropolis)MCMC 采样在大多数情况下卡住的原因可能是什么?有哪些可能的方法来改进它没有的抽样程序?
所以运行确实收敛,但并没有真正探索正确的范围。
更新: 使用不同的先验,我在 5/10 中得到正确的收敛(大约第一张图片),在另一个 5/10 中得到错误的收敛(大约第二张图片)。基本上,更改的行是下面的行,并删除了 AdaptiveMetropolis 步骤方法:
precs = mc.Gamma('precs', alpha=2.5, beta=1, size=n)
means = mc.Normal('means', [-5, 0, 5], 0.0001, size=n)