An example using PyPolyChord
Here we show a standalone example of using PyPolyChord 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 PyPolyChord to fit the parameters of a straight line.
"""
from __future__ import print_function, division
import os
import sys
from scipy.special import ndtri
import numpy as np
import resource
# import PolyChord
import pypolychord
from pypolychord.settings import PolyChordSettings
from pypolychord.priors import UniformPrior
# import model and data
from createdata import *
LN2PI = np.log(2.*np.pi)
LNSIGMA = np.log(sigma)
def prior_transform_polychord(cube):
"""
A function defining the tranform between the parameterisation in the unit hypercube
to the true parameters.
Args:
cube (array, list): a list containing the parameters as drawn from a unit hypercube.
Returns:
list: the transformed parameters.
"""
#mprime, cprime = cube # unpack the parameters (in their unit hypercube form)
mprime = cube[0]
cprime = cube[1]
cmin = -10. # lower bound on uniform prior on c
cmax = 10. # upper bound on uniform prior on c
mmu = 0. # mean of Gaussian prior on m
msigma = 10. # standard deviation of Gaussian prior on m
m = mmu + msigma*ndtri(mprime) # convert back to m
c = UniformPrior(cmin, cmax)(cprime) # convert back to c using UniformPrior class
theta = [m, c]
return theta
def loglikelihood_polychord(theta):
"""
The log-likelihood function.
Args:
theta (array, list): the set of parameter values.
Returns:
float: the log-likelihood value.
list: A list of any derived parameters (an empty list if there are none)
"""
# unpack the parameters
m = theta[0]
c = theta[1]
# normalisation
norm = -0.5*M*LN2PI - M*LNSIGMA
# chi-squared (data, sigma and x are global variables defined early on in this notebook)
chisq = np.sum(((data-straight_line(x, m, c))/sigma)**2)
return norm - 0.5*chisq, []
nlive = 1024 # number of live points
ndims = 2 # number of parameters
nderived = 0 # number of derived parameters (this is zero)
tol = 0.5 # stopping criterion
basedir = os.path.join(os.getcwd(), 'polychord') # output base directory
if not os.path.isdir(basedir):
os.makedirs(basedir) # create base directory
os.makedirs(os.path.join(basedir, 'clusters')) # 'clusters' directory
fileroot = 'straightline' # output file name
broot = os.path.join(basedir, fileroot)
# set an unlimited stack-size of PolyChord
curlimit = resource.getrlimit(resource.RLIMIT_STACK) # get current stack resource size
resource.setrlimit(resource.RLIMIT_STACK, (resource.RLIM_INFINITY,resource.RLIM_INFINITY)) # set to unlimited
# setup run settings using the PolyChordSetting class
pargs = {'nlive': nlive,
'precision_criterion': tol,
'base_dir': basedir,
'file_root': fileroot,
'write_resume': False, # don't output a resume file
'read_resume': False} # don't read a resume file
settings = PolyChordSettings(ndims, nderived, **pargs)
# run nested sampling
output = pypolychord.run_polychord(loglikelihood_polychord, ndims, nderived, settings, prior_transform_polychord)
# reset stack resource size
resource.setrlimit(resource.RLIMIT_STACK, curlimit)
# output marginal likelihood
print('Marginalised evidence is {} ± {}'.format(output.logZ, output.logZerr))
# 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)
samplefile = broot+'_equal_weights.txt'
samples = np.loadtxt(samplefile)
postsamples = samples[:,2:]
print('Number of posterior samples is {}'.format(postsamples.shape[0]))
fig = corner.corner(postsamples, labels=[r"$m$", r"$c$"], truths=[m, c])
fig.savefig('PyPolyChord.png')
Running the code
A description of installing PyPolyChord is given here. If you have downloaded the createdata.py
and test_PyPolyChord.py
scripts into the directory ${HOME}
, then you can run it using:
python test_PyPolyChord.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 PyPolyChord 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_PyPolyChord.py