Question

I would like to build a Bayesian network of discrete (pymc.Categorical) variables that are dependent on other categorical variables. As a simplest example, suppose variables a and b are categorical and b depends on a

Here is an attempt to code it with pymc (assuming a takes one of three values and b takes one of four values). The idea being that the CPT distributions would be learned from data using pymc.

import numpy as np
import pymc as pm
aRange = 3
bRange = 4

#make variable a
a = pm.Categorical('a',pm.Dirichlet('aCPT',np.ones(aRange)/aRange))

#make a CPT table as an array of 
CPTLines = np.empty(aRange, dtype=object)
for i in range(aRange):
    CPTLines[i] = pm.Dirichlet('CPTLine%i' %i,np.ones(bRange)/bRange)

#make a deterministic node that holds the relevant CPT line (dependent on state1)
@pm.deterministic
def selectedCPTLine(CPTLines=CPTLines,a=a):
    return CPTLines[a]

#make a node for variable b 
b=pm.Categorical('b', selectedCPTLine)

model = pm.MCMC([a, b, selectedCPTLine])

If we draw this model it looks like this

However, running this code we get an error:

Probabilities in categorical_like sum to [ 0.8603345]

Apparently, pymc can take a Dirichlet variable as the parameter of a Categorical variable. When the Categorical variable gets a Dirichlet variable as its parameter, it knows to expect a k-1 vector of probabilities with the assumption that the kth probability sums the vector to 1. This breaks down, however, when the Dirichlet variable is the output of a deterministic variable, which is what I need to make a CPT.

Am I going about this the right way? How can the representation mismatch be solved? I should mention that I'm relatively new to pymc and Python.

This question is related to a previous question on making a discrete state Markov model with pymc

Was it helpful?

Solution

OK, thanks. The problem is that, while usually, PyMC will recognize a Dirichlet as the parent of a Categorical and completes the probability simplex, here your Categoricals are embedded in a Container, and the Categorical does not make the automatic adjustment needed. The following code does this for you:

import numpy as np
import pymc as pm
aRange = 3
bRange = 4

aCPT = pm.Dirichlet('aCPT', np.ones(aRange))

#make variable a
a = pm.Categorical('a', aCPT)

#make a CPT table as an array of
CPTLines = [pm.Dirichlet('CPTLine%i' %i, np.ones(bRange)) for i in range(aRange)]

#make a node for variable b
@pm.stochastic(dtype=int)
def b(value=0, CPT=CPTLines, a=a):
    return pm.categorical_like(value, p=pm.extend_dirichlet(CPT[a]))

model = pm.MCMC([a, b, CPTLines])

Hope that helps.

OTHER TIPS

A couple points of confusion:

  • your model seems to contain no data (observed stochastics), so there is no information to fit the model
  • not sure what you mean by a Dirichlet variable being the output of a deterministic. As long as the probabilities are of length k-1 and they sum to less than one, you should be good. If you have a value that sums to unity, you can just pass the first k-1 of the values.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top