Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

2. Distribution gallery

In this notebook, we introduce the distribution gallery in CUQIpy: a collection of two-dimensional “toy” distributions provided for illustrative purposes and for testing and benchmarking samplers. Each gallery distribution is specified by its log-density (and gradient) only, making them ideal test targets for the sampling methods covered later in the book. The set follows the benchmark distributions of The Markov-chain Monte Carlo Interactive Gallery.

Notebook Cell

The gallery is loaded through DistributionGallery, which takes the name of the desired distribution as a string. The following distributions are available:

NameShapeUseful for testing
"CalSom91"Two crescent-shaped modesMultimodality with curved modes
"BivariateGaussian"Correlated Gaussian (ρ=0.9\rho = 0.9)Baseline; the only gallery distribution with direct sampling
"funnel"Neal’s funnelDistributions whose scale varies strongly across the space
"mixture"Mixture of three GaussiansMultimodality
"squiggle"Strongly correlated, “squiggly” GaussianStrong correlation
"donut"Ring of radius rrNon-convex support and strong curvature
"banana"Twisted (“banana-shaped”) GaussianStrong curvature; a classic benchmark for HMC-type samplers

All gallery distributions share the same interface: they provide a logpdf (and a gradient), and most of them are density-only — that is, they cannot be sampled directly, only via a sampler.

2.2. Loading a distribution: the “donut”

As a first example, we load the “donut” distribution, which is a bivariate distribution of a donut shape. Its log-density is

log⁡(p(x))∝−1σdonut2(∥x∥−rdonut)2,\begin{aligned} \log(p(\mathbf{x})) \propto - \frac{1}{\sigma_\text{donut}^2} \left( \left\| \mathbf{x} \right\| - r_\text{donut} \right)^2, \end{aligned}

where x=(x1,x2)\mathbf{x} = (x_1, x_2) is a 2D vector, ∥x∥\left\| \mathbf{x} \right\| is the Euclidean norm of x\mathbf{x}, rdonutr_\text{donut} is the radius of the donut, and σdonut\sigma_\text{donut} is a scalar that controls the width of the “donut”. The density is largest where ∥x∥≈rdonut\left\| \mathbf{x} \right\| \approx r_\text{donut} — i.e. on a ring — and the default parameters are rdonut=2.6r_\text{donut} = 2.6 and σdonut2=0.033\sigma_\text{donut}^2 = 0.033.

CUQI DistributionGallery.

2.3. Plotting the densities

We can visualize the density of a gallery distribution as

<Figure size 640x480 with 1 Axes>

Let’s also plot a few more gallery distributions. Note the different plotting windows needed to capture the mass of each distribution.

<Figure size 640x480 with 1 Axes>
<Figure size 640x480 with 1 Axes>
<Figure size 640x480 with 1 Axes>

The plots show the variety of shapes in the gallery: the banana is a strongly curved Gaussian, the funnel has a narrow “neck” (the width of x1x_1 varies by orders of magnitude depending on x2x_2), and the mixture is clearly multimodal.

2.4. Density and gradient evaluation

All gallery distributions provide logpdf and gradient, which is the interface CUQIpy samplers rely on:

logpdf at [2. 1.] : [-4.01353082]
gradient at [2. 1.] : [19.72792101  9.8639605 ]

Note that most gallery distributions do not implement direct sampling (an exception is "BivariateGaussian", which wraps a Gaussian). This is intentional: the gallery targets are meant to be explored with the samplers, which we do next.

BivariateGaussian can be sampled directly: CUQIpy Samples:
---------------

Ns (number of samples):
 3

Geometry:
 _DefaultGeometry1D[2]

Shape:
 (2, 3)

Samples:
 [[ 1.39286824  0.92761334 -0.22646405]
 [ 2.2408932   1.86755799 -0.97727788]]


Since the gallery targets are density-only, we sample them with CUQIpy samplers. The sampling workflow is: construct the sampler with an initial point, warmup (adapt), then sample, and finally collect the samples with get_samples.

Below we sample the donut distribution with two different samplers: Metropolis–Hastings (MH) with a fixed proposal scale, and the No-U-Turn Sampler (NUTS), which adapts its step size and uses the gradient.

Warmup:   0%|          | 0/200 [00:00<?, ?it/s]
Warmup: 100%|██████████| 200/200 [00:00<00:00, 4861.44it/s, acc rate: 31.50%]

Sample:   0%|          | 0/1000 [00:00<?, ?it/s]
Sample: 100%|██████████| 1000/1000 [00:00<00:00, 4743.20it/s, acc rate: 31.20%]

Warmup:   0%|          | 0/200 [00:00<?, ?it/s]
Warmup: 100%|██████████| 200/200 [00:00<00:00, 346.69it/s, acc rate: 64.00%]

Sample:   0%|          | 0/500 [00:00<?, ?it/s]
Sample: 100%|██████████| 500/500 [00:00<00:00, 590.28it/s, acc rate: 70.80%]

<Figure size 640x480 with 1 Axes>

Both samplers correctly concentrate the samples on the ring. The MH sampler with a small fixed step size moves slowly around the ring, while NUTS (which adapts its step size and follows the gradient) explores it more efficiently. The donut is a nice illustration of why the choice of sampler and its tuning parameters matter. For more details on sampling the donut distribution, we refer to 1. Sampling with CUQIpy: five little stories.

2.6. Exercises