如何在PyMC中建模3个法线的混合? [英] How to model a mixture of 3 Normals in PyMC?

查看:112
本文介绍了如何在PyMC中建模3个法线的混合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于CrossValidated的问题如何使用PyMC将两个正态分布拟合到数据. Cam.Davidson.Pilon 的答案是使用伯努利分布将数据分配给其中一个两个法线:

There is a question on CrossValidated on how to use PyMC to fit two Normal distributions to data. The answer of Cam.Davidson.Pilon was to use a Bernoulli distribution to assign data to one of the two Normals:

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

现在我的问题是:如何使用三个法线?

Now my question is: how to do it with three Normals?

基本上,问题是您不能再使用伯努利分布和1-伯努利.但是那怎么办呢?

Basically, the issue is that you can't use a Bernoulli distribution and 1-Bernoulli anymore. But how to do it then?

编辑:在CDP的建议下,我编写了以下代码:

edit: With the CDP's suggestion, I wrote the following code:

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})

具有以下采样过程的迹线也看起来不错.解决了!

The traces with the following sampling procedure look good as well. Solved!

mcmc = mc.MCMC( model )
mcmc.sample( 50000,0 )
mcmc.trace('means').gettrace()[-1,:]

推荐答案

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

there is a mc.Categorical object that does just this.

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

它返回一个介于0和len(p)-1之间的int.要为3个法线建模,请使pmc.Dirichlet对象(它接受k长度数组作为超参数;将数组中的值设置为相同将先验概率设置为相等).该模型的其余部分几乎相同.

It returns an int between 0 and len(p)-1. To model the 3 Normals, you make p a mc.Dirichlet object (it accepts a k length array as the hyperparameters; setting the values in the array to be the same is setting the prior probabilities to be equal). The rest of the model is nearly identical.

这是我上面建议的模型的概括.

This is a generalization of the model I suggested above.

更新:

好吧,所以我们可以采用多种方法将它们全部折叠为1:

Okay, so instead of having different means, we can collapse them all into 1:

means = Normal( "means", 0, 0.001, size=3 )

...

@mc.deterministic
def mean(categorical=categorical, means = means):
   return means[categorical]

这篇关于如何在PyMC中建模3个法线的混合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆