How to model a mixture of 3 Normals in PyMC? -
there a question on crossvalidated on how use pymc fit 2 normal distributions data. answer of cam.davidson.pilon use bernoulli distribution assign data 1 of 2 normals:
size = 10 p = uniform( "p", 0 , 1) #this fraction come mean1 vs mean2 ber = bernoulli( "ber", p = p, size = size) # produces 1 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 question is: how three normals?
basically, issue can't use bernoulli distribution , 1-bernoulli anymore. how then?
edit: cdp's suggestion, wrote following code:
import numpy np import pymc 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 following sampling procedure well. solved!
mcmc = mc.mcmc( model ) mcmc.sample( 50000,0 ) mcmc.trace('means').gettrace()[-1,:]
there mc.categorical
object this.
p = [0.2, 0.3, .5] t = mc.categorical('test', p ) t.random() #array(2, dtype=int32)
it returns int between 0 , len(p)-1
. model 3 normals, make p
mc.dirichlet
object (it accepts k
length array hyperparameters; setting values in array same setting prior probabilities equal). rest of model identical.
this generalization of model suggested above.
update:
okay, instead of having different means, can collapse them 1:
means = normal( "means", 0, 0.001, size=3 ) ... @mc.deterministic def mean(categorical=categorical, means = means): return means[categorical]
Comments
Post a Comment