ML model & data pipeline

Predicting extreme
atmospheric events.

Two models trained on ERA5 reanalysis data (Copernicus), covering 1940–1990 and 2010–2024, grid centred on Seville. Binary target: extreme weather event tomorrow. The Random Forest serves as the production predictor. The LSTM was trained as a sequence-aware baseline.

Model comparison

Both architectures were evaluated on the same dataset. The Random Forest serves as the production predictor due to its superior AUC, simpler feature requirements, and no need for sequence context at inference time. The LSTM was trained as a sequence-aware baseline on 17 raw and derived physical features, without the full 39-feature set used by the RF.

Production
Random Forest
Mean AUC (5-fold CV) 0.836
Mean F1 (5-fold CV) 0.149
Features 39
Training samples 5,472
Event rate 5.0%
Baseline
AtmosphericLSTM
Test ROC-AUC 0.678
Test F1 (th=0.38) 0.135
Sequence length 14 days
Parameters 127,169
Epochs (early stop) 40 / 150
Why the RF wins

The LSTM trained on 17 physical features (raw + rolling + gradients) achieves AUC 0.678 vs. 0.836 for the RF on 39 features. The gap is expected: the RF receives pre-computed 7-day rolling means, 3-day lags, and a dry index specifically tuned for Seville's climate — temporal context that the LSTM must reconstruct from raw sequences. With 24k days of training data the LSTM saturates quickly. The AUC-PR plateaued around epochs 14-15 and early stopping triggered at epoch 40.

Random Forest — cross-validation

Time-series aware 5-fold cross-validation (TimeSeriesSplit). Folds are strictly sequential — no future data leaks into any training window. The event rate is 5.0%, addressed with class_weight='balanced_subsample' across 400 estimators.

Fold F1 ROC-AUC
1 0.043 0.806
2 0.127 0.773
3 0.190 0.888
4 0.156 0.825
5 0.229 0.886
Mean 0.149 0.836

AUC improves in later folds (0.773 → 0.886), consistent with the model learning Seville's seasonal extreme patterns more reliably as the training window grows. Low F1 is expected at 5% event rate under strong class imbalance — AUC 0.836 is the operative metric.

RF feature importance — top 10 (SHAP)

Mean absolute SHAP values via TreeExplainer over 200 training samples. Minimum daily pressure ranks first — sharp pressure drops are the clearest precursor of frontal systems. Temperature maximum ranks second, directly defining heat and cold thresholds. Cosine day-of-year ranks third, confirming strong seasonality.

The dry index (thermal range × (100 − mean humidity)) is the most Seville-specific feature: wide diurnal swings with very low humidity are the signature precondition for the city's most dangerous heat events.

LSTM architecture

Two-layer LSTM with LayerNorm and a GELU MLP head. LayerNorm was chosen over BatchNorm for stability with short sequences and variable batch sizes. Focal Loss (α=0.80, γ=1.5) shifts gradient weight toward the rare positive class. Trained with AdamW (lr=1×10⁻⁴) and cosine annealing.

# AtmosphericLSTM — forward pass
Input  →  (batch, 14, 17)          # 14-day window × 17 features
LSTM₁  →  hidden=128               # short-range synoptic patterns
LSTM₂  →  hidden=64                # regime-level compression
LayerNorm  →  (batch, 64)          # last timestep only
Linear(6432) + GELU + Dropout(0.25)
Linear(321)  + Sigmoid         # P(extreme event tomorrow)
LSTM — validation metrics per epoch
ROC-AUC
AUC-PR
F1

Early stopping triggered at epoch 40 (patience 25 on AUC-PR). AUC-PR peaked at epoch 15 (0.121) and did not improve further, while ROC-AUC continued rising slowly. This plateau is characteristic of Focal Loss on highly imbalanced data: once the model stops finding new positive examples to focus on, the precision-recall curve saturates.

ERA5 data pipeline

The dataset covers two periods: 1940–1990 (51 years of pre-industrial and early-industrial baseline) and 2010–2024 (15 years of contemporary climate with documented warming trend). This split allows the model to learn both long-run climatological distributions and the contemporary extreme event shift.

01

Download

Copernicus CDS API via cdsapi. 7 variables at 06:00 / 12:00 / 18:00 UTC. Area: 38°N–36.5°N, 6.5°W–5°W. Two NetCDF4 series — instantaneous (temp, pressure, wind, dewpoint) and accumulated (precipitation, cloud cover).

02

Physical conversion & daily aggregation

K → °C · Pa → hPa · precipitation diff × 1000 (m→mm) · wind → speed via √(u²+v²) · humidity from dewpoint via Magnus formula. Resampled to daily: Tmax, Tmin, Tmean, Pmean, Pmin, windmax/mean, precipsum, humiditymax/mean, cloudmean.

03

Bias correction

ERA5 underestimates Tmax in Seville by ~2.5°C due to the 1.5° grid resolution. A constant +2.5°C correction is applied to all temperature fields before feature engineering and label thresholding.

04

Feature engineering

RF (39 features): raw daily aggregates · 3/7-day rolling means · 1/2/3-day lags · pressure and temperature gradients · sin/cos seasonality · thermal range, heat intensity, pressure deficit, humidity range, wind spike, dry index, normalized pressure.
LSTM (17 features): 9 raw physical variables + 8 derived: temp_ma3/ma7, pressure_ma3, pressure_grad, wind_speed, wind_ma3, precip_ma3, dry_index. Scaled with StandardScaler fitted on train days only — before sequence construction to avoid overlap bias.

05

Label definition

Binary target: extreme event tomorrow (shift −1 day). Triggers: heat Tmax ≥ 38°C · cold Tmax ≤ 10°C · wind ≥ 8 m/s · rain ≥ 1 mm/day. OR logic. Event rate: 5.0%.

RF configuration

RandomForestClassifier(
    n_estimators=400,
    max_depth=10,
    min_samples_leaf=4,
    class_weight="balanced_subsample",   # resamples weights per tree
    random_state=42,
    n_jobs=-1
)

No feature scaling — RF is scale-invariant. The feature list is saved to features.pkl alongside the model to guarantee column order consistency at inference time.

Production inference

The RF requires temporal features (rolling means, lags) that cannot be computed from a single API snapshot. The system accumulates one daily record per calendar day in a CSV committed to the repository.

Risk score vs. event type

The production model outputs a calibrated probability through predict_proba(). That probability drives the visual warning system. The event type is a secondary heuristic label derived from the current feature row. When risk is active but no specific type crosses its physical threshold, the interface displays a generic extreme-event signal instead of over-claiming heat, cold, rain, or wind.

Day 0
Fallback to ERA5. The last observed day in the training CSV is used as the feature vector.
Days 1–6
Rolling means computed with min_periods=1. Lag features partially filled with current value as proxy.
Day 7+
Rolling means fully real (ma3 and ma7). Gradients from observed history.
Day 14+
All lags complete. Feature vector equivalent to training conditions.

Stack

Python 3.11 scikit-learn PyTorch shap xarray ERA5 / Copernicus CDS cdsapi netCDF4 joblib pandas numpy Playwright GitHub Actions GitHub Pages