Parameters and priors
- Synopsis:
Class containing the prior and reference pdf, and other parameter information.
- Author:
Jesus Torrado
Basic parameter specification
The params
block contains all the information intrinsic
to the parameters of the model: their prior pdf and reference pdf, their latex labels,
and useful properties for particular samplers (e.g. width of a proposal pdf in an MCMC
– see the documentation for each sampler).
The prior and reference pdf are managed by the Prior
class.
You can specify three different kinds of parameters:
Fixed parameters are specified by assigning them a value, and are passed directly to the likelihood or theory code.
Sampled parameters need a
prior
pdf definition and, optionally, a reference pdf (ref
), a LaTeX label to be used when producing plots, and additional properties to aid particular samplers.Derived parameters do not have a prior definition (neither a reference value or pdf), but can have a LaTeX label and a
min
and/ormax
to be used in the sample analysis (e.g. to guess the pdf tails correctly if the derived quantity needs to be positive or negative – defaulted to-.inf
,.inf
resp.).
The (optional) reference pdf (ref
) for sampled parameters defines the region
of the prior which is of most interest (e.g. where most of the prior mass is expected);
samplers needing an initial point for a chain will attempt to draw it from the ref
if it has been defined (otherwise from the prior). A good reference pdf will avoid a long
burn-in stage during the sampling. If you assign a single value to ref
, samplers
will always start from that value; however this makes convergence tests less reliable as
each chain will start from the same point (so all chains could be stuck near the same
point).
Note
When running in parallel with MPI you can give ref
different values for each of
the different parallel processes (either at initialisation or by calling
Prior.set_reference()
). They will be taken into account e.g. for starting
parallel MCMC chains at different points/distributions of your choice.
The syntax for priors and ref’s has the following fields:
dist
(default:uniform
): any 1-dimensional continuous distribution from scipy.stats; e.g.uniform
,[log]norm
for a [log-]gaussian, orhalfnorm
for a half-gaussian.loc
andscale
(default: 0 and 1, resp.): the location and scale of the pdf, as they are understood for each particular pdf inscipy.stats
; e.g. for auniform
pdf,loc
is the lower bound andscale
is the length of the domain, whereas in a gaussian (norm
)loc
is the mean andscale
is the standard deviation.Additional specific parameters of the distribution, e.g.
a
andb
as the powers of a Beta pdf.
Note
For bound distributions (e.g. uniform
, beta
…), you can use the more
intuitive arguments min
and max
(default: 0 and 1 resp.) instead of loc
and
scale
(NB: unexpected behaviour for an unbounded pdf).
The order of the parameters is conserved in the table of samples, except that derived parameters are always moved to the end.
An example params
block:
params:
A: 1 # fixed!
B1: # sampled! with uniform prior on [-1,1] and ref pdf N(mu=0,sigma=0.25)
prior:
min: -1
max: 1
ref:
dist: norm
loc: 0
scale: 0.25
latex: \mathcal{B}_2
proposal: 0.25
B2: # sampled! with prior N(mu=0.5,sigma=3) and fixed reference value 1
prior:
dist: norm
loc: 0.5
scale: 3
ref: 1 # fixed reference value: all chains start here!
latex: \mathcal{B}_2
proposal: 0.5
C: # derived!
min: 0
latex: \mathcal{C}
You can find another basic example here.
Multidimensional priors
The priors described above are obviously 1-dimensional.
You can also define more complicated, multidimensional priors
using a prior
block at the base level (i.e. not indented), as in the
the advanced example. All the details below also apply to
the definition of external likelihoods. We will call these
custom priors “external priors”.
Inside the prior
block, list a pair of priors as [name]: [function]
, where the
functions must return log-priors. These priors will be multiplied by the
one-dimensional ones defined above. Even if you define a prior for some parameters
in the prior
block, you still have to specify their bounds in the params
block.
A prior function can be specified in two different ways:
As a function, either assigning a function defined with
def
, or alambda
. Its arguments must be known parameter names.As a string, which will be passed to
eval()
. The string can be alambda
function definition with known parameters as its arguments (you can usescipy.stats
andnumpy
asstats
andnp
resp.), or animport_module('filename').function
statement if your function is defined in a separate filefilename
in the current folder and is namedfunction
(see e.g. the advanced example).
Note
Your function definition may contain keyword arguments that aren’t known parameter names. They will simply be ignored and left to their default.
Warning
When resuming a run using an external python object as input (e.g. a prior or a likelihood), there is no way for Cobaya to know whether the new object is the same as the old one: it is left to the user to ensure reproducibility of those objects between runs.
Warning
External priors can only be functions sampled and fixed and derived parameters that are dynamically defined in terms of other inputs. Derived parameters computed by the theory code cannot be used in a prior, since otherwise the full prior could not be computed before the likelihood, preventing us from avoiding computing the likelihood when the prior is null, or forcing a post-call to the prior.
Workaround: Define your function as a external likelihood instead, since likelihoods do have access to derived parameters (for an example, see this comment).
Prior normalization for evidence computation
The one-dimensional priors defined within the params
block are automatically
normalized, so any sampler that computes the evidence will produce the right results as
long as no external priors have been defined, whose normalization is unknown.
To get the prior normalization if using external functions as priors, you can substitute your likelihood by the dummy unit likelihood, and make an initial run with PolyChord to get the prior volume (see section Computing Bayes ratios).
In general, avoid improper priors, since they will produce unexpected errors, e.g.
params:
a:
prior:
min: -.inf
max: .inf
Defining parameters dynamically
We may want to sample in a parameter space different from the one understood by the likelihood, e.g. because we expect the posterior to be simpler on the alternative parameters.
For instance, in the advanced example, the posterior on the radius and the angle is a gaussian times a uniform, instead of a more complicated gaussian ring. This is done in a simple way at the end of the example. Let us discuss the general case here.
To enable this, cobaya creates a re-parameterization layer between the sampled parameters, and the input parameters of the likelihood. E.g. if we want to sample from the logarithm of an input parameter of the likelihood, we would do:
params:
logx:
prior: [...]
drop: True
x: "lambda logx: np.exp(logx)"
y:
derived: "lambda x: x**2"
When that information is loaded cobaya will create an interface between two sets of parameters:
Sampled parameters, i.e. those that have a prior, including
logx
but notx
(it does not have a prior: it’s fixed by a function). Those are the ones with which the sampler interacts. Since the likelihood does not understand them, they must be dropped withdrop: True
if you are using any parameter-agnostic components.Likelihood input parameters: those that will be passed to the likelihood (or theory). They are identified by either having a prior and not being dropped, or having being assigned a fixed value or a function. Here,
x
would be an input parameter, but notlogx
.
We can use a similar approach to define dynamical derived parameters, which can depend
on input and sampled parameters. To distinguish their notation from that of input
parameters, we insert the functions defining them under a derived
property
(see the parameter y
in the example above).
Note
Dynamical derived parameters can also be functions of yet-undefined parameters. In that case, those parameters will be automatically requested from the likelihood (or theory code) that understands them.
Note
Also available are the \(\chi^2 = -2 \log \mathcal{L}\) of the used likelihoods, as chi2__[name], e.g.
likelihood:
my_like: [...]
params:
my_derived:
derived: "lambda chi2__my_like: [...]"
Note
By default, the values of dynamical input parameters (e.g. x
above) are saved
as if they were derived parameters. If you would like to ignore them, define them using
the following extended notation:
params:
x:
value: "lambda logx: np.exp(logx)"
derived: False
Note
If you want to fix the value of a parameter whose only role is being an argument of a
dynamically defined one and is not supposed to be passed to the likelihood, you need
to explicitly drop it. E.g. suppose that you want to sample from a likelihood that
depends on x
, but want to use log(x)
as the sampled parameter; you would do it
like this:
params:
logx:
prior: [...]
drop: True
x:
value: "lambda logx: np.exp(logx)"
Now, if you want to fix the value of logx
without changing the structure of the
input, do
params:
logx:
value: [fixed_value]
drop: True
x:
value: "lambda logx: np.exp(logx)"
Priors on theory-derived parameters
The prior block can only be used to define priors on parameters that are sampled, directly or indirectly. If you have a parameter computed by a theory code that you want put an additional prior on, this cannot be done with the prior block as the derived parameter is not defined until the theory is called. Instead, you can treat the prior as an additional likelihood.
For example, to add a Gaussian prior on a parameter omegam that is computed by a theory code (e.g. CAMB), you can use:
likelihood:
like_omm:
external: "lambda _self: stats.norm.logpdf(_self.provider.get_param('omegam'), loc=0.334, scale=0.018)"
requires: omegam
Vector parameters
If your theory/likelihood takes an array of parameters as an argument, you can define the individual components’ priors separately, and then combine them into an array of any shape using a dynamically defined parameter.
Notice that the individual components must have
drop: True
in order not to be passed down the pipeline, and the dynamically-defined
vector must carry derived: False
, since only numbers, not arrays, can be saved as
derived parameters.
You can see an example below, defining a Gaussian likelihood on the sum of two parameters, which are taken as components of a single array-like argument:
from scipy import stats
def gauss_band(x_vector):
return stats.norm.logpdf(
x_vector[0] + x_vector[1], loc=1, scale=0.02)
# NB: don't forget the 'drop: True' in the individual parameters
# and 'derived: False' in the vector parameters
info = {
"likelihood": {"band": gauss_band},
"params": {
"x": {"prior": {"min": 0, "max": 2}, "proposal": 0.1, "drop": True},
"y": {"prior": {"min": 0, "max": 2}, "proposal": 0.1, "drop": True},
"x_vector": {"value": lambda x, y: [x, y], "derived": False}},
"sampler": {"mcmc": None}}
Changing and redefining parameters; inheritance
As we will see in the likelihoods documentation, just by mentioning a likelihood, the parameters of its default experimental model are inherited without needing to re-state them.
But you may want to fix their value, re-define their prior or some other property in your input file. To do that, simply state you new parameter definition as you would normally do. For your convenience, if you do that, you don’t need to re-state all of the properties of the parameters (e.g. the latex label if just changing the prior).
As a general rule, when trying to redefine anything in a parameter, everything not re-defined is inherited, except for the prior, which must not be inheritable in order to allow re-defining sampled parameters into something else.
Just give it a try and it should work fine, but, in case you need the details:
Re-defining fixed into:
fixed: simply assign it a new value
sampled: define a prior for it (and optionally reference, label, etc.)
derived: mention the parameter and assign nothing to it (you may define a min, max or latex label, but not a prior)
Re-defining sampled into:
fixed: simply assign it a value
sampled: change any of prior/ref/latex, etc, to your taste; the rest are inherited from the defaults
derived: mention the parameter and assign nothing to it (you may define a min, max or latex label, but not a prior; the label is inherited from the defaults)
Re-defining derived into:
fixed: simply assign it a value
sampled: define a prior for it (and optionally reference, label, etc.)
derived: change any of prior/ref/latex, etc, to your taste; the rest are inherited from the defaults
prior
class
- class cobaya.prior.Prior(parameterization, info_prior=None)
Class managing the prior and reference pdf’s.
- d()
- Returns:
Dimensionality of the parameter space.
- bounds(confidence=1, confidence_for_unbounded=1)
Returns a list of bounds
[min, max]
per parameter, containing confidence intervals of a certainconfidence
level, centered around the median, by default (confidence=1
the full parameter range).For unbounded parameters, if
confidence=1
, one can specify some value slightly smaller than 1 forconfidence_for_unbounded
, in order to ensure that all bounds returned are finite.NB: If an external prior has been defined, the bounds given in the ‘prior’ sub-block of that particular parameter’s info may not be faithful to the externally defined prior. A warning will be raised in that case.
- Parameters:
confidence (float, default 1) – Probability mass contained within the returned bounds. Capped at 1.
confidence_for_unbounded (float, default 1) – Confidence level applied to the unbounded parameters if
confidence=1
; ignored otherwise.
- Returns:
bounds – Array of bounds
[min,max]
for the parameters, in the order given by the input.- Return type:
2-d array [[param1_min, param1_max], …]
- Raises:
LoggedError – If some parameters do not have bounds defined.
- sample(n=1, ignore_external=False, random_state=None)
Generates samples from the prior pdf.
If an external prior has been defined, it is not possible to sample from the prior directly. In that case, if you want to sample from the “default” pdf (i.e. ignoring the external prior), set
ignore_external=True
.- Returns:
Array of
n
samples from the prior, as vectors[value of param 1, ...]
.
- logps(x)
Takes a point (sampled parameter values, in the correct order).
- Return type:
List
[float
]- Returns:
An array of the prior log-probability densities of the given point or array of points. The first element on the list is the products of 1d priors specified in the
params
block, and the following ones (if present) are the priors specified in theprior
block in the same order.
- logp(x)
Takes a point (sampled parameter values, in the correct order).
- Returns:
The prior log-probability density of the given point or array of points.
- logps_internal(x)
Takes a point (sampled parameter values, in the correct order).
- Return type:
float
- Returns:
The prior log-probability density of the given point or array of points, only including the products of 1d priors specified in the
params
block, no external priors
- logps_external(input_params)
Evaluates the logprior using the external prior only.
- Return type:
List
[float
]
- covmat(ignore_external=False)
- Returns:
The covariance matrix of the prior.
- set_reference(ref_info)
Sets or updates the reference pdf with the given parameter input info.
ref_info
should be a dict{parameter_name: [ref definition]}
, not{parameter_name: {"ref": [ref definition]}}
.When called after prior initialisation, not mentioning a parameter leaves its reference pdf unchanged, whereas explicitly setting
ref: None
sets the prior as the reference pdf.You can set different reference pdf’s/values for different MPI processes, e.g. for fixing different starting points for parallel MCMC chains.
- property reference_is_pointlike: bool
Whether there is a fixed reference point for all parameters, such that calls to
Prior.reference()
would always return the same.
- reference(max_tries=inf, warn_if_tries='10d', ignore_fixed=False, warn_if_no_ref=True, random_state=None)
- Return type:
ndarray
- Returns:
One sample from the ref pdf. For those parameters that do not have a ref pdf defined, their value is sampled from the prior.
If ignored_fixed=True (default: False), fixed reference values will be ignored in favor of the full prior, ensuring some randomness for all parameters (useful e.g. to prevent caching when measuring speeds).
NB: The way this function works may be a little dangerous: if two parameters have an (external) joint prior defined and only one of them has a reference pdf, one should sample the other from the joint prior conditioned to the first one being drawn from the reference. Otherwise, one may end up with a point with null prior pdf. In any case, it should work for getting initial reference points, e.g. for an MCMC chain.
- reference_variances()
- Returns:
The standard variances of the 1d ref pdf’s. For those parameters that do not have a proposal defined, the standard deviation of the prior can be taken as a starting point to estimate one.