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.

Gaussian copula on the residuals — spatial dependence in extremes

Annual temperature extremes over Spain — part 4: a Gaussian copula on the residuals

Notebooks 01–03 treated stations as conditionally independent given the latent fields. That is fine for the marginals but wrong for joint risk: when a heatwave hits, nearby stations exceed their return levels together. This notebook keeps nb 03’s four-GP marginal model and adds a Gaussian copula on the cross-station residuals, with a two-range exponential dependogram

Rij=c0 e−dij/c1+(1−c0) e−dij/c2.R_{ij} = c_0\,e^{-d_{ij}/c_1} + (1 - c_0)\,e^{-d_{ij}/c_2}.

Everything reuses the package stack: xtremax for the GEV margins (gev_cdf, gev_icdf), the distances (pairwise_distances) and the dependogram (two_range_correlation); pyrox.gp for the latent fields; and NumPyro SVI. The copula enters the ELBO as a numpyro.factor, so c0,c1,c2c_0, c_1, c_2 are inferred jointly with the margins (a step up from the plug-in/IFM recipe in jej_vc_snippets/extremes/models/temp_gevd_gp_copula.py).

Background — Gaussian copula in three steps

A copula separates marginal behaviour from dependence (Sklar’s theorem). With GEV margins FsF_s and a Gaussian copula with correlation RR:

  1. PIT: us,t=Fs(ys,t)∈(0,1)u_{s,t} = F_s(y_{s,t}) \in (0,1) — push each observation through its own marginal CDF.
  2. To Gaussian scores: zs,t=Φ−1(us,t)z_{s,t} = \Phi^{-1}(u_{s,t}).
  3. Correlate: the year-tt vector z⋅,t∼N(0,R)z_{\cdot,t} \sim \mathcal{N}(0, R).

The joint log-density is the sum of marginal GEV log-densities plus a copula correction

log⁡c(u⋅,t)=log⁡ϕR(z⋅,t)−∑ilog⁡ϕ(zi,t),\log c(u_{\cdot,t}) = \log \phi_R(z_{\cdot,t}) - \sum_i \log \phi(z_{i,t}),

summed over years. We add the marginals via the usual GEV likelihood and the correction via numpyro.factor.

To simulate correlated extremes we run Sklar’s theorem in reverse: zt∼N(0,R∗)→ut=Φ(zt)→yt=F−1(ut)z_t \sim \mathcal{N}(0, R^*) \to u_t = \Phi(z_t) \to y_t = F^{-1}(u_t).

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

Stations, GMST, pairwise distances (same grid as nbs 02–03)

station distance range: 0.11 -> 12.92 degrees

Truth — four latent fields (as nb 03) plus the copula

μ(s)\mu(s), β(s)\beta(s), σ(s)\sigma(s), ξ(s)\xi(s) exactly as nb 03; the copula adds a two-range dependogram with c0∗=0.5c_0^*=0.5, c1∗=0.5°c_1^*=0.5° (~55 km, convective) and c2∗=4°c_2^*=4° (~440 km, synoptic).

R* PD check: min eigval = 1.125e-01

Inverse-PIT simulation — correlated extremes via Sklar

zt∼N(0,R∗)z_t \sim \mathcal{N}(0, R^*), ut=Φ(zt)u_t = \Phi(z_t), yt=FGEV−1(ut)y_t = F^{-1}_{\rm GEV}(u_t) with the per-station margins. Uses xtremax.gev_icdf.

y_obs shape: (40, 40)  range: [26.4, 61.1] °C
xtremax GEV vs scipy (ξ=0.2)  max|Δ| = 5.12e-13

Inspect the truth — four fields + the copula dependogram

<Figure size 1500x900 with 7 Axes>

Model — nb 03 four-GP marginals + a Gaussian copula factor

The four pyrox spatial GPs and the xtremax GEV margins are exactly nb 03. Three extra scalars (c0,c1,c2)(c_0, c_1, c_2) parameterise the dependogram, and a numpyro.factor adds the per-year copula correction log⁡ϕR(zt)−∑ilog⁡ϕ(zi,t)\log\phi_R(z_t) - \sum_i \log\phi(z_{i,t}).

Inference — SVI (whitened GP bases initialised at zero, as nb 03)

SVI finished in 46.0s
fitted μ₀=34.19(35)  β₀=1.27  σ₀=1.99  ξ₀=0.142
fitted c0=0.474(0.5)  c1=0.552(0.5)  c2=3.515(4.0)  [degrees]

Loss curve

<Figure size 1000x320 with 1 Axes>

Recovery of the four latent fields

<Figure size 1100x900 with 4 Axes>

The killer plot — copula recovery

Three curves should agree on a single dependogram: the truth R∗(d)R^*(d), the empirical residual correlation of z^=Φ−1(Fθ^(y))\hat z = \Phi^{-1}(F_{\hat\theta}(y)) (the model’s own margins applied to the data), and the fitted parametric R^(d)\hat R(d).

<Figure size 1400x500 with 2 Axes>

Joint exceedance probabilities — where the copula visibly wins

Probability that the 5 most central stations all exceed their own 25-year return level in the same year. Under conditional independence this is (1/25)5≈10−7(1/25)^5 \approx 10^{-7}; under the fitted copula it is Pr⁡(⋂iZi>Φ−1(1−p))\Pr(\bigcap_i Z_i > \Phi^{-1}(1-p)) with Z∼N(0,RI)Z \sim \mathcal{N}(0, R_I).

Pr(all 5 central stations exceed their 25-yr return level in the same year):
  conditional independence (nb 03):  1.02e-07
  fitted Gaussian copula (MC):       1.10e-04   (1074x larger)
  observed in 40 years:             0.00e+00  (0/40 years)

Summary

  • The four-GP marginal model from nb 03 is unchanged; the copula adds three scalars and a per-year numpyro.factor correction log⁡ϕR(zt)−∑ilog⁡ϕ(zi,t)\log\phi_R(z_t) - \sum_i\log\phi(z_{i,t}) — so c0,c1,c2c_0, c_1, c_2 are inferred jointly with the margins (full variational inference, not plug-in/IFM).
  • The dependogram is built with xtremax.two_range_correlation and the distances with xtremax.pairwise_distances; PIT and its inverse use xtremax.gev_cdf / gev_icdf. The two-range form Rij=c0e−d/c1+(1−c0)e−d/c2R_{ij} = c_0 e^{-d/c_1} + (1-c_0) e^{-d/c_2} separates a convective range c1c_1 from a synoptic range c2c_2.
  • Empirical residual correlation, fitted R^(d)\hat R(d), and truth R∗(d)R^*(d) line up — the copula recovers both the parametric form and the empirical structure.
  • On joint return periods the copula gives a probability orders of magnitude larger than the conditional-independence approximation — the correction that matters for compound climate risk.

Follow-ups

  • Reparameterised-MC copula instead of the margin plug-in inside the factor.
  • Non-stationary copula R(d,s)R(d, s) for region-specific dependence regimes (Atlantic vs continental vs Mediterranean).
  • Tail-dependent copulas (Student-tt, Gumbel) — the Gaussian copula is asymptotically tail-independent, so it understates the tendency of the most extreme heatwaves to synchronise across regions.