Skip to content

EpiAware/ReparameterisedDistributions.jl

Repository files navigation

ReparameterisedDistributions.jl ReparameterisedDistributions logo

Documentation Build Status Code Quality License & DOI Downloads
Stable Dev Test codecov AD SciML Code Style Aqua QA JET License: MIT Downloads Downloads
ForwardDiff ReverseDiff (tape) Enzyme forward Enzyme reverse Mooncake reverse Mooncake forward
cov ForwardDiff cov ReverseDiff cov Enzyme forward cov Enzyme reverse cov Mooncake reverse cov Mooncake forward

Parameter-convention switches for Distributions.jl.

Why ReparameterisedDistributions?

Distributions.jl parameterises each family by its native parameters: a Gamma by shape and scale, a LogNormal by the mean and standard deviation of its logarithm. Modellers rarely reason in those coordinates. A delay distribution is elicited as a mean and a standard deviation, and a prior belongs on the mean, not on a shape parameter that only implies one.

A prior on a moment cannot be expressed through a native leaf, because independent priors on shape and scale do not compose into a prior on the mean. This package wraps a distribution so that its moments are its parameters: the wrapper reports the moments as the estimable parameters, converts to the native distribution internally through an exact closed form, and stays differentiable so the moments can be sampled directly.

Getting started

For the full walkthrough — every supported parameterisation, how to register a new one, and the AD backends it is checked against — see the Getting started documentation.

The package is not yet registered. Install it from the repository:

using Pkg
Pkg.add(url = "https://github.com/EpiAware/ReparameterisedDistributions.jl")

reparameterise returns a distribution whose parameters are the moments:

using ReparameterisedDistributions, Distributions

d = reparameterise(LogNormal; mean = 8.0, sd = 2.0)

params(d)      # (8.0, 2.0) — the moments, not the native (mu, sigma)
mean(d)        # 8.0
std(d)         # 2.0
logpdf(d, 7.5)

It is an ordinary Distribution, so it evaluates and samples exactly as the native one does, and it goes on the right of a ~. Because the moments are the parameters, a model puts its priors on them and the sampler moves in moment coordinates:

using Turing

@model function delays(x)
    m ~ LogNormal(2.0, 0.5)
    s ~ truncated(Normal(2.0, 1.0); lower = 0.1)
    for i in eachindex(x)
        x[i] ~ reparameterise(LogNormal; mean = m, sd = s, check_args = false)
    end
end

The chain comes back in m and s — a mean and a standard deviation — rather than in native parameters that only imply them. The conversion is exact algebra, so it is differentiable and the gradient with respect to the moments is exact. The package is tested against ForwardDiff, ReverseDiff, Enzyme (forward and reverse) and Mooncake (forward and reverse).

Supported parameterisations

Family Parameters Conversion
LogNormal mean, sd the moments of the distribution, not of its logarithm
LogNormal mean, var as above, given the variance
Gamma mean, sd scale = var / mean, shape = mean² / var
Gamma mean, var as above, given the variance
Gamma mean, shape scale = mean / shape; the shape is native
Gamma shape, rate scale = 1 / rate; the shape is native
NegativeBinomial mean, overdispersion var = mean + overdispersion · mean²
NegativeBinomial mean, dispersion var = mean + mean² / dispersion, the reciprocal convention
Exponential rate scale = 1 / rate
SkewNormal centre, scale, mass_below_centre alpha = tan(π · (1/2 − mass_below_centre))

The NegativeBinomial parameterisations are the two epidemiology reaches for: the overdispersion is the excess variance relative to a Poisson, so it tends to the Poisson limit as it goes to zero; the dispersion is its reciprocal (dispersion = 1 / overdispersion), so it tends to the Poisson limit as it goes to infinity instead. The wrapper stays discrete — its value support is taken from the family it wraps.

The Exponential and Gamma rate parameterisations let a distribution be specified, reported and estimated directly by its rate rather than by a scale hand-inverted from it — the natural coordinates for a hazard.

The SkewNormal parameterisation is keyed on an elicitation quantity rather than a moment: the probability mass falling below a reference point. That mass depends only on the native shape for the untruncated family, so it inverts exactly; the docstring notes that the elicited fraction is exact only before any truncation. Distributions.jl does not implement cdf/quantile for SkewNormal (Owen's T function is not implemented there), a limitation this parameterisation inherits rather than works around.

Adding a family is one to_native method (the closed form) and one _valid_moments method (the guard), so a downstream package can register its own.

Rescaling a moment

rescale(d, factor) scales one of d's registered moments by factor, holding the others fixed, routing through whichever parameterisation d was built under:

using ReparameterisedDistributions, Distributions

d = reparameterise(Gamma; mean = 8.0, shape = 2.0)
mean(rescale(d, 2.0))                      # 16.0 — shape stays at 2.0

nb = reparameterise(NegativeBinomial; mean = 10.0, overdispersion = 0.5)
mean(rescale(nb, 3.0))                     # 30.0 — a discrete family, scaled
                                            # in moment coordinates rather than
                                            # by an affine transform of the
                                            # native support

parameter defaults to :mean and can name any of d's registered parameters; naming one that is not registered for d's family raises a DomainError rather than applying the factor under different semantics.

Related packages

Where to learn more

Contributing

We welcome contributions and new contributors! Please open an issue or pull request on GitHub. This package follows ColPrac and the SciML style.

How to cite

If you use ReparameterisedDistributions in your work, please cite it. Citation metadata lives in CITATION.cff, which GitHub renders as a "Cite this repository" button on the repository page.

Code of conduct

Please note that the ReparameterisedDistributions project is released with a Contributor Code of Conduct. By contributing, you agree to abide by its terms.

About

Switching paramterisations between.

Resources

License

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

3 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages