pgmpy: Probabilistic Graphical Models using Python

Probabilistic Graphical Models (PGM) is a technique of compactly representing a joint distribution by exploiting dependencies between the random variables. It also allows us to do inference on joint distributions in a computationally cheaper way than the traditional methods. PGMs are widely used in the field of speech recognition, information extraction, image segmentation, modelling gene regulatory networks. pgmpy [pgmpy] is a python library for working with graphical models. It allows the user to create their own graphical models and answer inference or map queries over them. pgmpy has implementation of many inference algorithms like VariableElimination, Belief Propagation etc. This paper first gives a short introduction to PGMs and various other python packages available for working with PGMs. Then we discuss about creating and doing inference over Bayesian Networks and Markov Networks using pgmpy.


Introduction
Probabilistic Graphical Model (PGM) is a technique of representing Joint Distributions over random variables in a compact way by exploiting the dependencies between them.PGMs use a network structure to encode the relationships between the random variables and some parameters to represent the joint distribution.
There are two major types of Graphical Models: Bayesian Networks and Markov Networks.
Bayesian Network: A Bayesian Network consists of a directed graph and a conditional probability distribution associated with each of the random variables.A Bayesian network is used mostly when there is a causal relationship between the random variables.An example of a Bayesian Network representing a student [student] taking some course is shown in Fig 1.
Markov Network: A Markov Network consists of an undirected graph and a few Factors are associated with it.Unlike Conditional Probability Distributions, a Factor does not represent the probabilities of variables in the network; instead it represents the compatibility between random variables that is how much a particular state of a random variable likely to agree with the another state of some other random variable.An example of markov [markov] network over four friends A, B, C, D agreeing to some concept is shown in Fig 2.
There are numerous open source packages available in Python for working with graphical models.eBay's bayesian-belief-networks [bbn] mostly focuses on Bayesian Models and has implementation of a limited number of inference algorithms.Another package pymc [pymc] focuses mainly on Markov Chain Monte Carlo (MCMC) method.libpgm [libpgm] also mainly focuses on Bayesian Networks.
pgmpy tries to be a complete package for working with graphical models and gives the user full control on designing the model.The source code is very well documented with proper docstrings and doctests for each method so that users can quickly get upto speed.Furthermore, pgmpy also provides easy extensibility allowing users to write their own inference algorithms or elimination order algorithms without any additional effort to get familiar with the source code.

Getting Source Code and Installing
pgmpy is released under MIT Licence and is hosted on github.We can simply clone the repository and install it: git clone https://github.com/pgmpy/pgmpycd pgmpy [sudo] python3 setup.pyinstall Dependencies: pgmpy runs only on python3 and is dependent on networkx, numpy, pandas and scipy which can be installed using pip or conda as: pip install -r requirements.txtor: conda install --file requirements.txt

Creating Bayesian Models using pgmpy
A Bayesian Network consists of a directed graph where nodes represents random variables and edges represent the the relation between them.It is parameterized using Conditional Probability Distributions(CPD).Each random variable in a Bayesian Network has a CPD associated with it.If a random varible has parents in the network then the CPD represents P(var|Par var ) i.e. the probability of that variable given its parents.In the case, when the random variable has no parents it simply represents P(var) i.e. the probability of that variable.
For example, we can take the case of student model represented in Fig 1 .A possible CPD for the random variable grade is shown in Table 1.
We can represent the CPD shown in The network structure of a Graphical Model encodes the independence conditions between the random variables.pgmpy also has methods to determine the local independencies, D-Separation, converting to a markov model etc.A few example are shown below: student_model.get_cpds() [<TabularCPD representing P(G:3 | I:2, D:2) at 0x7f196c0b27b8>, <TabularCPD representing P(D:2) at 0x7f196c0b2828>,

Creating Markov Models in pgmpy
A Markov Network consists of an undirected graph which connects the random variables according to the relation between them.A markov network is parameterized by factors which represent the likelihood of a state of one variable to agree with some state of other variable.We can take the example of a Factor over variables A and B in the network shown in Fig 2 .A possible Factor over variables A and B is shown in Table 2.
We can represent this Factor in pgmpy as follows: Assuming some other possible factors as in Table 3, 4 and 5, we can define the complete markov model as:

Fit and Predict Methods
In a general machine learning task we are given some data from which we want to compute the parameters of the model.pgmpy simplifies working on these problems by providing fit and predict methods in the models.fit method accepts the given data as a pandas DataFrame object and learns all the parameters from it.The predict method also accepts a pandas DataFrame object and predicts values of all the missing variables using the model.An example of fit and predict over the student model using some randomly generated data:

Extending pgmpy
One of the main features of pgmpy is its extensibility.It has been built in a way so that new algorithms can be directly written without needing to get familiar with the code base.
For example, for writing any new inference algorithm we can simply inherit the Inference class.Inheriting this base inference class exposes three variables to the class: self.variables,self.cardinalities and self.factors;using these variables we can write our own inference algorithm.An example is shown: Similarly, for adding any new variable elimination order algorithm we can simply inherit from BaseEliminationOrder and define a method named cost(self, variable) which returns the cost of eliminating that variable.Inheriting this class also exposes two variables: self.bayesian_model and self.moralized_graph.We can then call the get_elimination_order method to get the elimination order.Below is an example for returning an elimination order in which the variables are sorted alphabetically.

Comparing pgmpy to other libraries
Starting with defining the model, pgmpy provides a very simple to use API.A model can be instantiated simply by using the __init__ method and the structure can be modified using add_node, add_edge etc methods.After the model is created, we can simply add the CPDs using the add_cpds method.In the case of eBay's bayesian belief network, we have to create a separate function for each CPD.And each of these function has a dict of CPD values and logic to return the value when the states are passed as arguments [example_bbn].Similarly in case of libpgm we have the option to read the data from files defined in a specific format [example_libpgm] but doesn't provide any methods for making changes to the network.For changing the structure we will need to modify the internal variables storing the network information.We have tried to keep pgmpy as modular as possible.We can take the example of creating a model.We define a network structure and separately define different CPDs and then simply associate the CPDs to the structure.At any time we can modify these CPDs, unassociate or associate another CPD to the network.
Other than providing the features to easily create models, pgmpy also supports 4 standard file formats: pomdpX [pomdpX], ProbModelXML [ProbModel], XMLBeliefNetwork [XMLBelief] and XMLBIF [XMLBIF].Using pgmpy we can read as well as write networks in these formats.Also there's an ongoing GSoC project for adding support for more file formats so hopefully we will be having support for many more formats soon.
There are many more benefits of using networkx to represent the graph structure.For example we can directly run various graph related algorihtms implemented in networkX on our networks.Also we can use networkX's plotting functionality to visualize our networks.
pgmpy also implements methods for getting independencies, D-Separation etc which would help a lot to people who are still new to Graphical Models.These features are not available in most of the other libraries.
We have tried to keep pgmpy as uniform as possible.For example we have fit and predict methods with each of the models which can automatically learn the parameters and structure and you can control the learning by simply passing arguments to these methods.Whereas in the case of libpgm, it has multiple methods for learning like lg_mle_estimateparams, lg_constraint_estimatesstruct, discrete_estimatebn etc. Similarly for each inference algorithm pgmpy prodives query and map_query methods.
Another area in which pgmpy excels is its extensibility.As we have discussed earlier, we can easily add new algorithms to pgmpy without even getting familiar with the code base.We have to tried to build pgmpy in such a way that new components can be easily added which will really help researchers working on new ideas to quickly prototype.Also, since pgmpy is documented very well it is very easy to understand the code base.
Performance wise pgmpy is a bit slower than a few libraries but we are currently actively working on improving the performance so hopefully we will be seeing a major improvement in the coming months.

TABLE 1 :
Conditional Probability Table.Now, coming back to defining a model using pgmpy.The general workflow for defining a model in pgmpy is to first define the network structure and then add the parameters to it.We can create the student model shown in Fig 1 in pgmpy as follows:

TABLE 2 :
Factor over variables A and B.

TABLE 3 :
Factor over variables B and C.

TABLE 4 :
Factor over variables C and D.Similar to Bayesian Networks, pgmpy also has the feature for computing independencies, converting to Bayesian Network etc in the case of Markov Networks.

TABLE 5 :
Factor over variables D and A.call either query method to find the probability of some variable given evidence, or else map_query method to know the state of the variable having maximum probability.Let's perform inference on the student model (Fig1) using variable elimination :