ernest is a comprehensive toolkit for nested sampling (NS), an algorithm for estimating a statistical model’s Bayesian evidence and posterior distribution. It provides S3 objects and methods that make nested sampling accessible, flexible, and robust within the R environment.
Installation
Install the development version of ernest from GitHub with:
# install.packages("devtools")
devtools::install_github("kylesnap/ernest")
Why use ernest?
In Bayesian inference, evidence ($`\mathcal{Z}`$, also called the marginal likelihood) is the probability of observing data $`D`$ under a proposed model $`M`$. This is obtained by integrating the model’s likelihood over the prior distribution of $`M`$’s parameters. $`\mathcal{Z}`$ provides a parameter-independent way to assess the plausibility of $`D`$ given $`M`$, and is key for Bayesian model comparison through methods such as Bayes factors.
Calculating $`\mathcal{Z}`$ is challenging, as it requires evaluating a high-dimensional integral over the parameter space. Nested sampling estimates this integral by dividing the space into a series of small volumes. It starts by drawing points from the prior and ranking them by likelihood. The least likely points are discarded and replaced with new samples from more restricted likelihood regions, gradually compressing the search space. Each round of discarding shrinks the explored volume in a predictable way, helping to approximate the integral.
This approach to estimating $`Z`$ offers several advantages over methods like Markov chain Monte Carlo (MCMC):
- Robustness: NS handles complex likelihood surfaces that would otherwise be difficult to traverse, such as those with multiple modes or discontinuities.
- Posterior inference: After a run, discarded samples can be weighted to approximate the model’s posterior distribution.
- Natural stopping criterion: NS can estimate the amount of evidence left within the unexplored prior volume, and can stop sampling once this amount gets trivially small.
- Tractable uncertainty estimates: The shrinkage at each iteration follows a uniform order statistic, so uncertainty can be simulated using the results from a single run.
ernest’s implementation of NS offers R users several benefits:
- Native R implementation: John Skilling’s Skilling (2006) NS algorithm is implemented in R, with no Python or Fortran dependencies. (C++ is used to implement the included likelihood samplers to improve run-time efficiency).
- Type- and size-safety: ernest helps ensure that the user provides likelihood functions and prior specifications meet the requirements of the NS algorithm.
-
Familiar methods: Sampler specifications and results are stored in S3 objects. Start or continue an NS run with
generate()
, review results withsummary()
, and simulate estimation error withcalculate()
. - Powerful visualizations: Plot evidence estimates and analyse posterior distributions using ggplot2 and posterior.
Quick Example
This example demonstrates a basic workflow: define a prior, specify a likelihood, run nested sampling, and summarise results.
library(ernest)
# Define a prior (i.i.d. multivariate uniform)
prior <- create_uniform_prior(lower = -10, upper = 10, varnames = c("x", "y", "z"))
# Define a log-likelihood function (multivariate normal)
mu <- c(0, 0, 0)
Sigma <- diag(1, 3)
Sigma[Sigma == 0] <- 0.95
loglike <- create_likelihood(
rowwise_fn = LaplacesDemon::dmvn,
mu = !!mu,
Sigma = !!Sigma,
log = TRUE
)
# Set up and run the sampler
sampler <- ernest_sampler(
log_lik = loglike,
prior = prior,
n_points = 500
)
run <- generate(sampler, seed = 42)
# Summarise and visualise results
summary(run)
plot(run)
visualize(run, type = "trace")
For advanced usage, including custom priors and hierarchical models, see the package vignettes.
Learn More
-
About NS:
vignette("nested-sampling-with-ernest")
, Skilling (2004), Skilling (2006), and Buchner (2023). -
How to use ernest:
vignette("more-ernest-runs.Rmd")
.
Prior Work
NS has been implemented in many languages; some offer R interfaces. This non-exhaustive list of popular NS implementations is adapted from Fowlie, Handley, and Su (2021):
Package | Citation | Language(s) |
---|---|---|
nestle | Barbary (2015) | Python |
dynesty | Speagle (2020) | Python |
DIAMONDS | Corsaro and Ridder (2014) | C++ |
MultiNest | Feroz, Hobson, and Bridges (2009) | Fortran; interfaces for C++, Python, R, and MatLab |
PolyChord | Handley, Hobson, and Lasenby (2015) | Fortran; interfaces for C++ and Python |
DNest4 | Brewer and Foreman-Mackey (2018) | C++; interfaces with Python, R, and Julia |
ernest’s design, API, and NS implementation are based on the nestle package, with further inspiration from dynesty.
The nestcheck Python package provides routines for error estimation and diagnostic plotting with nested sampling runs (Higson et al. 2019). Several of ernest’s methods are based on this work.