# Constrained Priors and Bijectors

**URL:** https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141
**Category:** Probabilistic Programming
**Created:** [November 12, 2022, 12:51am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141 "2022-11-12T00:51:01Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![marcobonici](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcobonici/32/20549_2.png) [@marcobonici](https://discourse.julialang.org/u/marcobonici)
#### Post date: [November 12, 2022, 12:51am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/1 "2022-11-12T00:51:01Z")

</div>

Hi to everybody!  
I have been using AdvancedHMC NUTS implementation and I am quite satisfied with the result I am obtaining.

The model I am trying to study is quite simple

```julia
logℓ(θ) = logpdf(MvNormal(data, mycov), theory(θ))

```

where `theory(θ)` is a function that computes the theoretical prediction of my model given the value of the parameters `θ`.  
Now I’d like to put priors on some parameters. For some of them I am using a `Normal`, but for some of them I’d like to put a `Uniform` distribution.  
As far as I understand, samplers such as NUTS require that the likelihood has a support on ℝ. This issue can be solved using Bijectors.jl.  
For instance, let’s say I want to put the following prior

```julia
Uniform(-2,2)

```

Then, using `Bijectors`, I can define

```julia
b = bijector(Uniform(-2,2))
b⁻¹ = Bijectors.Inverse(b)

```

Let’s assume for simplicity the I have a single parameter for my model. Then I can write

```julia
logℓ(θ) = logpdf(MvNormal(data, mycov), theory(b⁻¹ (θ)))+logpdf(Uniform(-2,2), b⁻¹ (θ))

```

Is this right of I am doing something wrong?  
Thank you,  
Marco

---

<div class="post-metadata">

### Author: ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)
#### Post date: [November 12, 2022, 1:35am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/2 "2022-11-12T01:35:02Z")

</div>

You might consider just shelling out for a PPL, which for your description above is super simple, in pseudo-code could be something like:

```julia
using Turing
@model function mymodel()
    θ ~ Uniform(-2, 2)
    d ~ MvNormal(theory(θ), mycov) 
end
problem = condition(mymodel(), (d = mydata,))
samples = sample(problem, HMC())

```

and Turing (or whatever library you choose, like Soss, Tilde…) will handle the bijections for you (including jacobian factors which I’m not sure you had) and you can play with the prior without much thinking.

---

<div class="post-metadata">

### Author: ![marcobonici](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcobonici/32/20549_2.png) [@marcobonici](https://discourse.julialang.org/u/marcobonici)
#### Post date: [November 12, 2022, 2:06am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/3 "2022-11-12T02:06:50Z")

</div>

Hi @marius311 ! Thank you for your answer:)  
Yeah, for sure I have to add the jacobian to account for the change of variable 😬  
Also, I have already tried using Turing as you suggested and it kind of works.  
My only problem regards some details.  
For instance, when reading [Turing API](https://turing.ml/v0.21/docs/library/#Turing.Inference.NUTS), it looks that several options that I can find in [AdvancedHMC](https://beta.turing.ml/AdvancedHMC.jl/dev/api/), are not present. For instance, I’d like to define the mass matrix using some previously computed Fisher Matrix, specify which kind of adaptation algorithm I am gonna use…  
Probably I am missing something, but I am not able to do the same within Turing… 😭

---

<div class="post-metadata">

### Author: ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)
#### Post date: [November 12, 2022, 2:42am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/4 "2022-11-12T02:42:48Z")

</div>

Maybe you can track down how to do it from here, seems like this added it?: [Add dense pre-conditioner by xukai92 · Pull Request #607 · TuringLang/Turing.jl · GitHub](https://github.com/TuringLang/Turing.jl/pull/607)

---

<div class="post-metadata">

### Author: ![marcobonici](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcobonici/32/20549_2.png) [@marcobonici](https://discourse.julialang.org/u/marcobonici)
#### Post date: [November 12, 2022, 3:14am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/5 "2022-11-12T03:14:44Z")

</div>

I’ll give it a check tomorrow. Now I am too much tired 😓  
Thank you again for your suggestions…I think that I’ll also give a look inside Turing repo.

---

<div class="post-metadata">

### Author: ![marcobonici](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcobonici/32/20549_2.png) [@marcobonici](https://discourse.julialang.org/u/marcobonici)
#### Post date: [November 12, 2022, 3:29am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/6 "2022-11-12T03:29:15Z")

</div>

Also: one of the things that makes me wonder if this is possible, is that in [pathfinder](https://mlcolab.github.io/Pathfinder.jl/stable/examples/turing/) @sethaxen writes

> To use Pathfinder’s estimate of the metric and skip warm-up, at the moment one needs to use AdvancedHMC directly.

But maybe it’s better to check tomorrow😅

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [November 12, 2022, 9:43am UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/7 "2022-11-12T09:43:12Z")

</div>

When using `Bijectors` you will need to add the Jacobian correction. For a single parameter, sampling from a uniform distribution could be done as follows:

```julia
function logL(θu) # θu is unconstrained parameter
    pd = Uniform(-2, 2) # desired density on constrained space
    bu2c = Inverse(bijector(pd)) # bijector from unconstrained to constraint space
    θc, ladj = with_logabsdet_jacobian(bu2c, θu[1]) # get constrained parameter θc and log Jacobian
    logpdf(pd, θc) + ladj # corrected log density
end

```

What is not so nice about the approach is that the returned samples, i.e., via `AdvancedHMC`, live on the unconstrained space, i.e., you may want to use the bijector `bu2c` on them before plotting.

The following rule of thumb might be helpful to remember if the log Jacobian needs to be added or subtracted (which I tend to forget):

p(c) \; dc = p(u) \; du \implies p(u) = p(c) \; \frac{dc}{du},

i.e., the density on the unconstrained space p(u) - as required by the sampler - is the density on the constrained space p(c) - naturally defined in the model - times the Jacobian of the bijector from the unconstrained to the constrained space.

---

<div class="post-metadata">

### Author: ![sethaxen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sethaxen/32/35604_2.png) [@sethaxen](https://discourse.julialang.org/u/sethaxen)
#### Post date: [November 12, 2022, 7:07pm UTC](https://discourse.julialang.org/t/constrained-priors-and-bijectors/90141/8 "2022-11-12T19:07:21Z")

</div>

No, currently it’s not possible to set the mass matrix through the Turing interface. This PR will eventually solve that, though currently it’s delayed by some AdvancedHMC refactors I haven’t had time for: [Allow more AdvancedHMC options in HMC types by sethaxen · Pull Request #1818 · TuringLang/Turing.jl · GitHub](https://github.com/TuringLang/Turing.jl/pull/1818)
