使用PyMC拟合3个法线:简单数据的错误收敛

时间:2013-10-01 11:17:12

标签: mcmc pymc mixture-model

我编写了一个PyMC模型,用于将3个法线拟合到数据中(类似于this question中的那个)。

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)采样的方法。 Data from 3 Normal distributions 我期望的结果的例子。这种情况发生在10例中的2例中。 MCMC trace producing a good fit 10个案例中有6个发生意外结果的示例。这很奇怪,因为在-5,数据中没有峰值所以我不能真正认为采样可能会陷入严重的局部最小值(从(-5,-5)到(-6,-4)应该改善适应性,等等)。 MCMC trace producing a bad fit

(自适应Metropolis)MCMC采样在大多数情况下被卡住的原因是什么?有哪些方法可以改善抽样程序?

所以这些运行会收敛,但并没有真正探索正确的范围。


更新: Using different priors,我在5/10获得了正确的收敛(appx。第一张图片),而在另一张5/10中获得了错误的收集(appx。第二张图片)。基本上,更改的行是下面的行并删除AdaptiveMetropolis步骤方法:

precs = mc.Gamma('precs', alpha=2.5, beta=1, size=n)
means = mc.Normal('means', [-5, 0, 5], 0.0001, size=n)

2 个答案:

答案 0 :(得分:3)

您是否有特殊原因要使用AdaptiveMetropolis?我想,香草MCMC没有用,你有这样的东西:

enter image description here

是的,这不好。我可以提出一些意见。下面我使用了香草MCMC。

  1. 您的means先前差异0.001太大了。这对应于约31(= 1 / sqrt(0.001))的标准偏差,这太小了。你真的强迫你的手段接近0.你想要一个更大的标准。偏离,以帮助探索该地区。我将值减少到0.00001并得到了这个:
  2. enter image description here

    完美。当然,apriori我知道真正的手段是50,0和-50。通常我们不知道这一点,因此将该值设置得非常小是一个好主意。

    2。你真的认为所有法线都排在0,就像你之前的mean建议一样吗? (你将它们的平均值设置为0)这个练习的目的是发现它们不同,所以你的先验应该反映出来。类似的东西:

    means = mc.Normal('means', [-5,0,5], 0.00001, size=n)
    

    更准确地反映了您的真实信念。这实际上也通过向MCMC建议应该的方式来帮助收敛。当然,你必须用你最好的估计来得出这些数字(我天真地选择了-5,0,5)。

答案 1 :(得分:0)

问题是由category变量的接受率低造成的。请参阅answer我给出的类似问题。