我编写了一个 PyMC 模型,用于使用(类似于 this question 中的模型)将 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 个案例中有 2 个发生了这种情况。
10 个案例中有 6 个发生意外结果的示例。这很奇怪,因为在 -5 上,数据中没有峰值,所以我不能真正确定采样可能陷入困境的严重局部最小值(从 (-5,-5) 到 (-6,-4))应该提高拟合,等等)。
在大多数情况下(自适应大都会)MCMC 采样卡住的原因可能是什么?有什么可能的方法来改进它没有的采样程序?
所以运行确实收敛,但没有真正探索正确的范围。
更新: Using different priors ,我在 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)
最佳答案
您有什么特别的理由想要使用 AdaptiveMetropolis
吗?我想 Vanilla MCMC
不起作用,你得到了这样的东西:
是的,那不好。我可以提出几点意见。下面我使用了 Vanilla MCMC。
means
先验方差 0.001
太大。这对应于大约 31 ( = 1/sqrt(0.001) ) 的标准偏差,这太小了。你真的在强制你的手段接近 0。你想要一个更大的标准。偏差以帮助探索该地区。我将值降低到 0.00001 并得到了这个:完美的。当然,先验我知道真正的平均值是 50,0 和 -50。通常我们不知道这一点,因此将该值设置得非常小总是一个好主意。
2. 你真的认为所有的法线都在 0 处,就像你之前的
mean
建议的那样吗? (您将所有这些的均值设置为 0)本练习的重点是发现它们不同,因此您的先验应该反射(reflect)这一点。就像是:means = mc.Normal('means', [-5,0,5], 0.00001, size=n)
更准确地反射(reflect)您的真实信念。这实际上还通过向 MCMC 建议手段应该在哪里来帮助收敛。当然,您必须使用最佳估计来得出这些数字(我在这里天真地选择了 -5,0,5)。
关于mcmc - 使用 PyMC : wrong convergence on simple data 拟合 3 个法线,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19114790/