Wheat yield forecasting for 23 countries across every populated continent, built from real satellite and weather data, benchmarked honestly against a naive baseline, with a Monte Carlo scenario simulator on top.
Each stage writes a file the next stage reads — reproducible end to end from python src/extract_yield.py through src/simulate.py.
01
Yield labels
FAOSTAT wheat yield, kg/ha, 2001–2023 (World Bank cereal kept as comparison)
extract_yield_wheat.py
02
Satellite
MODIS NDVI/EVI, monthly Feb–Jun, via Earth Engine
extract_satellite.py
03
Weather
NASA POWER precip + temp, monthly, grain-belt point
extract_weather.py
04
Panel + lag
Merge, add yield_lag1, drop first year/country
build_dataset.py
05
Train & evaluate
6 models, time-based split, honest metrics
train.py
06
Simulate
Monte Carlo scenarios, stratified resampling
simulate.py
Results · model comparison
Which model actually wins?
Trained on 2002–2018 (391 rows), tested on 2019–2023 (115 rows) — years the model never saw. Sorted by test RMSE, lower is better.
Honest read: the naive "yield repeats last year" baseline is still strong (R²=0.940) — most of a country's wheat yield is just its recent level. LightGBM now wins outright (not a tie), beating the baseline by ~20% RMSE — a bigger, more real lift than the original 9-country study's ~13%. Worth naming directly: that first report said LightGBM's stock hyperparameters were "tuned for far more rows than this study's 153 training rows" — with 391 rows now, LightGBM goes from worst model to best. Not tuned differently, just given enough data, exactly as predicted rather than retroactively explained.
Results · feature importance
What the winning model actually looks at
XGBoost feature importance, now at monthly resolution — last year's own yield still dominates, but June conditions (pre-harvest) carry real secondary signal the season-average view had completely hidden.
Monthly resolution changed the story: temp_m06_c (June temperature) alone carries 8.2% — more than every NDVI/EVI feature combined except season-max. All 10 monthly weather columns together now carry ~11% (vs. under 2% for a single season-wide average in the original study); all 11 monthly + season-max NDVI/EVI columns together carry ~8%. yield_lag1 still dominates at 80.3%. This is exactly why the scenario simulator below resamples real historical seasons together rather than moving one variable in isolation.
Monte Carlo scenario simulator
Not one number — a distribution
5,000 draws per scenario, resampled from that country's own real 2002–2023 seasons, stratified by NDVI tercile, run through the LightGBM model above. Pick a country.
Afghanistan
Driest third of seasonsAll seasons (typical)Wettest third of seasons
Underlying data
23 years, 23 countries, real numbers
Actual wheat yield per country, 2002–2023 (FAOSTAT). Each panel scaled to its own range — magnitudes differ by 9× between countries, shapes are the point here.
Read before citing this anywhere
Known limitations
Resolved
Wheat-specific labels, closed out. The original report used World Bank all-cereal yield as a proxy because FAOSTAT's query API was down (HTTP 521 — still is). Their bulk-download route works, so labels are now wheat-specific (FAOSTAT item "Wheat", element "Yield") for all 23 countries — the cereal series is kept only as a side-by-side comparison column now, not the target.
Fixed window
Same Feb–Jun season for every country, not a per-country wheat calendar. Approximate, not phenology-matched.
Spatial blend
Country-level satellite averaging mixes non-cropland pixels — desert, mountains, cities — diluting the signal vs. a cropland mask.
Point weather
One coordinate per country, not an area average — NASA POWER is a point API. See the <2% combined feature importance above.
Small N
391 training rows, 22 features. Bigger than the original 9-country study's ~150, still modest for the feature count. Simulator pools go as low as 8 seasons per country.
No field data
Labels are national statistics, not farmer-reported outcomes — nowhere in this pipeline is there ground truth from an actual field.