# Custom bijector in TuringLang Bijectors

**URL:** https://discourse.julialang.org/t/custom-bijector-in-turinglang-bijectors/105278
**Category:** Probabilistic Programming
**Tags:** question, turing, machine-learning
**Created:** [October 22, 2023, 1:24pm UTC](https://discourse.julialang.org/t/custom-bijector-in-turinglang-bijectors/105278 "2023-10-22T13:24:13Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![hanyas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hanyas/32/51078_2.png) [@hanyas](https://discourse.julialang.org/u/hanyas)
#### Post date: [October 22, 2023, 1:24pm UTC](https://discourse.julialang.org/t/custom-bijector-in-turinglang-bijectors/105278/1 "2023-10-22T13:24:13Z")

</div>

I am new to Julia and I am trying to use the Bijectors.jl package to define a `tanh` bijector. Looking through the doc and the code, I came up with different versions of the following

```julia
struct Tanh <: Bijectors.Bijector end

(b::Tanh)(x::Real) = tanh(x)
(b::Tanh)(x::AbstractArray) = @. tanh(x)

(ib::Bijectors.Inverse{<: Tanh})(y::Real) = atanh(y)
(ib::Bijectors.Inverse{<: Tanh})(y::AbstractArray) = @. atanh(y)

function with_logabsdet_jacobian(b::Tanh, x::Real)
    transformed = tanh(x)
    log_det_jacobian = 2.0 * (log(2.0) - x - softplus(-2.0 * x))
    return (result=transformed, logabsdetjac=log_det_jacobian)
end

function with_logabsdet_jacobian(b::Tanh, x::AbstractArray)
    transformed = @. tanh(x)
    log_det_jacobian = 2.0 .* (log(2.0) .- x .- softplus.(-2.0 .* x))
    return (result=transformed, logabsdetjac=log_det_jacobian)
end

Bijectors.logabsdetjac(b::Tanh, x) = last(with_logabsdet_jacobian(b, x))

```

The forward transformation appears to be working, however combining the bijector with a `transformed` distribution runs into a stack overflow when I call the `logpdf` function

```julia
using Random
using Distributions
using LinearAlgebra
import Bijectors
using LogExpFunctions: softplus

dist = Distributions.MvNormal(zeros(1), LinearAlgebra.I)
td = Bijectors.transformed(dist, Tanh())

y = Random.rand(td)
lp = Distributions.logpdf(td, y)

```

```julia
ERROR: StackOverflowError:
Stacktrace:
     [1] with_logabsdet_jacobian(ib::Bijectors.Inverse{Tanh}, y::Vector{Float64})
       @ Bijectors ~/.julia/packages/Bijectors/QhObI/src/interface.jl:213
     [2] transform(t::Bijectors.Inverse{Tanh}, x::Vector{Float64})
       @ Bijectors ~/.julia/packages/Bijectors/QhObI/src/interface.jl:92
--- the last 2 lines are repeated 39990 more times ---
 [79983] with_logabsdet_jacobian(ib::Bijectors.Inverse{Tanh}, y::Vector{Float64})
       @ Bijectors ~/.julia/packages/Bijectors/QhObI/src/interface.jl:213

```

Any ideas what what I’ve gotten wrong here?

---

<div class="post-metadata">

### Author: ![hanyas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hanyas/32/51078_2.png) [@hanyas](https://discourse.julialang.org/u/hanyas)
#### Post date: [October 22, 2023, 3:26pm UTC](https://discourse.julialang.org/t/custom-bijector-in-turinglang-bijectors/105278/2 "2023-10-22T15:26:53Z")

</div>

The following definition appears to work although I don’t really know why. Would still appreciate an explanation.

```julia
struct Tanh <: Bijectors.Bijector end

# (b::Tanh)(x::Real) = tanh(x)
# (b::Tanh)(x::AbstractArray) = @. tanh(x)

# (ib::Bijectors.Inverse{<: Tanh})(y::Real) = atanh(y)
# (ib::Bijectors.Inverse{<: Tanh})(y::AbstractArray) = @. atanh(y)

Bijectors.transform(b::Tanh, x) = tanh(x)
Bijectors.transform(b::Tanh, x::AbstractArray) = @. tanh(x)

Bijectors.transform(ib::Bijectors.Inverse{<:Tanh}, y) = atanh(y)
Bijectors.transform(ib::Bijectors.Inverse{<:Tanh}, y::AbstractArray) = @. atanh(y)

function with_logabsdet_jacobian(b::Tanh, x::Real)
    y = tanh(x)
    ldj = 2.0 * (log(2.0) - x - softplus(-2.0 * x))
    return (result=y, logabsdetjac=ldj)
end

function with_logabsdet_jacobian(b::Tanh, x::AbstractArray)
    y = @. tanh(x)
    ldj = @. 2.0 * (log(2.0) - x - softplus(-2.0 * x))
    return (result=y, logabsdetjac=only(ldj))
end

```

---

<div class="post-metadata">

### Author: ![Red-Portal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/red-portal/32/9102_2.png) [@Red-Portal](https://discourse.julialang.org/u/Red-Portal)
#### Post date: [November 20, 2023, 6:36pm UTC](https://discourse.julialang.org/t/custom-bijector-in-turinglang-bijectors/105278/3 "2023-11-20T18:36:38Z")

</div>

@torfjelde
