Mic*_*ert 9 mixture-model pymc
CrossValidated上有一个关于如何使用PyMC将两个Normal分布拟合到数据的问题.Cam.Davidson.Pilon的答案是使用伯努利分布将数据分配给两个法线之一:
size = 10
p = Uniform( "p", 0 , 1) #this is the fraction that come from mean1 vs mean2
ber = Bernoulli( "ber", p = p, size = size) # produces 1 with proportion p.
precision = Gamma('precision', alpha=0.1, beta=0.1)
mean1 = Normal( "mean1", 0, 0.001 )
mean2 = Normal( "mean2", 0, 0.001 )
@deterministic
def mean( ber = ber, mean1 = mean1, mean2 = mean2):
    return ber*mean1 + (1-ber)*mean2
现在我的问题是:如何用三个法线做到这一点?
基本上,问题是你不能再使用伯努利分布和1伯努利了.但那怎么办呢?
编辑:根据CDP的建议,我写了以下代码:
import numpy as np
import pymc as mc
n = 3
ndata = 500
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]
v = np.random.randint( 0, n, ndata)
data = (v==0)*(50+ np.random.randn(ndata)) \
       + (v==1)*(-50 + np.random.randn(ndata)) \
       + (v==2)*np.random.randn(ndata)
obs = mc.Normal('obs', mean, prec, value=data, observed = True)
model = mc.Model({'dd': dd,
              'category': category,
              'precs': precs,
              'means': means,
              'obs': obs})
具有以下采样程序的迹线看起来也很好.解决了!
mcmc = mc.MCMC( model )
mcmc.sample( 50000,0 )
mcmc.trace('means').gettrace()[-1,:]
有一个mc.Categorical对象就是这样做的.
p =  [0.2, 0.3, .5]
t = mc.Categorical('test', p )
t.random()
#array(2, dtype=int32)
它返回0和0之间的int len(p)-1.要对3个法线进行建模,可以创建p一个mc.Dirichlet对象(它接受一个k长度数组作为超参数;将数组中的值设置为相同,将先验概率设置为相等).模型的其余部分几乎相同.
这是我上面建议的模型的概括.
更新:
好的,所以我们可以将它们全部折叠为1,而不是使用不同的方法:
means = Normal( "means", 0, 0.001, size=3 )
...
@mc.deterministic
def mean(categorical=categorical, means = means):
   return means[categorical]