Mohd Zamin Quadri

GitHubLinkedIn

All work

Scientific computing demonstration

Synthetic Streamflow Forecasting Benchmark

A deterministic benchmark comparing seasonal-naive, SARIMAX, and gradient-boosted one-step streamflow predictions.

Role
Project author
Classification
Synthetic demonstration
Inspect repository
R² 0.979 on synthetic data, one step ahead with yesterday's measurement supplied. The two lines overlap because of what the model was given.Fifteen years of synthetic daily streamflow drawn as a ribbon, with the two-year chronological holdout marked. A 120-day window is taken out of the test period and magnified; lag and rolling-window features are cut from it, and a one-step-ahead prediction is laid over the observation, matching it closely at an R-squared of 0.9786. The top decile of flow is then marked, and the model is shown coming in under every peak in it. The sequence ends on the feature importances, where lag-1 and lag-2 together carry 94 per cent of the model, against a lag-1 autocorrelation of 0.9941.

01 / 13Three numbersA benchmark result, in the shape everyone reads first.

  1. Seasonal Naive-11.692 · RMSE 90.299 · scored on 730 daily values
  2. SARIMAX (Monthly)0.7206 · RMSE 13.536 · scored on 25 monthly means
  3. XGBoost0.9786 · RMSE 3.71 · scored on 730 daily values
Reported result, and what each row was scored on
  1. Seasonal Naive-11.692RMSE 90.299 · MAE 89.935 · scored on 730 daily values
  2. SARIMAX (Monthly)0.7206RMSE 13.536 · MAE 11.901 · scored on 25 monthly means
  3. XGBoost0.9786RMSE 3.71 · MAE 2.865 · scored on 730 daily values

Read as a ranking, the table says gradient boosting beats classical statistics by a wide margin. Read against the code, the three rows are not answering the same question. XGBoost is scored one step ahead with the previous day’s measured discharge supplied as an input feature; SARIMAX forecasts 25 monthly means without seeing any of them; the baseline repeats a seasonal average that has no trend term at all.

Q120 days
Observed (white) and predicted (teal) over the first 120 test days. They overlap because the model is predicting tomorrow having been told today.

Two things explain the table. The series was written rather than measured — a fixed-seed generator whose recursion is y[t] = 0.85·y[t−1] + …, so its day-to-day autocorrelation is 0.9941 and the two most recent lags carry 94.4% of the fitted model while rainfall carries 0.0007. And the baseline is undefended against trend: the same generator adds 0.005 a day, which its own feedback multiplies by 6.67, so the series climbs 89.91 between the training and test periods while the baseline’s mean bias is 89.94. Its MAE (89.935) and RMSE (90.299) are nearly equal because the error is an offset, not scatter.

Where it is worst is measurable rather than impressionistic. On the highest tenth of test days — observed flow above 266.28 — the mean absolute error is 5.591 against 2.562 everywhere else, and the signed mean is -5.506: the misses are undershoots. Those days are 10% of the holdout and carry 29% of the squared error. The worst single day observed 273.12 and came in 12.99 low.

Record
5,475 days
Holdout
730 days
Features
26
Horizon
One step
  • Synthetic data, not a catchmentThe river was written by a 40-line generator with a fixed seed. Nothing here is evidence about any real basin, and the repository's own scope note says so first.
  • One step ahead, with the answer in the featuresThe XGBoost score is next-day prediction given discharge already observed at prior timestamps. It is not a recursive multi-day forecast and was never evaluated as one.
  • The three rows are not the same taskThe naive baseline and XGBoost are scored on 730 daily values; SARIMAX is scored on 25 monthly means it forecast without seeing any of them. A single table makes them look comparable.
  • The baseline is undefended against trendA day-of-year mean has no trend term, and the generator injects one. Most of the gap between the baseline and everything else is that, not model quality.
  • No uncertainty of any kindEvery prediction here is a point. The benchmark produces no intervals, no coverage and no calibration, so none is shown.
  • One seed, one runThe tracked figures and JSON record a single reference run. The README notes that library versions may shift the numbers slightly.

01Problem

Why this work exists

Forecasting methods should be compared against simple baselines with temporal holdouts and hydrology-relevant metrics.

02Contribution

What I can claim

Created a fixed-seed synthetic daily series, chronological split, lag and rolling features, model comparison, diagnostics, and an explicit distinction between one-step and recursive forecasting.

Method

Three numbers that are not the same measurement

A benchmark table invites one reading: rank the rows. This one rewards a second look, because the three rows were not asked the same question, and the differences between the questions are larger than the differences between the models.

  1. Rank

    Read as a leaderboard, gradient boosting beats classical statistics by a wide margin and the naive baseline is not close.

  2. Open

    One row predicts tomorrow having been given today's measurement. One forecasts two years of monthly means without seeing any of them. One repeats a seasonal average that carries no trend term.

  3. Attribute

    The two most recent lag features carry most of the strongest model, on a series whose day-to-day autocorrelation is very close to one - because the series was generated by a recursion that is public.

  4. What this does not show

    This benchmark is deterministic and synthetic, and its evaluation is one step ahead with observed discharge supplied as an input. It exercises an evaluation pipeline honestly; it is not a claim about any particular river.

03System

Workflow and decisions

  1. 01Synthetic 15-year series
  2. 02Chronological holdout
  3. 03Three model families
  4. 04Hydrology metrics
  5. 05Error analysis
  • XGBoost
  • statsmodels
  • scikit-learn
  • pandas
  • NumPy
  • Matplotlib

04Evidence

What is actually versioned

One-step benchmarkR² 0.979

XGBoost on synthetic data with observed lag inputs; not a recursive multi-day forecast.

Classical comparatorR² 0.721

SARIMAX result on monthly means within the same synthetic benchmark.

05Quality controls

How the work is checked

  • Fixed-seed data generator and chronological test split
  • Seasonal-naive baseline retained alongside stronger models
  • Tracked metrics and nine diagnostic figures
  • Repository checker validates source and artifacts

06Limitations

Where the evidence stops

  • Synthetic data cannot establish real-catchment performance
  • XGBoost evaluation is one-step-ahead with observed historical discharge lags
  • The benchmark does not test recursive multi-day behavior or distribution shift

What this changed in my practice

Strong synthetic scores are useful for testing an evaluation pipeline, but they are not evidence of field validity.