This is an extract from a notebook available at this location on Github.

We will make a simple hierarchical probabilistic model and illustrate:

  • the shrinkage of uncertainties on individual objects in the presence of population parameters,
  • the way the likelihood function must be modified to account for selection effects (here a cut on the signal-to-noise ratio of the data points),
  • use Hamiltonian Monte Carlo to perform a very efficient parameter inference


Some basic knowledge of Bayes theorem, parameter inference via MCMC, hierarchical probabilistic models, and Hamiltonian Monte Carlo.


Our model will consist of:

  • one population parameter , describing the distribution of values via ,
  • a set of true (unobserverd, or latent) variables drawn from ,
  • a set of noisy, observed variables drawn from ,
  • a set of noise levels, described by , which are given / fixed,
  • a selection effect S, for example a cut on signal-to-noise ratio (SNR) applied to the noisy variables .

Let us draw the model corresponding to this description:


Parameter inference (without selection effects)

We want to infer and from .

The posterior distribution on those parameters, via Bayes’ theorem applied to the hierarchical model, is:

The denominator (the evidence, or marginalized likelihood) can be dropped since it is constant w.r.t. the parameters of interest. We are only interested in exploring the interesting region of the posterior distribution, not its overall scale (which we would need for model comparison/selection).

is the likelihood function. is the population model, the prior.

Parameter inference (with selection effects)

We now assume that the data have been selected according to a selection effect or cut which will affect the parameters of interest (otherwise it would not affect any of the probabilisties and it could be dropped).

The posterior distribution on the parameters is now:

The term is a new likelihood function (a slight abuse of terminology), modified by selection effects:

The term is constant. The real selection function is implemented in .

The other term,


captures the way the original likelihood function is modified due to selection effects.

Example: Gaussian noise and SNR cut

In many cases, we will have


when the selection effects are simple and deterministic.

We now consider a simple signal-to-noise ratio (SNR) cut, with some threshold :

if , otherwise .

We also consider Gaussian noise, so that the likelihood function is simply


With this deterministic cut, the correction term of interest, , is a convolution:


leading to

So the final result, our new likelihood function for the hierarchical model, is

where are have dropped irrelevant multiplicative constant terms everywhere.

Lets test that with a simulation!

Let’s generate ’s from a Gaussian centered at , then add noise.

Let’s also apply a SNR cut, i.e. only keep objects that satisfy some SNR criterion.

We will infer (and the ) with the framework presented above.

We will check that neglecting the selection effects leads to a biased answer, and that the formulae above correctly mitigates this bias.

nobj = 1000
alpha, sigma_alpha = 10, 1 # some arbitrary values
x_i = alpha + sigma_alpha * np.random.randn(nobj) # Gaussian draws
sigma_i = np.random.uniform(sigma_alpha, sigma_alpha * 2, size=nobj) # uniform draws
y_i = x_i + sigma_i * np.random.randn(nobj)  # Gaussian draws from N(x_i, sigma_i)
# some grid for computing and plotting p(x\vert alpha), here a Gaussian.
x_grid = np.linspace(np.min(y_i), np.max(y_i), 100)
p_x_alpha_grid = np.exp(-0.5*((x_grid-alpha)/sigma_alpha)**2)/\

Let’s plot the initial distribution and the samples (with and without noise):


snrcut = 5 # our SNR cut
sel = np.where(y_i / sigma_i > snrcut)[0]
print(sel.size, "objects on", nobj, 'satisfy the SNR cut')
848 objects on 1000 satisfy the SNR cut

Let’s apply the SNR cut and visualise the resulting distribution of samples:



We can already see that by applying the cut we are biasing ourselves towards higher values of .

However, there is enough data (think coverage in or ) and we the selection cut, so we could hope to invert this effect.

And indeed, the equations we derived above show that it is possible in theory.

The new likelihoods

Let us now look at the new likelihood functions and compare them to the original ones, , which ignore selection effects.

As expected, the correction term boosts the distribution at the low values of .


Sampling the posterior distributions via Hamiltonian Monte Carlo

Hamiltonian Monte Carlo (HMC) is a great technique for sampling from probability distributions of interest. It only requires the gradients w.r.t. the parameters of interest to be known analytically or easily computable.

Provided the HMC sampler is tuned, it is very efficient: it has an acceptance probability of one (it is an MCMC that never rejects samples) and efficiently mixes parameters, even in high dimensions.

Given that our model is very simple, has a lot of parameters, and admits simple gradients, it is very natural to opt for HMC to explore the posterior distributions of interest.

First run

Let’s run HMC to sample from the posterior distribution of the first model:

no SNR cut (use the full data set) with the correct likelihood function (with no SNR cut).

And check that the results make sense



We see from the first panel that indeed the recover a nice posterior distribution for (with the s all marginalized out) capturing the true value.

The other panels show that the are also recover, and how the uncertainties significantly shrinkage around the true value, compared to the original likelihood . All we have done is connecting them via the population model and simultaneously infer all the parameters. This is a nice example of the typical Bayesian Shrinkage (tm) of uncertainties in hierarchical models.

Second and third runs

Let us now run the sampler on the subset of objects passing the SNR cut.

We will first do a run with the standard likelihood function ignoring selection effects.

We will then do an other run with the correct, selection-corrected likelihood function.



We see that indeed, running the standard likelihood on the SNR-selected objects leads to biased answers for !

This gets fixed when using the correct likelihood function, which is aware of the SNR cut and attempts to correct it.

Of course, this process has its limits. Here we have used enough data and our knowledge of the selection effect.


If you’ve applied cuts to your data, then you most likely have to modify the likelihood function involved in the parameter inference! This might require some math, but it will mitigate the bias arising from using an incorrect likelihood function.