Portfolio

From user requirements to end to end service delivery

Ari Atoll, Maldives — contains modified Copernicus Sentinel-2 data.
© ESA, CC BY-SA 3.0 IGO

Selected projects
Case study 01 · Agriculture & climate

Crop yield prediction under domain uncertainty

Field-level yield models for crops that must predict a year nobody has seen before — and say honestly how wrong they might be.

Client
Envira
climate-impact & crop yield modelling
9.0 7.3 5.5 t/ha drought year — out of distribution observed forecast 95 % interval
Schematic of the delivered output. The point forecast alone is not the product — the calibrated interval is. In a leave-one-year-out protocol the interval has to keep its promise in the years the model has never seen, including anomalies such as the 2018 drought.

Method

  • Evaluation. Leave-one-year-out CV only. Random k-fold leaks across seasons and inflates R² for a model that will always be deployed into an unseen year.
  • Uncertainty. Split-conformal wrapper; the calibration year is picked by nearest seasonal red-edge profile instead of a random split, and residuals are collected leave-one-year-out so no training data is sacrificed.
  • Structure. National in-season forecast supplies the year-level prior; the field model predicts the residual around it, separating the climate signal from the field-to-field signal.
  • Features. Sentinel-2 red-edge time series, Sentinel-1 backscatter, ERA5-Land (VPD, soil moisture, water balance), MODIS NDVI/EVI, phenology-aligned aggregation windows, yield lags.
  • Models. CatBoost, XGBoost, Random Forest and TabPFN
Sentinel-1 / Sentinel-2 ERA5-Land · MODIS Google Earth Engine Conformal prediction CatBoost · XGBoost · TabPFN WOFOST Python · GCP
Case study 02 · Soil & nature capital

Satellite-based soil erosion modelling

A reproducible RUSLE pipeline on Google Earth Engine that turns Sentinel-2 time series into per-parcel soil-loss rates — validated against European reference layers, not against itself.

Client
The Landbanking Group
Munich · nature-capital measurement & verification
R rainfall × K soil × LS slope × C cover · S2 × P practice A t · ha⁻¹ · yr⁻¹ low moderate high hillslope profile · modelled soil loss per pixel steep, sparsely covered ground erodes fastest
RUSLE decomposes soil loss into five multiplicative factors.

Method

  • Cover factor from measurement. Fractional vegetation cover derived from Sentinel-2 surface reflectance and weighted over the season, replacing the per-crop constants that standard assessments read from a lookup table at kilometre resolution.
  • Cloud-gap reconstruction. Harmonic fit of the fCover series, benchmarked against linear interpolation and resample-plus-harmonic on real gapped series with the ungapped record as truth.
  • Crop context. JRC EUCROPMAP land cover drives crop-aware C assignment.
  • Validation. Four C-factor methods scored on mean, standard deviation and Pearson correlation against the JRC European C-factor layer; the R factor validated against the GloRESatE reference.
  • Engineering. YAML-config driven, Dockerised, parallel over locations and years, batch processing of GeoJSON areas, exports straight to cloud storage. Output: soil loss in t · ha⁻¹ · yr⁻¹ at 100 m, EPSG:3857, plus the individual factor layers.
cloud gap — no usable observation 0.6 0.3 0.0 Jan Jul Dec fCover
The seasonal cover curve is where the erosion signal lives — and it is exactly where clouds remove the data. The reconstruction is validated on real gapped series against the ungapped record, not assumed to be correct.
RUSLE Sentinel-2 fCover Google Earth Engine JRC EUCROPMAP · EU C-factor GloRESatE Docker Python · GCS
Case study 03 · Representation learning

Embeddings under domain shift

A crop-type classifier trained on two seasons and asked to work on a third one that was 1.4 °C warmer and drier — and what self-supervised pre-training does, and does not, fix.

Research
European Space Agency
Frascati · my postdoctoral research
The learned latent space for several crop types.

Method

  • Shift. Sentinel-2 L1C field time series over Upper Bavaria for six crops (corn, winter wheat, winter barley, rapeseed, sugar beet, potato), 2016–2018. Train on 2016–17, predict 2018: a drought year, 1.4 °C warmer than 2016 with below-normal spring rainfall, so the spectral fingerprint of the plants moves.
  • Representation. SimSiam with a transformer encoder, symmetrised negative cosine loss, then a linear classification head fine-tuned on top.
  • Augmentation. Three schemes: real same-crop pairs drawn across years as positives, synthetic noise and drift, and a cloud-offset simulation. The cross-year pairing is the one that treats weather variation itself as the augmentation.
  • Collapse control. The ℓ2-normalised output is tracked against 1/√dim throughout pre-training. Training loss alone did not reveal collapse; without this check the fine-tuning silently stops improving.
  • Baselines. Random Forest and the same transformer trained supervised, over four label budgets for the target year: none, 5 %, 10 %, and all years pooled.

Results

0.54 → 0.71overall accuracy on the unseen year with no target labels — supervised transformer vs. the same network after SSL pre-training, identical inputs
0.90overall accuracy with only 5 % of target-year labels, against 0.85 for the supervised baseline
+16 %relative accuracy gain at a 10 % label budget over the supervised transformer
Sentinel-2 L1C Google Earth Engine SimSiam · self-supervised Transformer encoder Random Forest PyTorch Lightning Domain adaptation

Does that sound exciting?

Data and machine learning — from a research question to a pipeline your team can run. Happy to talk through scope before anything is committed.

Write me an e-mail Other ways to reach me

I reply within one working day.