LazyPPL is a Haskell library for 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.
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 Bitbucket repository.
> {-# LANGUAGE ExtendedDefaultRules #-}
> module Index where
> import LazyPPL
> import Distr
> import Graphics.Matplotlib hiding (density)
> import Data.List
> model :: 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 sunday
> inference :: 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}