LazyPPLLazyPPL 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.Listmodel :: Meas Bool
model = do
-- Prior belief: it is Sunday with prob. 1/7
sunday <- sample $ bernoulli (1/7)
-- I know the rates of buses on the different days:
let rate = if sunday then 3 else 10
-- observe 4 buses
score $ poissonPdf rate 4
return sundayinference :: IO ()
inference = do
xws <- mh 1 model
plotHistogram "images/index-posterior.svg" (map fst $ take 1000 xws)plotHistogram :: (Show a , Eq a) => String -> [a] -> IO ()
plotHistogram filename xs = do
putStrLn $ "Generating " ++ filename ++ "..."
let categories = nub xs
let counts = map (\c -> length $ filter (==c) xs) categories
file filename $ bar (map show categories) $ map (\n -> (fromIntegral n)/(fromIntegral $ length xs)) counts
putStrLn $ "Done."
main = do {inference}