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.

Kronecker GP + GEV likelihood

Annual temperature extremes over Spain — an additive space + time GP with GEV observations

This notebook threads together three modelling ingredients, now built on the xtremax + pyrox + gaussx stack rather than hand-rolled helpers:

  1. Latent space + time GPs via pyrox.gp — a spatial GP μ(s)\mu(s) over stations and a temporal residual GP τr(t)\tau_r(t) over GMST, each drawn with a whitened gp_sample inside a NumPyro model.
  2. A Generalized Extreme Value likelihood for yearly maxima — supplied by xtremax (GeneralizedExtremeValueDistribution), so we no longer carry a bespoke numpyro.distributions.Distribution subclass.
  3. Variational inference with a NumPyro AutoNormal guide and an optax optimiser — the mean-field posterior is learned by SVI, replacing the hand-written VariationalFactor / closed-form-KL / Gauss–Hermite-ELL loop.

The pedagogical payoff is unchanged: return-level maps — the temperature exceeded once every 25 or 100 years — at current and warming-projected climates, computed with xtremax.gev_return_level.

Background

Block maxima and the GEV distribution

Let X1,…,XnX_1, \dots, X_n be i.i.d. draws from some well-behaved base distribution and set Mn=max⁡iXiM_n = \max_i X_i. The Fisher–Tippett–Gnedenko theorem says the only non-degenerate limits of normalised MnM_n are Generalized Extreme Value laws,

GEV(y∣μ,σ,ξ)=1σ [1+ξ z]+−(1+1/ξ) exp⁡ ⁣(−[1+ξz]+−1/ξ),z=y−μσ,\mathrm{GEV}(y \mid \mu, \sigma, \xi) = \frac{1}{\sigma}\,\bigl[1 + \xi\,z\bigr]_+^{-(1 + 1/\xi)}\,\exp\!\Bigl(-\bigl[1 + \xi z\bigr]_+^{-1/\xi}\Bigr), \qquad z = \frac{y - \mu}{\sigma},

with ξ>0\xi > 0 Fréchet (heavy tail), ξ=0\xi = 0 Gumbel, ξ<0\xi < 0 Weibull (bounded above). Mediterranean max-temperature data typically gives ξ∈[0.05,0.25]\xi \in [0.05, 0.25]. xtremax ships this distribution and its quantile / return-level functions, matching scipy.stats.genextreme (with c = -\xi) to machine precision — we verify that below.

Additive separable structure

We treat space and time as two independent zero-mean GPs with no interaction, f(s,t)=μ0+μ(s)+τ(t)f(s, t) = \mu_0 + \mu(s) + \tau(t), and split the temporal part into a linear warming response plus a smooth residual,

τ(t)=β (GMST(t)−GMST‾)+τr(t),τr∼GP(0,kt).\tau(t) = \beta\,\bigl(\mathrm{GMST}(t) - \overline{\mathrm{GMST}}\bigr) + \tau_r(t), \qquad \tau_r \sim \mathcal{GP}(0, k_t).

Fixing the level on μ0\mu_0 and the trend on β — by centering the two GP fields to be zero-mean — removes the additive identifiability (μ0\mu_0 vs the mean of μ(s)\mu(s); β vs the mean of τr\tau_r) that otherwise lets the latent fields silently absorb the constant and the slope.

Setup

/home/user/research_notebook/projects/gaussian_processes/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm

Synthetic data — a warming Spain

Stations

Forty on-land Iberian stations from xtremax.simulations.generate_spatial_field (lat/lon/elevation). In a real study you’d load AEMET or ERA5 yearly maxima — the inference below is unchanged.

GMST proxy

A synthetic GMST anomaly from xtremax.simulations.generate_gmst_trajectory (linear warming trend + noise). The anomaly feeds the temporal GP.

GMST: start 0.15 °C  →  end 0.90 °C

Ground-truth field

A single ground-truth realisation of the additive model, drawn from pyrox GP priors with fixed kernels via GPPrior.sample — no bespoke draw helper.

GEV observation model — from xtremax

We use xtremax.GeneralizedExtremeValueDistribution directly (Coles parameterisation, 1+ξz1 + \xi z). Verify it matches scipy.stats.genextreme with c = -\xi across the Fréchet, Gumbel, and Weibull regimes.

xtremax GEV vs scipy  (ξ=+0.2):  max|Δ| = 5.12e-13
xtremax GEV vs scipy  (ξ=+0.0):  max|Δ| = 1.42e-14
xtremax GEV vs scipy  (ξ=-0.2):  max|Δ| = 5.33e-15

Draw the observations

observations shape: (40, 40)  range: [27.6, 62.0] °C

Data inspection — stations + a few timeseries

<Figure size 1300x500 with 3 Axes>

The model — pyrox GP latents + xtremax GEV likelihood

A single NumPyro model:

  • Matern-3/2 spatial kernel and RBF temporal kernel from pyrox.gp, each with log-normal hyperpriors;
  • latent fields drawn with whitened gp_sample (well-conditioned reparam), then centered so μ0\mu_0 owns the level and β owns the trend;
  • an xtremax GEV likelihood on the S×TS \times T grid of yearly maxima.

Inference — SVI with a NumPyro AutoNormal guide

optax.zero_nans() guards against the occasional out-of-support GEV draw (a -inf log-prob → NaN gradient) during early exploration; init_to_value starts the location near the data so we don’t begin deep out of support.

SVI finished in 13.3s
fitted μ₀  = 34.41 ± 0.05  (truth 35.0)
fitted β   = 1.18 ± 0.17  (truth 1.5)
fitted σ   = 1.83 ± 0.04  (truth 1.8)
fitted ξ   = 0.142 ± 0.021  (truth 0.12)

Loss curve

<Figure size 1000x320 with 1 Axes>

Parameter recovery

The additive model has a residual constant degeneracy between μ0\mu_0 and the mean of μ(s)\mu(s); with the centered fields the posterior tracks the truth’s shape with a small (≲ 0.5 °C) vertical offset.

<Figure size 1300x420 with 2 Axes>

GEV tail recovery

<Figure size 1100x380 with 2 Axes>

The payoff — return-level maps

The TrT_r-year return level is zp=F−1(1−1/Tr)z_p = F^{-1}(1 - 1/T_r), computed with xtremax.gev_return_level. We map 25- and 100-year return temperatures for a typical year at the end of record (2024) and a warming projection (2050) obtained by linearly extrapolating GMST.

GMST 2024 = 0.903 °C, GMST 2050 (extrapolated) = 1.403 °C
2024 → 2050 mean shift in 100-yr return level: 0.59 °C
<Figure size 1500x1400 with 8 Axes>

Summary

  • pyrox.gp supplies the kernels (Matern, RBF, matern_kernel, rbf_kernel), the GPPrior, and whitened gp_sample latent fields.
  • xtremax supplies the GEV likelihood (GeneralizedExtremeValueDistribution, machine-precision vs scipy) and the return-level helper (gev_return_level).
  • NumPyro SVI with an AutoNormal guide replaces the hand-rolled variational scaffold; centering the latent fields fixes the additive identifiability so μ0\mu_0 owns the level and β owns the warming trend.

Follow-ups

  • Multiplicative Ks⊗KtK_s \otimes K_t — spatially-varying warming rates.
  • Non-stationary GEV — let log⁡σ\log\sigma and/or ξ vary over space.
  • Real data — swap the synthetic stations / maxima for AEMET or ERA5.