LazyPPL is a Haskell library for Bayesian probabilistic programming. It supports lazy use of probability, and we provide new Metropolis-Hastings algorithms to allow this. LazyPPL is inspired by recent ideas in synthetic probability theory and synthetic measure theory, such as quasi-Borel spaces and Markov categories. Laziness appears to be a good paradigm for non-parametric statistics. LazyPPL is inspired by many other languages, including Church, Anglican, and MonadBayes. Several aspects are now incorporated into MonadBayes (see here).
LazyPPL provides two monads:
Prob a
:
probability measures, supporting probability measure such as uniform :: Prob Double
,
normal :: Double -> Double -> Prob Double
,
bernoulli :: Double -> Prob Bool
.
This is lazy, in other words it is an affine monad.Meas a
:
unnormalized measures, as used in Monte Carlo simulations for Bayesian
statistics. There are two key functions:
sample :: Prob a -> Meas a
,
which samples from a probability measure;score :: Double -> Meas ()
,
which weights a measure by a given value, typically coming from a
likelihood function.To illustrate the basic usage, here is a very simple first example, that doesn’t use laziness. More advanced examples are in the menu above, and further examples in the GitHub repository.
{-# LANGUAGE ExtendedDefaultRules #-}
module Index where
import LazyPPL
import LazyPPL.Distributions
import Graphics.Matplotlib hiding (density)
import Data.List
model :: Meas Bool
= do
model -- Prior belief: it is Sunday with prob. 1/7
<- sample $ bernoulli (1/7)
sunday -- I know the rates of buses on the different days:
let rate = if sunday then 3 else 10
-- observe 4 buses
$ poissonPdf rate 4
score return sunday
inference :: IO ()
= do
inference <- mh 1 model
xws "images/index-posterior.svg" (map fst $ take 1000 xws) plotHistogram
plotHistogram :: (Show a , Eq a) => String -> [a] -> IO ()
= do
plotHistogram filename xs putStrLn $ "Generating " ++ filename ++ "..."
let categories = nub xs
let counts = map (\c -> length $ filter (==c) xs) categories
$ bar (map show categories) $ map (\n -> (fromIntegral n)/(fromIntegral $ length xs)) counts
file filename putStrLn $ "Done."
= do {inference} main