Baselines in forecasting projects: why the naive method must be beaten
A forecasting model does not earn its complexity unless it measurably beats a method as simple as “repeat the last value”.
Split time series by time, never by random shuffling: the training period comes before the test period. Fit scalers, feature windows and other preprocessing only on the training data. For evaluation, use walk-forward splits, so each test window lies in the future relative to the data the model was trained on. Random splits make results look better than they are.
A standard random split (shuffle) puts neighbouring hours into both the training and the test sets. One hour’s value is almost the same as the next hour’s. The model learns that neighbourhood, so the test score looks better than the model will perform in service. In production the model must predict forward, and no such neighbour exists.
A correct split respects order: the training period ends before the test period begins. A single cut point is the simplest version. One test period, however, may reflect one event’s luck or one unusual season, so several consecutive splits give a more reliable picture.
Suppose a pump has 365 days of hourly records, which is 365 × 24 = 8 760 rows. The first 300 days (7 200 rows) are used for training and the last 65 days (1 560 rows) for testing. 7 200 + 1 560 = 8 760, so no rows are lost.
Walk-forward evaluation moves the cut point forward:
Each test window is 30 days. The three folds give 90 days of out-of-sample evaluation, and the spread of scores across folds is more informative than any single number.
Leakage happens when information from the test period enters training. Three routes are common:
The fix is to fit every transformation inside each fold, using only that fold’s training data, and to check rolling features for any reference to future values.
A general rule is a gap at least as long as the longest feature window and the prediction horizon. For example, 24-hour features with a 6-hour horizon suggest a gap of at least 24 hours. The right value depends on how far back the features look, so check it in the feature code.
Not in its standard, shuffled form, because it places future data in the training folds and inflates the scores. Use time-aware variants instead, where each test fold is preceded only by data from earlier in time.
Example numbers are hypothetical, not measured field results.