TuringLang / Bijectors.jl

Implementation of normalising flows and constrained random variable transformations
https://turinglang.org/Bijectors.jl/
MIT License
196 stars 32 forks source link

Radial flow to a simplex #291

Closed theogf closed 8 months ago

theogf commented 8 months ago

Hey!

I tried to make a "radial flow in a simplex" with the following code:

using Bijectors, Distributions, CairoMakie, LinearAlgebra
d = MvNormal(zeros(2), I(2))
z_0 = zeros(length(d))
α = -6.7
β = 0.4
r = RadialLayer(α, β, z_0)
dr = transformed(d, r)
ddr = transformed(dr, inverse(bijector(SimplexDistribution(3, 1.0))))
ax = 0:0.01:1
pts = [[x, y] for x in ax for y in ax if x + y < 1]
vals = [[x, y, 1 - x - y] for (x, y) in pts]
Z = pdf.(Ref(ddr), vals)
scatter(Point2.(pts), color=Z)

Which results in the following plot: image

Which is more or less what I want, however I am a bit surprised by the asymmetry of it. Should this be expected?

torfjelde commented 8 months ago

So I don't think this is an issue with the RadialFlow:

d = MvNormal(zeros(2), I(2))
b = inverse(bijector(Dirichlet(ones(3))))

# RadialLayer
z_0 = zeros(length(d))
α = 0
β = 1
r = RadialLayer(α, β, z_0)

# Without simplex.
xs = eachcol(rand(transformed(d, r), 10000))
histogram2d(first.(xs), Base.Fix2(getindex, 2).(xs), nbins=50)

results in

tmp

So it's indeed symmetric.

The "issue" I guess is that the simplex bijector is not. The transformation is described here: https://mc-stan.org/docs/reference-manual/simplex-transform.html

It's not immediately obvious to me why this would be symmetric, though the resulting distribution indeed looks symmetric if you use a zero-mean isotropic Gaussian as the base.

I think @sethaxen might be the best guy to answer this:)

sethaxen commented 8 months ago

All stick-breaking transforms are indeed not symmetric. There are symmetric transforms on the simplex though (in particular, several softmax-based transforms, e.g. the additive log ratio transform from compositional data analysis), though some are better for MCMC than others. How important is this symmetry to you?

theogf commented 8 months ago

@sethaxen Quite crucial, my general goal is to have some kind of circular prior in the simplex, but all components should have equal chances. Since the bijection aspect is not so important to me, I could try using the softmax approach.

theogf commented 8 months ago

Since it's not a bug but just a specificity of the model used I will close this issue

sethaxen commented 8 months ago

Cool, just don't use softmax directly, as it's not bijective. You might want to try out "NormalizedExponential" or "AugmentedSoftmax" here: https://github.com/mjhajharia/transforms/tree/main/transforms/simplex . Both are bijective by augmenting softmax with logsumexp, but they do different things to the inputs to softmax to try to improve the geometry, and they use different priors for the discarded parameter (the output of logsumexp).