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/or max 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, or halfnorm for a half-gaussian.

  • loc and scale (default: 0 and 1, resp.): the location and scale of the pdf, as they are understood for each particular pdf in scipy.stats; e.g. for a uniform pdf, loc is the lower bound and scale is the length of the domain, whereas in a gaussian (norm) loc is the mean and scale is the standard deviation.

  • Additional specific parameters of the distribution, e.g. a and b 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:

  1. As a function, either assigning a function defined with def, or a lambda. Its arguments must be known parameter names.

  2. As a string, which will be passed to eval(). The string can be a lambda function definition with known parameters as its arguments (you can use scipy.stats and numpy as stats and np resp.), or an import_module('filename').function statement if your function is defined in a separate file filename in the current folder and is named function (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 not x (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 with drop: 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 not logx.

_images/diagram.svg

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(x)"

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(x)"

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 certain confidence 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 for confidence_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 the prior 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.