Inspecting automatic transformations in MCMC

I’m a numpyro newbie so would like some help confirming the details of automatic transformations in MCMC.

I want to use HMC in numpyro for inferring posterior parameter distributions using constrained uniform priors. I understand from the docs numpyro will automatically transform the priors from constrained to unconstrained and then automatically do the inverse transform when I request the samples. I expect the transform to be a composition of an affine and sigmoid transformation. How can I verify this in the code?

Here is my mwe:

import jax.numpy as jnp
import jax.random as jnpr
from numpyro import (distributions as dist, infer, sample, set_host_device_count)
from numpyro.infer.util import get_transforms

def make_synthetic_data(rng, true_values, obs_sigma_sq, N):
    lower, upper = 0, 10
    x = np.sort(rng.uniform(lower, upper, N))
    y = true_values["m1"] * x + true_values["c"]
    yerr = np.full(N, obs_sigma_sq)
    y += yerr * rng.standard_normal(size=N)
    return x, y, yerr

def linear_model(X, yerr, y=None):
    c = sample("c", dist.Uniform(-1.0, 1.0))
    m1 = sample("m1", dist.Uniform(0.1, 5.0))
    theta = jnp.array([c, m1])
    mu = jnp.dot(X, theta)
    sample("obs", dist.Normal(mu, yerr), obs=y)

seed = 1234
rng = np.random.default_rng(seed)
key = jnpr.PRNGKey(seed)
set_host_device_count(2)
N = 50
unknowns = {"c": (-1, 1), "m1": (0.1, 5.0)}
tvs = {"c": 0.2, "m1": 2.1}

x, y_obs, yerr = make_synthetic_data(rng, tvs, 0.01, N)
X_obs = np.vander(x, 2, increasing=True)
sampler = infer.MCMC(
    infer.NUTS(linear_model),
   num_warmup=2000,
   num_samples=2000,
   num_chains=2,
   progress_bar=True,
)
sampler.run(key, X_obs, yerr, y=y_obs)
samples = sampler.get_samples()["c"]

transforms = get_transforms(model=linear_model, model_args=(X_obs, yerr, y_obs),
                            model_kwargs={}, params=tvs)

x_unconstrained = 100.0
x_constrained = transforms["c"](x_unconstrained)
print(f"{x_unconstrained} -> {x_constrained}")

The code shows how to retrieve samples from the constrained space and how to retrieve the composed transformations for each parameter. My specific questions are:

  • How to get samples in unconstrained space? Do I have to apply the inverse transform or can I retrieve them directly from sampler?
  • transforms["c"] is a composition. How can I decompose this so I can verify an affine and sigmoid transformation have been used?
  • Where in the numpyro code are the transforms identified and composed?

Any help would be greatly appreciated.