Skip to content

Repository files navigation

pgmpy is a Python library for causal and probabilistic modeling using graphical models. It provides a uniform API for building, learning, and analyzing models, such as Bayesian Networks, Dynamic Bayesian Networks, Directed Acyclic Graphs (DAGs), and Structural Equation Models (SEMs). By integrating tools from both probabilistic inference and causal inference, pgmpy enables users to seamlessly transition between predictive and causal analyses.

Documentation · Examples . Tutorials
Open SourceGitHub License
TutorialsBinder
CommunityDiscord Online!slack
CI/CDgithub-actionscodecovasvplatform
Code!pypi!conda!python-versions!black
DownloadsPyPI - DownloadsPyPI - DownloadsDownloads
Supported ByGC.OS SponsoredFLOSS/FUNDAffiliated with NumFOCUS

Key Features

FeatureDescription
Causal Discovery / Structure LearningLearn the model structure from data, with optional integration of expert knowledge.
Causal ValidationAssess how compatible the causal structure is with the data.
Parameter LearningEstimate model parameters (e.g., conditional probability distributions) from observed data.
Probabilistic InferenceCompute posterior distributions conditioned on observed evidence.
Causal InferenceCompute interventional and counterfactual distributions using do-calculus.
SimulationsGenerate synthetic data under specified evidence or interventions.

Resources and Links

Quickstart

Installation

pgmpy is available on both PyPI and anaconda. To install from PyPI, use:

pip install pgmpy

To install from conda-forge, use:

conda install conda-forge::pgmpy

Examples

Discrete Data

frompgmpy.example_modelsimportload_model# Load a Discrete Bayesian Network and simulate data.discrete_bn=load_model("bnlearn/alarm")
alarm_df=discrete_bn.simulate(n_samples=100)
# Learn a network from simulated data.frompgmpy.estimatorsimportPCdag=PC(data=alarm_df).estimate(ci_test="chi_square", return_type="dag")
# Learn the parameters from the data.frompgmpy.modelsimportDiscreteBayesianNetworkdiscrete_bn=DiscreteBayesianNetwork(dag.edges())
discrete_bn.add_nodes_from(dag.nodes())
dag_fitted=discrete_bn.fit(alarm_df)
dag_fitted.get_cpds()
# Drop a column and predict using the learned model.evidence_df=alarm_df.drop(columns=["FIO2"], axis=1)
pred_FIO2=dag_fitted.predict(evidence_df)

Linear Gaussian Data

frompgmpy.example_modelsimportload_model# Load an example Gaussian Bayesian Network and simulate datagaussian_bn=load_model("bnlearn/ecoli70")
ecoli_df=gaussian_bn.simulate(n_samples=100)
# Learn the network from simulated data.frompgmpy.estimatorsimportPCdag=PC(data=ecoli_df).estimate(ci_test="pearsonr", return_type="dag")
# Learn the parameters from the data.frompgmpy.modelsimportLinearGaussianBayesianNetworkgaussian_bn=LinearGaussianBayesianNetwork(dag.edges())
dag_fitted=gaussian_bn.fit(ecoli_df)
dag_fitted.get_cpds()
# Drop a column and predict using the learned model.evidence_df=ecoli_df.drop(columns=["ftsJ"], axis=1)
pred_ftsJ=dag_fitted.predict(evidence_df)

Mixture Data with Arbitrary Relationships

frompgmpy.global_varsimportconfigconfig.set_backend("torch")
importpyro.distributionsasdistfrompgmpy.modelsimportFunctionalBayesianNetworkfrompgmpy.factors.hybridimportFunctionalCPD# Create a Bayesian Network with mixture of discrete and continuous variables.func_bn=FunctionalBayesianNetwork(
[
("x1", "w"),
("x2", "w"),
("x1", "y"),
("x2", "y"),
("w", "y"),
("y", "z"),
("w", "z"),
("y", "c"),
("w", "c"),
]
)
# Define the Functional CPDs for each node and add them to the model.cpd_x1=FunctionalCPD("x1", fn=lambda_: dist.Normal(0.0, 1.0))
cpd_x2=FunctionalCPD("x2", fn=lambda_: dist.Normal(0.5, 1.2))
# Continuous mediator: w = 0.7*x1 - 0.3*x2 + εcpd_w=FunctionalCPD(
"w",
fn=lambdaparents: dist.Normal(0.7*parents["x1"] -0.3*parents["x2"], 0.5),
parents=["x1", "x2"],
)
# Bernoulli target with logistic link: y ~ Bernoulli(sigmoid(-0.7 + 1.5*x1 + 0.8*x2 + 1.2*w))cpd_y=FunctionalCPD(
"y",
fn=lambdaparents: dist.Bernoulli(
logits=(-0.7+1.5*parents["x1"] +0.8*parents["x2"] +1.2*parents["w"])
),
parents=["x1", "x2", "w"],
)
# Downstream Bernoulli influenced by y and wcpd_z=FunctionalCPD(
"z",
fn=lambdaparents: dist.Bernoulli(
logits=(-1.2+0.8*parents["y"] +0.2*parents["w"])
),
parents=["y", "w"],
)
# Continuous outcome depending on y and w: c = 0.2 + 0.5*y + 0.3*w + εcpd_c=FunctionalCPD(
"c",
fn=lambdaparents: dist.Normal(0.2+0.5*parents["y"] +0.3*parents["w"], 0.7),
parents=["y", "w"],
)
func_bn.add_cpds(cpd_x1, cpd_x2, cpd_w, cpd_y, cpd_z, cpd_c)
func_bn.check_model()
# Simulate data from the modeldf_func=func_bn.simulate(n_samples=1000, seed=123)
# For learning and inference in Functional Bayesian Networks, please refer to the example notebook: https://github.com/pgmpy/pgmpy/blob/dev/examples/Functional_Bayesian_Network_Tutorial.ipynb

Contributing

We welcome all contributions --not just code-- to pgmpy. Please refer out contributing guide for more details. We also offer mentorship for new contributors and maintain a list of potential mentored projects. If you are interested in contributing to pgmpy, please join our discord server and introduce yourself. We will be happy to help you get started.

About

Python library for Causal AI

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages