Open-source project
bayespy/bayespy avatar
bayespy/bayespy

BayesPy does variational message passing for conjugate models

Bayesian Python: Bayesian inference tools for Python

705 stars162 forksPythonMIT

At a glance

What is it?
BayesPy is a Python library for Bayesian inference that builds a Bayesian network, observes data and runs posterior inference, but only for one family of models and one algorithm: variational message passing over conjugate exponential families. It is elegant and narrow, and the alternatives cover the cases it does not.
Who is it for?
BayesPy suits an expert who wants exact-ish variational message passing on a conjugate exponential model, written as a network with named plate-like groupings, and who values a small readable codebase over a general inference framework.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 142 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A network, some observations, and a posterior

The stated goal is to provide a tool that is efficient, flexible and extendable enough for expert use but also accessible for more casual users, and the workflow in the README is three steps. The user constructs a model as a Bayesian network, observes data and runs posterior inference. That is the whole public contract, and it is a different starting point from the array-of-random-variables approach used by the general purpose probabilistic programming tools. Here the model is a structured object, a network of nodes with parents and children, and the inference machinery is chosen to suit that structure. The package is called BayesPy, it is on PyPI and on conda-forge, the documentation lives at bayespy.org, and the author is Jaakko Luttinen with a mailing list and a Gitter chat alongside the issue tracker. The audience is therefore a statistician or a machine learning researcher who already thinks in graphical models and wants a library that lets them write the model down rather than one that infers a program from samples.

One algorithm, one family of distributions

The scope statement in the README is the most important sentence in the project for a potential user: currently, only variational Bayesian inference for the conjugate-exponential family, described as variational message passing, has been implemented. Future work includes variational approximations for other types of distributions and possibly other approximate inference methods such as expectation propagation, Laplace approximations, Markov chain Monte Carlo and other methods. So the library is not a general inference engine with several backends. It is one algorithm, implemented carefully, for the class of models where conjugate priors and likelihoods make the message passing algebra tractable. The trade is the classic one. In exchange for exact algebra rather than sampling, you give up the ability to express almost any model, because a non conjugate pair breaks the closed form update. The upside is real too. Message passing gives a deterministic, inspectable posterior rather than a set of samples, and for a conjugate model the resulting marginals and expectations can be computed in closed form, which is useful when you want the answer rather than a posterior sample to feed into something else. The README explicitly welcomes contributions, so the missing inference methods are an open invitation rather than a closed decision.

Installing from PyPI or conda-forge

The package is distributed on PyPI and on conda-forge, with the release badge on the README pointing at the PyPI project page and the conda badge at the conda-forge channel. The source install goes through setup.py, which reads its metadata from bayespy/_meta.py and takes the version from versioneer, so the installed version always matches the git checkout. The runtime dependencies are pinned with lower bounds and the comments explain why.

python
    install_requires = [
        'numpy>=1.10.0', # 1.10 implements broadcast_to
                            # 1.8 implements broadcasting in numpy.linalg
        'scipy>=0.13.0', # <0.13 have a bug in special.multigammaln
        'h5py',
        'truncnorm',
    ]

The version bounds are old and specific, which tells you something about the era of the code. numpy has been required at 1.10 or newer since broadcast_to existed, scipy at 0.13 or newer because of a bug in special.multigammaln, and h5py and truncnorm are there for file input and for truncated normal distributions, which is a hint that continuous conjugate models with non standard supports are in scope. The setup script also refuses to run on Python 2, raising a RuntimeError if the major version is below 3, which is a leftover from the period when that check mattered. The repository has a tox.ini, requirements-dev.txt, requirements-doc.txt and a shell.nix, so the development and documentation environments are reproducible, and INSTALL.rst sits at the top level for the installation instructions that the README does not reproduce in full.

master and develop, and a release line that stopped in 2021

The branch table in the README separates the stable line from the development line with badges for test status, coverage and documentation: master is the stable branch and develop is the latest branch, each with its own Travis CI status, Coveralls coverage and a documentation build, stable or latest. That structure is conventional and useful, but the dates underneath it are the thing to notice. The recent releases list shows 0.5.21 published on 2021-03-04, 0.5.11 on 2017-09-26 and 0.5.10 on 2017-09-02, while the repository itself is not archived and its last push was on 2026-06-03. So the code is being touched, and the published versions stopped moving five years ago. The copyright line in the README covers 2011 to 2017, and the setup.py header says 2011 to 2015. A user therefore has three choices, and each is a different risk. Pinning a released version from PyPI gives you 0.5.21 and whatever fixes it carries, with no expectation of new ones. Installing from the develop branch gives you the current state of the code, which is more recent than 2021 and carries the develop branch's own compatibility state. Vendoring the source into your own repository gives you reproducibility and the ability to patch, at the cost of owning the merge. What the project does not give you is a dependable stream of new releases, and if your environment policy requires a version with a published changelog entry, check the CHANGELOG.rst at the top of the repository before you commit to a number.

What BayesPy does not do

Three boundaries follow from the design, and each of them has bitten someone. The first is model expressiveness. If your model contains a non conjugate prior and likelihood pairing, the variational update is not available in closed form, and the library does not fall back to sampling on your behalf. The second is inference method coverage. Expectation propagation, Laplace approximation and MCMC are listed as future work, so a model that needs them, or a user who wants to cross check the variational answer against samples, has to go elsewhere. The third is the scale of the problem. BayesPy builds and infers over an explicit network with explicit groupings, and the cost of that representation grows with the number of nodes and plates, so the library is aimed at models you can draw on a page rather than at large-scale data pipelines where you would sample a posterior in the background. There is also an ecosystem point. The README does not describe any integration with array frameworks or gradient-based tooling, and the whole design is message passing rather than autodiff, so a project that wants to differentiate through its posterior is in a different world. If any of these apply, the cost of switching is not the inference call itself but rewriting the model description, which is why the fit check has to happen at the start rather than after the first results look odd.

The alternatives differ by algorithm, not by taste

The README lists comparable projects and their licences, and the list is more useful than it looks because the differences are algorithmic. VIBES allows variational inference to be performed automatically on a Bayesian network, is implemented in Java and is released under the revised BSD license. Bayes Blocks is a C++ and Python implementation of the variational building block framework, allows easy learning of a wide variety of models using variational Bayesian learning, and is available as free software under the GNU General Public License. Infer.NET is a .NET framework for machine learning that provides message-passing algorithms and statistical routines for Bayesian inference, and it is partly closed source and licensed for non commercial use only. So the same algorithmic family exists elsewhere, with a different licence, a different language and a different model description style. Then the sampling tools come in. PyMC provides MCMC methods in Python and is released under the Academic Free License. OpenBUGS performs Bayesian inference using Gibbs sampling under the GNU General Public License. Dimple provides Gibbs sampling, belief propagation and a few other inference algorithms for Matlab and Java under the Apache License. Stan provides inference using MCMC with an interface for R and Python under the New BSD License. And PBNT, the Python Bayesian Network Toolbox, is a Bayesian network library in Python supporting static networks with discrete variables, with no information about its licence. The choice for most people is algorithmic. Message passing with conjugate models is what BayesPy is for, sampling is what PyMC or Stan are for, and a mixed workflow is what a team ends up with when the model has one part that fits and another that does not.

Editorial conclusion

BayesPy suits an expert who wants exact-ish variational message passing on a conjugate exponential model, written as a network with named plate-like groupings, and who values a small readable codebase over a general inference framework. It is the wrong tool if your model is not conjugate, if you need MCMC, expectation propagation or a Laplace approximation, because the README states only variational Bayesian inference for the conjugate exponential family has been implemented and lists the rest as future work, and it is the wrong tool for a team that needs a maintained release stream, since the newest tagged version on record is 0.5.21 from 2021-03-04 while the repository was pushed as recently as 2026-06-03. Before you adopt it, check whether your model fits the conjugate exponential family at all, and read the documentation at bayespy.org against the branch you install, since the stable and develop lines document different things.

Frequently asked questions

Which inference methods does BayesPy implement?

The README states that currently only variational Bayesian inference for the conjugate-exponential family, meaning variational message passing, has been implemented. Expectation propagation, Laplace approximations, Markov chain Monte Carlo and other methods are listed as future work.

How do I install BayesPy?

The package is published on PyPI and on conda-forge, and the source install runs through setup.py with versioneer reading the version from the git checkout. The runtime dependencies are numpy 1.10 or newer, scipy 0.13 or newer, h5py and truncnorm.

Is BayesPy still maintained?

The repository is not archived and its last push was on 2026-06-03, but the most recent published release on record is 0.5.21 from 2021-03-04. The README documents a stable master branch and a develop branch, each with its own test status, coverage and documentation build.

Official sources

  1. bayespy/bayespy on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bayespy-bayespy.svg)](https://hysenlabs.com/projects/bayespy-bayespy)

Was this useful?