An example using Zeus
Here we show a standalone example of using Zeus to
estimate the parameters of a straight line model in data with Gaussian noise. The
data and model used in this example are defined in createdata.py, which can be downloaded
from here. The
script shown below can be downloaded from here.
Example code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Example of running Zeus to fit the parameters of a straight line.
"""
from __future__ import print_function, division
import os
import sys
import numpy as np
# import zeus
import zeus
# import model and data
from createdata import *
def logposterior(theta, data, sigma, x):
"""
The natural logarithm of the joint posterior.
Args:
theta (tuple): a sample containing individual parameter values
data (list): the set of data/observations
sigma (float): the standard deviation of the data points
x (list): the abscissa values at which the data/model is defined
"""
lp = logprior(theta) # get the prior
# if the prior is not finite return a probability of zero (log probability of -inf)
if not np.isfinite(lp):
return -np.inf
# return the likeihood times the prior (log likelihood plus the log prior)
return lp + loglikelihood(theta, data, sigma, x)
def loglikelihood(theta, data, sigma, x):
"""
The natural logarithm of the joint likelihood.
Args:
theta (tuple): a sample containing individual parameter values
data (list): the set of data/observations
sigma (float): the standard deviation of the data points
x (list): the abscissa values at which the data/model is defined
Note:
We do not include the normalisation constants (as discussed above).
"""
# unpack the model parameters from the tuple
m, c = theta
# evaluate the model (assumes that the straight_line model is defined as above)
md = straight_line(x, m, c)
# return the log likelihood
return -0.5*np.sum(((md - data)/sigma)**2)
def logprior(theta):
"""
The natural logarithm of the prior probability.
Args:
theta (tuple): a sample containing individual parameter values
Note:
We can ignore the normalisations of the prior here.
"""
lp = 0.
# unpack the model parameters from the tuple
m, c = theta
# uniform prior on c
cmin = -10. # lower range of prior
cmax = 10. # upper range of prior
# set prior to 1 (log prior to 0) if in the range and zero (-inf) outside the range
lp = 0. if cmin < c < cmax else -np.inf
# Gaussian prior on m
mmu = 0. # mean of the Gaussian prior
msigma = 10. # standard deviation of the Gaussian prior
lp -= 0.5*((m - mmu)/msigma)**2
return lp
Nens = 100 # number of ensemble points
mmu = 0. # mean of the Gaussian prior
msigma = 10. # standard deviation of the Gaussian prior
mini = np.random.normal(mmu, msigma, Nens) # initial m points
cmin = -10. # lower range of prior
cmax = 10. # upper range of prior
cini = np.random.uniform(cmin, cmax, Nens) # initial c points
inisamples = np.array([mini, cini]).T # initial samples
ndims = inisamples.shape[1] # number of parameters/dimensions
Nburnin = 500 # number of burn-in samples
Nsamples = 500 # number of final posterior samples
# set additional args for the posterior (the data, the noise std. dev., and the abscissa)
argslist = (data, sigma, x)
# set up the sampler
sampler = zeus.EnsembleSampler(Nens, ndims, logposterior, args=argslist)
# pass the initial samples and total number of samples required
sampler.run_mcmc(inisamples, Nsamples+Nburnin);
# extract the samples (removing the burn-in)
postsamples = sampler.get_chain(flat=True, discrd=Nburnin)
# plot posterior samples (if corner.py is installed)
try:
import matplotlib as mpl
mpl.use("Agg") # force Matplotlib backend to Agg
import corner # import corner.py
except ImportError:
sys.exit(1)
print('Number of posterior samples is {}'.format(postsamples.shape[0]))
fig = corner.corner(postsamples, labels=[r"$m$", r"$c$"], truths=[m, c])
fig.savefig('zeus.png')
Running the code
A description of installing Zeus is given here. If you have downloaded the createdata.py and test_zeus.py scripts into the directory ${HOME}, then you can run it using:
python test_zeus.py
If you have Matplotlib installed then the script will produce a plot of the posterior distributions on the straight line parameters $m$ and $c$.
A Python 3 Docker image with emcee installed is available, which can be used with:
docker run -it -v ${HOME}:/work mattpitkin/samplers:python3
to enter an interactive container, and then within the container the test script can be run with:
python test_zeus.py