prior

pmrf.parameters.prior(tree, names: str | Sequence[str] | Callable[[Any], Any], distribution: AbstractDistribution, space: Literal['raw', 'declared', 'physical'] = 'declared', *, truncate: Literal['normalised', 'unnormalised'] = 'normalised')

Returns a copy of a model with a prior attached to the parameters names selects.

This attaches a prior after construction, instead of rebuilding a parameter with Random(). The distribution’s event size decides how it is attached:

  • Scalar event: each selected parameter gets its own prior, exactly as if it had been built with Random(). Its raw space becomes the new prior’s whitening. The prior is truncated to the parameter’s validity and renormalised, so the validity still holds. A prior whose support already lies inside the validity is kept as given.

  • Event size equal to the total size of the selected parameters: a joint prior over them. The tree is wrapped, unchanged, in a pmrf.modules.Probabilistic (inside a pmrf.models.Wrapped if tree is a pmrf.Model, so RF methods stay available). Every parameter keeps its name and stays a parameter. The distribution’s vector is their values, each flattened in C order, concatenated in name order: with a sequence of exact names, that order; a glob, or a callable, expands to sorted names. A parameter’s own shape is its declared shape when the prior is attached; leading axes beyond it, as in a batched model, are batch axes.

  • Anything else raises.

A parameter’s bounds combine its validity, the constraint of the model field it was passed to (see param()), which always holds, with its range: a Bounded() interval, a constraint given to Random() or Constrained(), or a Random() distribution’s own support. A range is prior information, so a prior over declared or physical space replaces it, along with any prior the parameters already had, and keeps their validity. A prior over raw space keeps their range, since it reaches declared space through it. Their value, scale, name, metadata and fixed state are kept.

A joint prior over declared or physical space must have its support inside the parameters’ validity by default. Set truncate='unnormalised' to keep the supplied density unchanged inside that validity and assign zero density outside; ParamRF does not calculate a truncation normaliser. This option is only available for declared- or physical-space joint priors, and those priors cannot be sampled or used as evidence. For a joint prior, log_prior() scores the parameters jointly in place of their own priors: over raw space these stay attached but unused, and otherwise they are dropped with the range. A value outside a parameter’s validity scores minus infinity.

Attaching a joint prior redefines raw space for its parameters as the distribution’s whitened space, inferred as for a one-dimensional prior: a flow’s base, the Cholesky-whitened space of a multivariate normal, and so on. Where no whitening is known, raw is the distribution’s own space. Each parameter’s raw value, in values(), update() and log_prior(), is its slice of that vector in its own shape, so optimisers and samplers move in well-conditioned coordinates.

A parameter under a joint prior cannot be fixed or tied, and cannot be under a second prior.

Parameters:
  • tree (PyTree) – A model, or any collection of models and parameters.

  • names (str, Sequence[str] or Callable) – The parameters to attach the prior to, as for update(): a name, an fnmatch glob over names, a sequence of them, or a callable returning nodes of tree. An unknown name raises; a glob matching nothing selects nothing.

  • distribution (AbstractDistribution) – The prior. See pmrf.stats.distributions.

  • space ({'declared', 'physical', 'raw'}, default='declared') – The space distribution is over. 'raw' is the parameters’ raw space as it was just before this call, as values() returned it with space='raw'. The prior is mapped to declared space, with its change-of-variables term, and a prior over raw space keeps the mapping from that raw space to declared space. A hypercube sampler maps a mapped one-dimensional prior through its base’s inverse CDF, so the base needs one.

  • truncate ({'normalised', 'unnormalised'}, default='normalised') – How a declared- or physical-space joint prior whose support leaves a selected parameter’s validity is treated. 'normalised' requires the full support to lie inside every validity. 'unnormalised' retains the supplied density in the valid region and gives out-of-validity values zero density, without renormalising it. This is for MAP and linearisation only; sampling is rejected.

Returns:

The copy, with the selected parameters’ priors replaced.

Return type:

PyTree

Raises:

ValueError – If a name is unknown, space is unknown, the event size is neither scalar nor the total size of the selected parameters, the prior has to be truncated to the validity and cannot be, or a selected parameter is already under a joint prior. For a joint prior, also if a selected name is not a free parameter (a fixed or frozen parameter raises, and a tie’s target is not a parameter at all), or, over 'declared' or 'physical' space with truncate='normalised', the distribution’s support leaves a selected parameter’s validity in any element. truncate='unnormalised' raises for a scalar-event prior or for a joint prior over raw space. A support Parax cannot determine counts as unbounded.

Examples

from pmrf.parameters.constraints import Positive
from pmrf.stats.distributions import Normal

class Line(prf.Model):
    w: prf.Param = prf.param(constraint=Positive())   # validity

line = Line(prf.Bounded(1.0, 5.0, value=2.0), name='line')   # a range
model = prf.prior(line, 'w', Normal(2.0, 3.0))
prf.params(model)['w'].distribution   # Normal(2, 3) truncated to [0, inf)
prf.params(model)['w'].bounds         # (0.0, inf): the range is replaced

A joint prior, here the posterior of an earlier fit over two parameters:

model = prf.prior(model, ['a.R', 'b.R'], posterior, space='raw')
prf.params(model)   # the same names as before