Usage with distributions
Bijectors provides many utilities for working with probability distributions.
using Bijectors
dist = LogNormal()
x = rand(dist)
b = bijector(dist) # bijection (0, ∞) → ℝ
y = b(x)1.0911565677233277Here, bijector(d::Distribution) returns the corresponding constrained-to-unconstrained bijection for Beta, which is a log function. The resulting bijector can be called, just like any other function, to transform samples from the distribution to the unconstrained space.
The function link provides a short way of doing the above:
link(dist, x) ≈ b(x)trueSee the Turing.jl docs for more information about how this is used in probabilistic programming.
Transforming distributions
We can also couple a distribution together with its bijector to create a transformed Distribution, i.e. a Distribution defined by sampling from a given Distribution and then transforming using a given transformation:
dist = LogNormal() # support on (0, ∞)
tdist = transformed(dist) # support on ℝUnivariateTransformed{LogNormal{Float64}, Base.Fix1{typeof(broadcast), typeof(log)}}(
dist: LogNormal{Float64}(μ=0.0, σ=1.0)
transform: Base.Fix1{typeof(broadcast), typeof(log)}(broadcast, log)
)
We can then sample from, and compute the logpdf for, the resulting distribution:
y = rand(tdist)1.7542258572904934logpdf(tdist, y)-2.4575927123979557We should expect here that
logpdf(tdist, y) ≈ logpdf(dist, x) - logabsdetjac(b, x)where b = bijector(dist) and y = b(x).
To verify this, we can calculate the value of x using the inverse bijector:
b = bijector(dist)
binv = inverse(b)
x = binv(y)5.778972260605668(Because b is just a log function, binv is an exponential function, i.e. x = exp(y).)
Then we can check the equality:
logpdf(tdist, y) ≈ logpdf(dist, x) - logabsdetjac(b, x)trueYou can also use Bijectors.logpdf_with_trans with the original distribution:
logpdf_with_trans(dist, x, false) ≈ logpdf(dist, x)truelogpdf_with_trans(dist, x, true) ≈ logpdf(tdist, y)true