ReparameterisedDistributions.jl
Parameter-convention switches for Distributions.jl.
Why ReparameterisedDistributions?
A delay can be elicited as a mean and a standard deviation, but Distributions.jl names each family by its native parameters, so those are not the coordinates a model has to be written in.
Independent priors on a shape and a scale imply a prior on the mean that was never chosen, and is usually not the one that was meant.
reparameterisemakes the moments a distribution's parameters, so a prior can be put on the mean directly.The wrapper is an ordinary
Distributionand stays differentiable, so the moments can be sampled directly inside a model.
Getting started
See the Getting started documentation for every supported parameterisation.
using Pkg
Pkg.add("ReparameterisedDistributions")reparameterise returns a distribution whose parameters are the moments, so a prior goes on the mean rather than on a shape that only implies one.
using ReparameterisedDistributions, Distributions, Turing, Random
Random.seed!(1)
truth = reparameterise(Gamma; mean = 8.0, sd = 3.0)
y = rand(truth, 200)
@model function delay(y)
delay_mean ~ truncated(Normal(8.0, 4.0); lower = 0.0)
delay_sd ~ truncated(Normal(3.0, 2.0); lower = 0.0)
y .~ reparameterise(Gamma; mean = delay_mean, sd = delay_sd)
end
chain = sample(delay(y), NUTS(), 500; progress = false)
summarystats(chain)Summary Statistics
parameters mean std mcse ess_bulk ess_tail rhat e ⋯
Symbol Float64 Float64 Float64 Float64 Float64 Float64 ⋯
delay_mean 8.0778 0.2407 0.0142 289.8410 329.6722 1.0011 ⋯
delay_sd 3.2642 0.1846 0.0115 258.2991 247.9024 1.0012 ⋯
1 column omittedThe chain comes back in a mean and a standard deviation, the coordinates the delay was elicited in, rather than in native parameters that only imply them.
using CairoMakie, AlgebraOfGraphics, DataFramesMeta
CairoMakie.activate!(type = "png", px_per_unit = 2)
draws = DataFrame(
value = vcat(vec(chain[:delay_mean]), vec(chain[:delay_sd])),
moment = vcat(fill("mean", length(chain[:delay_mean])),
fill("sd", length(chain[:delay_sd])))
)
actual = DataFrame(moment = ["mean", "sd"], value = [8.0, 3.0])
draw(
data(draws) * mapping(:value, layout = :moment) *
AlgebraOfGraphics.density() +
data(actual) * mapping(:value, layout = :moment) *
visual(VLines, color = :black, linestyle = :dash);
facet = (; linkxaxes = :none)
)
Related packages
ComposedDistributions.jl builds delay distributions by composing leaves; a reparameterised leaf carries its moments as its parameters, so a prior sits on a component's mean rather than on a native shape.
ConvolvedDistributions.jl, ModifiedDistributions.jl and CensoredDistributions.jl build the convolved, transformed and censored distributions this package can wrap in moment coordinates for fitting.
DistributionsInference.jl is the emerging fit-protocol layer across the EpiAware distribution packages, where reparameterising to estimable moments is most useful.
Distributions.jl supplies the native families whose parameterisation this package switches.
Where to learn more
Getting started, for the full walkthrough.
EpiAware, the wider ecosystem this package belongs to.
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.