Liesel: A Probabilistic Programming Framework#

Welcome to the API documentation of Liesel, a probabilistic programming framework with a focus on semi-parametric regression. It includes:

  • Liesel, a library to express statistical models as Probabilistic Graphical Models (PGMs). Through the PGM representation, the user can build and update models in a natural way.

  • Goose, a library to build custom MCMC algorithms with several parameter blocks and MCMC kernels such as the No U-Turn Sampler (NUTS), the Iteratively Weighted Least Squares (IWLS) sampler, or different Gibbs samplers. Goose also takes care of the MCMC bookkeeping and the chain post-processing.

  • Liesel-GAM, a modeling library built on Liesel which assists the user with the configuration of semi-parametric regression models such as Generalized Additive Models for Location, Scale and Shape (GAMLSS) with different response distributions, spline-based smooth terms and shrinkage priors.

The name “Liesel” is an homage to the Gänseliesel fountain, landmark of Liesel’s birth city Göttingen.

Installation#

You can install Liesel via pip:

pip install liesel

If you want to work with the latest development version of Liesel or use PyGraphviz for prettier plots of the model graphs, see the README in the main repository.

Now you can get started. Throughout this documentation, we import Liesel as follows:

import liesel.model as lsl
import liesel.goose as gs

We also commonly use the following imports:

import jax
import jax.numpy as jnp
import numpy as np
import tensorflow_probability.substrates.jax.distributions as tfd
import tensorflow_probability.substrates.jax.bijectors as tfb

Guides#

Start with Model building to construct and inspect a model, then follow MCMC sampling or Optimization for inference. See Example library for statistical applications.

Further Reading#

For a scientific discussion of the software, see our paper on arXiv.

Acknowledgements#

Liesel is being developed by Paul Wiemann and Hannes Riebl at the University of Göttingen with support from Thomas Kneib. Important contributions were made by Joel Beck, Alex Afanasev, Gianmarco Callegher and Johannes Brachem. We are grateful to the German Research Foundation (DFG) for funding the development through grant 443179956.

University of Göttingen Funded by DFG

API Reference#

This is an overview of the central classes in Liesel.

Models#

Start with the Model building guide. These three classes describe the model graph; their reference pages document arguments and defaults.

The model building workflow in Liesel consists of the following steps:

  1. Set up the nodes and variables that make up your model.

  2. Initialize a Model with your root variable(s).

Model

A probabilistic graphical model.

Var

A variable in a statistical model.

Dist

A Node subclass that wraps a probability distribution.

MCMC#

Start with MCMC sampling for worked examples and task guides. The pages below describe arguments, defaults, and exact behavior.

LieselMCMC

Manages the setup of MCMC specifications for a Liesel model.

MCMCSpec

Specification for the MCMC kernel and optional jitter distribution associated with a model variable.

EngineBuilder

The EngineBuilder is used to construct an MCMC Engine.

Engine

MCMC engine capable of combining multiple transition kernels.

MCMC results#

The central classes for handling your sampling results are:

You can obtain your posterior samples as a dictionary via get_posterior_samples. There is also experimental support for turning your samples into an ArviZ data object via to_arviz_inference_data.

Goose also comes with a number of plotting functions that give you quick acccess to important diagnostics.

SamplingResults

Contains the results of the MCMC engine.

Summary

Posterior summary and diagnostics for SamplingResults.

SamplesSummary

Posterior summary and diagnostics for a dictionary of sample arrays.

loo

Compute Pareto-smoothed importance sampling leave-one-out cross-validation (PSIS-LOO-CV) statistic via ArviZ.

Optimization#

Start with the Optimization guide. These pages describe the arguments and defaults.

LieselOptim

Builds an OptimEngine for a Liesel model using sensible defaults.

OptimEngine

Runs an optimization loop over epochs, batches, and optimizers.

OptimCheckpoint

An explicit snapshot from which an optimization run can continue.

OptimHistory

Stores loss values and optional position histories for optimizer runs.

OptimResult

Result returned by an optimizer run.

OptimNaNDebugInfo

Reproduction data for the first NaN captured by OptimEngine.

Stopper

Handles maximum-epoch and early stopping decisions.

EmaTrainLossMonitor

Configures EMA monitoring of the pre-update mini-batch training loss.

LossMonitor

Experimental#

These integrations have experimental APIs.

arviz

pymc

A ModelInterface for PyMC models.

Deprecated#

liesel.goose.optim_flat() is deprecated and emits a FutureWarning. Use liesel.optim.LieselOptim for new code, including finding starting values for MCMC. See Migrate optim_flat for a before-and-after example.

optim_flat

Optimize the parameters of a Liesel Model.

Stopper

Handles (early) stopping for optim_flat().

history_to_df

Turns liesel.goose.OptimResult.history into a pandas.DataFrame.

OptimResult

Holds the results of model optimization with optim_flat().

Effort-Based Versioning#

Starting with v0.4.0, we will be using effort-based versioning. See the EffVer documentation at https://jacobtomlinson.dev/effver/

The JAX developers provide a wonderful summary: https://docs.jax.dev/en/latest/jep/25516-effver.html

The following description is almost entirely quoted from the linked JAX page, but it describes what we intend with effort-based versioning perfectly.

Effort-based versioning is a three-number versioning system, similar to the better-known semantic versioning (SemVer: https://semver.org/). It uses a three-number format: MACRO.MESO.MICRO, where version numbers are incremented based on the expected effort required to adapt to the change.

As an example, consider software with current version 2.3.4:

  1. Increasing the micro version (i.e. releasing 2.3.5) signals to users that little to no effort is necessary on their part to adapt to the changes.

  2. Increasing the meso version (i.e. releasing 2.4.0) signals to users that some small effort will be required for existing code to work with the changes.

  3. Increasing the macro version (i.e. releasing 3.0.0) signals to users that significant effort may be required to update to the changes.

In some ways, this captures the essence of more commonly-used semantic versioning, but avoids phrasing in terms of compatibility guarantees that are hard to meet in practice.

Zero Version#

In addition, EffVer gives special meaning to the zero version. Early releases of software are often versioned 0.X.Y, and in this case:

  • X has the characteristics of the macro version.

  • Y has the characteristics of the meso version.

Liesel has been in a zero-version state since its initial release, and EffVer’s zero-version case is a good post-facto description of the implicit intent behind Liesel’s releases to date.

In EffVer, bumping from 0.X.Y to version 1.0.0 is recommended when a certain level of stability has been reached in practice: If you end up on a version like 0.9.x for many months, it is a good signal that things are pretty stable and that it’s time to switch to a 1.0.0 release.