emcee Python Toolkit
repository·main·Indexed 23 days ago
https://github.com/dfm/emceeA Python toolkit for performing affine-invariant ensemble sampling using Markov chain Monte Carlo (MCMC) methods. It features the EnsembleSampler class for drawing samples from probability distributions, support for various sampling moves like StretchMove, DEMove, and DESnookerMove, and tools for estimating integrated autocorrelation time. The library supports parallelization via multiprocessing.Pool or MPI using the schwimmbad library.
What's inside emcee
- emcee is a stable, well-tested Python implementation of the affine-invariant ensemble sampler for Markov chain Monte Carlo (MCMC). It is based on the algorithm proposed by Goodman & Weare (2010) and is widely used in scientific research, particularly in Astrophysics.
Understand what walkers are in emcee
mainInemcee, walkers are the individual members of the ensemble. While they behave similarly to separate Metropolis-Hastings chains, they are interconnected: the proposal distribution for any single walker depends on the current positions of all other walkers in the ensemble.What are blobs in emcee?
mainBlobs allow you to track arbitrary metadata associated with every sample in the MCMC chain. In version 3, blobs are stored as NumPy arrays, and the sampler performs type inference to determine the simplest representation.
To use blobs, your
log_probfunction must return more than one value. The first value is always assumed to be the log probability, and all subsequent values are treated as blobs.Note on non-finite probabilities: If
log_probreturns-np.inffor the log probability, the sampler does not inspect or track the blobs. However, you must still return the correct number of arguments to match your expected blob structure.How moves work in emcee
mainIn
emceeversion 3 and later, a "move" is an algorithm used to update the coordinates of walkers in an ensemble sampler. Instead of relying solely on the traditional "stretch move", you can provide a mixture of different moves to create a more efficient sampler, especially for high-dimensional or multi-modal probability surfaces.Key concepts:
- Mixture of Moves: You can specify a mixture of moves using the
moveskeyword in theEnsembleSampler. This mixture can be weighted. At each sampling step, a move is randomly selected from the mixture to serve as the proposal. - Parallelization: Most ensemble moves are designed to update the ensemble in parallel (following Foreman-Mackey et al. 2013), allowing computationally expensive models to leverage multiple CPUs.
- Complementary Ensembles: Updates for a walker are typically based on the coordinates of a complementary set of walkers in the ensemble.
- Move Types:
- Ensemble Moves: Update walkers based on the current state of the ensemble (e.g.,
StretchMove,WalkMove,KDEMove). Many of these inherit fromRedBlueMoveto support parallelization. - Metropolis–Hastings Moves: Use independent proposals to update walkers (e.g.,
GaussianMove, which inherits fromMHMove).
- Ensemble Moves: Update walkers based on the current state of the ensemble (e.g.,
- Mixture of Moves: You can specify a mixture of moves using the
Use the EnsembleSampler for MCMC sampling
mainStandard usage ofemceeinvolves instantiating anEnsembleSampler. This class is the primary interface for performing Markov Chain Monte Carlo (MCMC) sampling using an ensemble of walkers.Work with State objects in emcee
mainSeveral methods within theEnsembleSamplerclass are designed to return or consumeStateobjects. AStateobject encapsulates the current status of the sampler, including the positions of the walkers and potentially other metadata required for sampling or resuming processes.Install emcee via pip
mainThe recommended way to install the stable version of
emceeis usingpip. Ensure you havenumpyinstalled as it is a dependency.Run the following commands to upgrade your build tools and install
emcee:python -m pip install -U pip pip install -U setuptools setuptools_scm pep517 pip install -U emceeInitialize walkers for sampling
mainTo initialize walkers effectively, start them in a small cluster (a "small ball") around the preferred position based on your a priori knowledge. The walkers are designed to quickly branch out from this cluster to explore the rest of the parameter space.Install emcee from source
mainTo install the latest development version from the GitHub repository, clone the repository and install it in editable mode using
pip:python -m pip install -U pip python -m pip install -U setuptools setuptools_scm pep517 git clone https://github.com/dfm/emcee.git cd emcee python -m pip install -e .Handle parameter limits and boundaries
mainTo confine walkers to a finite volume of the parameter space, you should ensure your log-probability function returns negative infinity for any parameter values that fall outside the allowed volume (i.e., where the log of the prior probability is 0).
return -numpy.infUse `blobs_dtype` to define named blobs
mainIf you want to save multiple pieces of metadata with specific names and types, use the
blobs_dtypeargument when initializingemcee.EnsembleSampler. This results inget_blobs()returning a structured NumPy array.If
blobs_dtypeis not provided, the sampler automatically guesses the dtype from the first call tolog_prob.Example of using named blobs:
import emcee import numpy as np def log_prob(params): lp = log_prior(params) if not np.isfinite(lp): return -np.inf, None, None ll = log_like(params) if not np.isfinite(ll): return -np.inf, None, None # Return log probability, log prior, and parameter mean return lp + ll, lp, np.mean(params) coords = np.random.randn(32, 3) nwalkers, ndim = coords.shape # Define the structured dtype for named blobs dtype = [("log_prior", float), ("mean", float)] sampler = emcee.EnsembleSampler(nwalkers, ndim, log_prob, blobs_dtype=dtype) sampler.run_mcmc(coords, 100) # Access named blobs via keys blobs = sampler.get_blobs() log_prior_samps = blobs["log_prior"] mean_samps = blobs["mean"] # Access flattened named blobs flat_blobs = sampler.get_blobs(flat=True) flat_log_prior_samps = flat_blobs["log_prior"] flat_mean_samps = flat_blobs["mean"]def log_prob(params): lp = log_prior(params) if not np.isfinite(lp): return -np.inf, None, None ll = log_like(params) if not np.isfinite(ll): return -np.inf, None, None return lp + ll, lp, np.mean(params) coords = np.random.randn(32, 3) nwalkers, ndim = coords.shape # Here are the important lines for defining the blobs_dtype dtype = [("log_prior", float), ("mean", float)] sampler = emcee.EnsembleSampler(nwalkers, ndim, log_prob, blobs_dtype=dtype) sampler.run_mcmc(coords, 100) blobs = sampler.get_blobs() log_prior_samps = blobs["log_prior"] mean_samps = blobs["mean"] print(log_prior_samps.shape) # (100, 32) print(mean_samps.shape) # (100, 32) flat_blobs = sampler.get_blobs(flat=True) flat_log_prior_samps = flat_blobs["log_prior"] flat_mean_samps = flat_blobs["mean"] print(flat_log_prior_samps.shape) # (3200,) print(flat_mean_samps.shape) # (3200,)Replace MPIPool with schwimmbad
mainTheMPIPoolimplementation has been removed from emcee. For MPI-based parallel sampling, use theschwimmbadproject, which is a fork of the original emcee implementation designed to fix memory leaks and crashes.