【问题标题】:How to model a mixture of 3 Normals in PyMC?如何在 PyMC 中模拟 3 个法线的混合?
【发布时间】:2013-09-30 00:41:03
【问题描述】:

a question on CrossValidated 介绍了如何使用 PyMC 将两个正态分布拟合到数据中。 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,:]

【问题讨论】:

    标签: pymc mixture-model


    【解决方案1】:

    有一个mc.Categorical 对象可以做到这一点。

    p =  [0.2, 0.3, .5]
    t = mc.Categorical('test', p )
    t.random()
    #array(2, dtype=int32)
    

    它返回一个介于 0 和 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]
    

    【讨论】:

    • 谢谢。我想到了分类和狄利克雷,让我感到困惑的是在return ber*mean1 + (1-ber)*mean2 的行中放什么。我用提案更新了问题,你能告诉我这是否是正确的方法吗?
    • 好吧,这确实有帮助。我在您的帮助下添加了一个完整的代码示例,但它仍然没有按照应有的方式收敛。
    • 忽略我最后的评论,我认为实现仍然是错误的,但事实证明它是采样。拟合上面的代码,非常感谢! :)
    猜你喜欢
    • 2014-07-10
    • 2013-10-07
    • 2014-01-10
    • 2015-11-24
    • 1970-01-01
    • 2017-10-23
    • 2014-08-19
    • 2019-07-02
    • 2014-07-26
    相关资源
    最近更新 更多