Benchmark forecasts and honest evaluation: backtesting, metrics and leakage
Before this lesson: lesson 01 (trend, season, the seasonal period ) and lesson 02 (white noise, random walk, the ACF and the Ljung–Box test). Cross-validation in ordinary machine learning helps (ml-fundamentals track). Time: about 75 minutes, plus the notebook.
Why this matters #
A forecast is only useful when it beats a simple rule. In the M4 competition (100,000 series), the six pure machine-learning methods were all less accurate than a simple combination of exponential smoothing methods, and only one of them beat a seasonally adjusted naive forecast (Makridakis, Spiliotis and Assimakopoulos 2020). Many published "improvements" disappear when they are compared with a seasonal naive forecast on the same backtest.
Evaluation mistakes are common and they always flatter the model:
- a random train/test split puts future values into the training set;
- one test period of a few weeks can be lucky or unlucky;
- a scaler, a decomposition or a hyperparameter search that sees the test period leaks information;
- a percentage metric quietly rewards forecasts that are too low.
Every later lesson of this track compares its method with the benchmarks of this lesson, using the rolling-origin backtest of this lesson.
1. Predict first #
2. The picture #
Four benchmark forecasts #
You stand at the forecast origin : you know and nothing after. You want the values at . The number of steps ahead, , is the horizon. We write the forecast of made at origin as .
Four rules need no model fitting:
- mean: every future value equals the average of the past;
- naive: every future value equals the last observed value ;
- seasonal naive: every future value equals the value one season earlier (for monthly data with a yearly pattern, next March equals the last March);
- drift: draw a straight line through the first and the last observation, and extend it.
These are the benchmark forecasts (also called baselines). They are not toys: each one is the best possible forecast for one simple kind of series (section 3.2).
Drag in the chart to move the forecast origin (yellow line). The four benchmarks start there: mean, naive, seasonal naive and drift (dashed grey). The blue dots in the shaded window are the values they try to predict; the table scores them. Switch the series: on the seasonal "monthly demand" series the seasonal naive forecast usually wins, on a random walk the naive forecast wins, and on white noise the mean wins.
Backtesting: many origins, not one #
One test period is one sample. It can be lucky. A backtest (also called rolling-origin evaluation or time series cross-validation) repeats the forecast at many origins:
- Choose an origin . Fit the method on the data up to .
- Forecast and store the errors, labelled by their horizon .
- Move the origin forward by a step (for example 6 months) and repeat.
- Average the errors over all origins, separately for each horizon .
The training data either grow (expanding window: always start at ) or keep a fixed length (sliding window: drop the oldest values). A gap leaves some values out between the end of the training data and the first test value (section 3.5 says when you need one).
Each row is one fold. The training window (aqua) ends at the forecast origin (yellow); the test window (violet) holds the next values. Move the sliders and watch the rows. The bottom chart averages the error of the seasonal naive and the drift forecast over all folds, for each horizon : the errors are not the same at every horizon. Then choose "random K-fold": most test points now have training points after them.
Monthly data, seasonal period , forecast origin . Which observation is the seasonal naive forecast for horizon ?
The seasonal naive forecast is with . For , , so it is : the same month in the last observed year. The tempting is in the future, which is not known at the origin.
months, expanding window, initial training size 48, horizon , step 6, no gap. How many folds does the backtest have?
The origins are The last test window must end by month 120, so the origin needs , that is . That gives origins. Check it in the figure above.
3. Definitions and main results #
3.1 Forecasts, errors and residuals #
- The forecast uses only .
- The forecast error is . It is measured on data the method did not see.
- The residual is the one-step error on the training data, . For a method with fitted parameters, the residuals use the parameters fitted on all the training data, so they are in-sample.
Residuals tell you whether a method used all the information in the data. Forecast errors tell you how accurate it is. Do not report residuals as accuracy: they are almost always too small.
3.2 The four benchmarks and when each one is optimal #
Let be the number of observations known at the origin, the seasonal period and the horizon.
| Method | Forecast | Best forecast (smallest mean squared error) for |
|---|---|---|
| mean | white noise around a constant: | |
| naive | a random walk: | |
| seasonal naive | , | a seasonal random walk: |
| drift | a random walk with drift: |
Here is white noise with mean 0 and variance (lesson 02). In the seasonal naive formula, counts how many full years of the forecast period lie before the target: for , and the forecast is .
Why the conditional mean is the best forecast under squared error. Let be the unknown future value and the information at the origin. For any number computed from ,
The first term does not depend on , so the smallest value is at . (To get the identity, write and expand; the cross term has conditional mean 0.)
Now compute the conditional mean for each model.
- Random walk. . The future have mean 0 and are independent of the past, so : the naive forecast.
- Random walk with drift. , so the best forecast is . The drift is unknown. Estimate it by the average change: , because the sum telescopes. This gives the drift forecast.
- Seasonal random walk. Each season is its own random walk, so the best forecast of a future value is the last observed value of the same season: the seasonal naive forecast.
- White noise around . The best forecast is ; the sample mean estimates it.
The fan. For the random walk, the forecast error is , a sum of independent terms, so its variance is . The error grows like : the prediction interval opens like a fan. With normal errors, a 95 % prediction interval is . The standard deviations of the four benchmarks (FPP3, §5.5, Table 5.2; is the standard deviation of the residuals):
| Method | |
|---|---|
| mean | |
| naive | |
| seasonal naive | , |
| drift |
For the drift forecast the error is with . The two parts are independent, so the variance is : the extra term is the uncertainty of the estimated slope. Lesson 10 checks whether such intervals have the coverage they promise.
3.3 Checking residuals #
A good forecasting method leaves residuals that look like white noise. Check, in this order:
- Uncorrelated. If the residuals are correlated, the method missed information that is in the past values. Look at the ACF of the residuals and run the Ljung–Box test (lesson 02): , compared with a distribution with degrees of freedom (minus the number of fitted parameters, for models from lesson 05 on). FPP3 suggests for non-seasonal data and for seasonal data.
- Mean zero. A nonzero mean is a bias: add the mean to the forecasts to remove it.
- Constant variance (homoscedastic). If the spread grows with the level, try a log transform (lesson 01).
- Roughly normal. Needed only for the normal prediction intervals above.
Properties 1 and 2 are essential. Properties 3 and 4 only matter for intervals. A method can pass all four checks and still forecast badly; residual checks never replace a backtest.
3.4 Split by time, never at random #
A holdout split for time series is a split in time order: the training set is , the test set is . A random split is wrong in general for two reasons:
- Neighbours are correlated. A test point with training points and on both sides can be interpolated. A real forecast must extrapolate into the future, which is harder. The error estimate becomes too small.
- The future is in the training set. Information after (a new level, a trend change) helps to predict . In real use that information does not exist yet.
3.5 Rolling-origin evaluation #
Definition. A rolling-origin evaluation (backtest, time series cross-validation) uses forecast origins . At each origin :
- the training set is (expanding window) or for a fixed length (sliding window);
- the test set is , where is the gap;
- the origins are spaced by a step : .
The error at horizon is the average over the origins: .
Expanding or sliding? An expanding window uses all the data and gives stable estimates. A sliding window follows a series whose behaviour changes, and it shows how the method works with a fixed amount of history. Use the scheme you will use in production.
Report each horizon separately. A one-step error and a twelve-step error answer different questions: the error usually grows with . If you average all horizons into one number, say so, and also show the curve .
The gap (embargo). Leave values out between training and test when information near the origin is not really available at forecast time:
- the target is known late (sales are corrected two weeks later; a medical outcome is known after 30 days);
- features are built from windows that overlap the test period (a centred moving average, a label defined over the next 7 days);
- you will really forecast from an older origin (data arrive with a delay of 3 days, so the forecast for "tomorrow" is a 4-step forecast).
In finance this idea is called an embargo, together with purging training samples whose labels overlap the test period (López de Prado 2018).
In scikit-learn. sklearn.model_selection.TimeSeriesSplit(n_splits, max_train_size, test_size, gap)
makes expanding folds whose test windows have test_size points and follow each other without
overlap (the step equals test_size). max_train_size turns it into a sliding window, and gap
removes that many points from the end of each training set. The folds start from the end of the
series: the last fold always tests the last test_size points.
When is ordinary K-fold cross-validation acceptable?
Bergmeir, Hyndman and Koo (2018) show that standard K-fold cross-validation is valid for a purely autoregressive model (the inputs are lagged values ) fitted to a stationary series, if the model's errors are uncorrelated. Then each row is a fair test example, and K-fold uses the data better than a single holdout. When the model underfits, its errors are correlated, and K-fold becomes too optimistic. The result does not cover non-stationary series (trend, level shifts) or models with other inputs. The last figure of this lesson shows both cases: on a series with a trend, random folds flatter a k-nearest-neighbour model a lot, but they agree with the truth for a linear model on lags.
3.6 Point-forecast metrics #
Let , , be the forecast errors of a test set (all origins and horizons you want to summarise).
| Metric | Formula | Units and remarks |
|---|---|---|
| MAE (mean absolute error) | units of | |
| RMSE (root mean squared error) | units of ; large errors count more | |
| MAPE (mean absolute percentage error) | percent; undefined if some , huge if is near 0 | |
| sMAPE (symmetric MAPE, M4 version) | percent; between 0 and 200; not really symmetric | |
| WAPE (weighted absolute percentage error) | a ratio; the same as MAE divided by the mean of | |
| MASE (mean absolute scaled error) | with | no units; is defined below |
| RMSSE (root mean squared scaled error) | no units; used in the M5 competition |
MAE and RMSE are scale-dependent: you cannot average them over series with different units or sizes. Percentage errors have no units, but they need a meaningful zero (they make no sense for temperatures in °C) and they explode near .
MASE (Hyndman and Koehler 2006) divides by the in-sample MAE of the one-step seasonal naive forecast on the training data :
For non-seasonal data use (the naive forecast). For RMSSE, is the mean of the squared differences .
- MASE < 1: the forecasts on the test set are, on average, better than the one-step seasonal naive forecasts were on the training set.
- MASE > 1: they are worse. This is not the same as "worse than the seasonal naive method on the test set": the scale is in-sample and one-step, while the test errors are often several steps ahead. Even the seasonal naive method itself often has MASE > 1 on a test set.
- The scale uses only training data, so it is known at the origin and it is positive unless the training data are exactly periodic.
A method has MASE on a test set. What does this say?
MASE divides the test MAE by a fixed scale: the MAE of the one-step seasonal naive forecast on the training data. So 1.3 means "30 % larger errors than that in-sample benchmark". To know whether you beat the seasonal naive method on the test set, compute its MASE on the same test set and compare the two numbers.
3.7 Which forecast does each metric reward? #
A point forecast is one number, but the future value is uncertain: it has a distribution. Each metric is minimised by a different summary of that distribution. Let have the predictive distribution with CDF and density .
Theorem.
- is smallest at the mean .
- is smallest at the median of .
- (the MAPE of a constant forecast) is smallest at the median of the distribution with density proportional to . This value is below the median of .
Proof.
- This is the identity of section 3.2 without conditioning.
- Write . Its derivative in is . This is negative for below the median and positive above it, so the minimum is at .
- . Up to a constant factor, this is for a variable with density divided by its integral. By part 2 the minimum is the median of . The weight is larger for small values, so the distribution of is shifted towards small values, and its median is below the median of .
The log-normal case: the MAPE-optimal value is
Let , so . Then . Complete the square in : . The last two terms do not depend on . So is proportional to the log-normal density with parameters and . The median of that distribution is . For , : mean , median , MAPE-optimal value .
Drag the orange forecast across the skewed data. The three curves are , and , each divided by its own minimum. Their minima sit at the mean, the median and a much smaller value. Switch to symmetric data: the mean and the median now agree.
Consequence: choose the metric from the decision, then the forecast. If the cost of an error grows like its square (large errors are very expensive), report the mean and evaluate with RMSE. If the cost grows linearly, report the median and evaluate with MAE. Do not use MAPE to choose between methods for skewed positive data unless you want forecasts that are too low. When you need several quantiles, use the pinball loss of lesson 10.
Daily demand is skewed: most days are small, a few days are very large. You must report one constant forecast and you are judged by MAE. Which constant is best?
The derivative of is , which is 0 at the median. The mean minimises squared error; with right-skewed data it is pulled up by the large days and has a larger MAE. A value below the median is what MAPE rewards.
3.8 Leakage in evaluation #
Leakage means that the model, or any step before it, used information that would not be available at the forecast origin. The backtest then reports an error that you will never see in real use. The general rule: at each origin, simulate exactly what was known at that time.
Common forms in forecasting:
- Preprocessing on the whole series. A scaler, a log-mean, a decomposition (STL, classical) or a missing-value fill computed on all data, before the split. Fit every step inside each fold, on the training window only.
- Filling missing values from the future. Back-fill (
bfill) and centred interpolation use values after the gap. Use forward-fill or a model of the past only. - Tuning on the test period. Choosing the smoothing parameter, the lag order or the network size by looking at test errors. Tune inside the training window (a nested backtest), and keep a final test period untouched.
- Revised data (vintages). GDP, sales and sensor data are often corrected later. A backtest on today's corrected values uses information that did not exist at the origin. Use the data vintage that was available at each origin, when you have it.
- Covariates not known at forecast time. Observed weather used as an input, as if it were a weather forecast; a promotion flag that is decided after the forecast. Use the forecast of the covariate, or its value at the origin.
One model, three error estimates. The model predicts from . Its error is estimated by random 5-fold cross-validation, by a rolling origin inside the history, and measured on the true future (the last 50 points). With k-nearest neighbours, random folds are far too optimistic: the neighbours of a test row come from both sides of it in time. In the true future, many values lie above the range of the training data, and k-NN cannot predict outside that range. Switch to linear regression on lags: averaged over 30 series, the three estimates now agree (the deeper box of section 3.5 says why).
You standardise a series with the mean and standard deviation of all 10 years, then run TimeSeriesSplit with 5 folds. What is wrong?
The split is in time order, but the preprocessing happened before the split. The mean and standard deviation of all 10 years include the test years (for example a later rise in level). Fit the scaler inside each fold, on the training window only: in scikit-learn, put it in a Pipeline together with the model.
3.9 Comparing two methods #
- Average over many origins and many series. With few origins the ranking of two methods is often noise.
- Use the same folds for both methods. Then the differences are paired, and the comparison is much more precise.
- Look at the curve per horizon, not only at the average.
The Diebold–Mariano test
To test whether two methods have the same expected loss at horizon , compute the loss differential for the test errors of the two methods (for example or ), over origins. Under the null hypothesis . The statistic is
where is the sample autocovariance of at lag . For large , DM is approximately standard normal (Diebold and Mariano 1995). The sum goes up to lag because -step errors from origins one step apart share future shocks, so they are correlated. For small , Harvey, Leybourne and Newbold (1997) give a corrected version with a distribution. The test compares forecasts, not models: it says nothing about which model is "true".
Answers to section 1. (1) The seasonal naive forecast. With a strong yearly pattern and no trend, "same month last year" keeps the pattern; "repeat the last value" gives a flat line and misses every seasonal swing. (2) Something below the median. MAPE divides by the true value, so errors on small values cost more; section 3.7 shows that the best constant for MAPE is the median of a distribution shifted towards small values (for a log-normal, ). (3) Too low. A random fold lets the model interpolate between neighbours and see the future level, so random K-fold is usually too optimistic. It is acceptable only in the special case of the deeper box in section 3.5.
4. Worked example #
(a) Benchmarks and metrics by hand. A quarterly series () has three years of training data and one year of test data:
| Q1 | Q2 | Q3 | Q4 | |
|---|---|---|---|---|
| year 1 () | 10 | 14 | 8 | 12 |
| year 2 () | 12 | 15 | 9 | 14 |
| year 3 () | 12 | 17 | 10 | 15 |
| year 4, test () | 14 | 19 | 11 | 16 |
The origin is and .
Step 1: the four forecasts.
- Mean: for every .
- Naive: for every .
- Seasonal naive: for , , so : the values of year 3.
- Drift: slope . Forecasts : .
Step 2: errors on the test year .
| Method | ||||
|---|---|---|---|---|
| mean | 1.67 | 6.67 | −1.33 | 3.67 |
| naive | −1 | 4 | −4 | 1 |
| seasonal naive | 2 | 2 | 1 | 1 |
| drift | −1.45 | 3.09 | −5.36 | −0.82 |
Step 3: the MASE scale. The in-sample seasonal naive errors are for : , , , , , , , . Their absolute values sum to 10, so .
Step 4: the metrics. For the seasonal naive forecast: ; ; ; ; .
| Method | MAE | RMSE | MAPE (%) | MASE |
|---|---|---|---|---|
| mean | 3.33 | 3.95 | 20.5 | 2.67 |
| naive | 2.50 | 2.92 | 17.7 | 2.00 |
| seasonal naive | 1.50 | 1.58 | 10.0 | 1.20 |
| drift | 2.68 | 3.21 | 20.1 | 2.15 |
The seasonal naive forecast wins on every metric. Its MASE is still above 1: its test errors (one to four steps ahead, one year later, with a small upward trend) are larger than its in-sample one-step errors. The trend of about one unit per year is visible in its errors: all four are positive. A method that combines the season with a trend (lesson 04) can do better.
(b) Listing the folds. , expanding window, initial training size 12, , step 4, gap 0. The origins are 12 and 16 (the next one, 20, has no test data left):
| Fold | training indices | test indices |
|---|---|---|
| 1 | 1–12 | 13–16 |
| 2 | 1–16 | 17–20 |
This is exactly TimeSeriesSplit(n_splits=2, test_size=4) on 20 points (with indices from 0 in
Python). With gap=1, the training sets would end at 11 and 15 instead.
5. In code #
NumPy checks the worked example. The notebook has these cells and the exercises.
import numpy as np
y_train = np.array([10, 14, 8, 12, 12, 15, 9, 14, 12, 17, 10, 15.])
y_test = np.array([14, 19, 11, 16.])
m, n, H = 4, len(y_train), len(y_test)
h = np.arange(1, H + 1)
fc = {
"mean": np.full(H, y_train.mean()),
"naive": np.full(H, y_train[-1]),
"snaive": y_train[n + h - m * ((h - 1) // m + 1) - 1], # -1: Python indices start at 0
"drift": y_train[-1] + h * (y_train[-1] - y_train[0]) / (n - 1),
}
scale = np.mean(np.abs(y_train[m:] - y_train[:-m]))
print("scale", scale) # scale 1.25
for name, f in fc.items():
e = y_test - f
print(f"{name:7s} MAE {np.mean(np.abs(e)):.2f} RMSE {np.sqrt(np.mean(e**2)):.2f} "
f"MAPE {100 * np.mean(np.abs(e) / y_test):.1f} MASE {np.mean(np.abs(e)) / scale:.2f}")
# mean MAE 3.33 RMSE 3.95 MAPE 20.5 MASE 2.67
# naive MAE 2.50 RMSE 2.92 MAPE 17.7 MASE 2.00
# snaive MAE 1.50 RMSE 1.58 MAPE 10.0 MASE 1.20
# drift MAE 2.68 RMSE 3.21 MAPE 20.1 MASE 2.15
from sklearn.model_selection import TimeSeriesSplit
for tr, te in TimeSeriesSplit(n_splits=2, test_size=4).split(np.arange(20)):
print(tr[0], tr[-1], te)
# 0 11 [12 13 14 15]
# 0 15 [16 17 18 19]
6. Where it shows up #
- Forecasting competitions. The M3, M4 and M5 competitions rank methods by sMAPE, MASE and (M5) a weighted RMSSE, always against naive and seasonal naive benchmarks. The M4 results showed that simple statistical benchmarks are hard to beat (Makridakis et al. 2020).
- Demand and energy forecasting. Retailers report WAPE (it weights each product by its volume); electricity load forecasts are evaluated per horizon, because a day-ahead error and an hour-ahead error lead to different actions.
- Finance. Trading strategies are tested with walk-forward backtests (a rolling origin with refitting). Purging and an embargo remove training samples whose labels overlap the test period (López de Prado 2018). Leakage here gives strategies that only work in the past.
- Machine learning models for time series. Gradient boosting (lesson 08) and deep networks (lesson 09) are judged by the same backtests and by their MASE relative to seasonal naive. Foundation models for time series are compared on held-out series and periods; overlap between pretraining data and the test data is a form of leakage.
- ML for science. Machine-learning weather models are trained on earlier years of reanalysis data and tested on later years they never saw (for example GraphCast, Lam et al. 2023); the skill score of a forecast is often reported relative to a reference forecast such as climatology or persistence, which play the roles of the mean and naive benchmarks. Drift monitoring of deployed models uses the same idea (mlops lesson 07).
7. Common mistakes #
- No benchmark. A complex model with MAPE 8 % sounds good until the seasonal naive forecast has 7 %. Always report the benchmarks on the same folds.
- Shuffled cross-validation.
KFold(shuffle=True)on time series lets the model interpolate and see the future. Use a time-ordered split, unless the special conditions of Bergmeir et al. hold. - One test period. One split of the last 3 months is one sample. Use many origins.
- Residual error reported as accuracy. In-sample residuals are too small. Report errors on data that the method did not see.
- Preprocessing before the split. Scaling, decomposition, feature selection and imputation must be fitted inside each training window.
- Averaging errors over horizons without saying so. The error at and at are different quantities. Show .
- MAPE on data with zeros or values near zero. It is undefined or dominated by a few points, and it rewards forecasts that are too low. Use MASE or WAPE.
- Averaging MAE over series with different scales. The series with the largest values dominate. Use a scaled metric (MASE, RMSSE) to average across series.
8. Check yourself #
- A daily series has a weekly pattern (). The origin is Sunday, day . What is the
seasonal naive forecast for the next Wednesday, , and for the Wednesday after that, ?
Answer
For : , so , the last observed Wednesday. For : , so again. The seasonal naive forecast repeats the last observed week. - Show that the naive forecast is the best mean-squared-error forecast for a random walk, and give
the variance of its -step error.
Answer
. The future shocks have mean 0 and are independent of the past, so . The conditional mean minimises the expected squared error. The error is the sum of independent shocks, so its variance is . - Compute MASE for the naive forecast of the worked example, and say what it means.
Answer
The naive errors are , so MAE . The scale is , so MASE . Its test errors are twice as large as the in-sample one-step errors of the seasonal naive method. It ignores the strong season. - A demand series has many days with zero sales. Your manager wants MAPE. What do you say, and
what do you propose?
Answer
MAPE divides by , so it is undefined on days with zero sales and very large on days with small sales; it also rewards forecasts that are too low. Propose MASE (scale-free, defined unless the training data are exactly periodic) or WAPE (total absolute error divided by total sales, which is well defined as long as total sales are positive). - Your features include a 7-day centred moving average of the target. You backtest with
TimeSeriesSplit(gap=0). What leaks, and how large should the gap be?Answer
A centred 7-day average at time uses . For the last training rows these values lie in the test window, so test targets leak into training features. A gap of at least 3 removes this overlap. Better: use a trailing average, which only uses past values, and keep the gap for delays in data arrival. - Why does the seasonal naive method itself often have a MASE above 1 on the test set?
Answer
The MASE scale is the in-sample MAE of *one-step* seasonal naive forecasts. On the test set the seasonal naive method forecasts up to steps ahead, often with a trend or a change in level between the training and the test period. Its errors are then larger than its one-step in-sample errors.
Name the four benchmark forecasts.
Mean (average of the past), naive (last value), seasonal naive (value one season earlier), drift (line through the first and last observation).
Write the seasonal naive forecast .
with : the last observed value of the same season.
For which model is the naive forecast optimal, and how fast does its error grow?
For a random walk . The -step error has variance , so the interval grows like .
What is rolling-origin evaluation?
Forecast from many origins ; at each one, fit on data up to the origin only, forecast the next values, then average the errors over origins for each horizon.
Expanding window or sliding window: what is the difference?
An expanding window always starts at and grows; a sliding window keeps a fixed length and drops the oldest values.
Why does random K-fold cross-validation usually leak on time series?
Test points have training neighbours on both sides in time, so the model interpolates and uses information from the future; the error estimate is too optimistic.
Define MASE.
Test MAE divided by the in-sample MAE of the one-step seasonal naive forecast, .
Which constant forecast minimises MSE, and which minimises MAE?
The mean minimises MSE; the median minimises MAE.
Why does MAPE reward forecasts that are too low?
It divides each error by the true value, so errors on small values cost more; its best constant is the median of a distribution weighted by , which lies below the median.
What does a gap (embargo) between training and test data prevent?
Leakage when labels become known late or when features use windows that overlap the test period; it also simulates a delay in data arrival.
9. Interview angle #
- "How would you evaluate a forecasting model?" — A rolling-origin backtest with the same folds for all methods, refit (or update) at each origin, errors per horizon, and a comparison with naive and seasonal naive benchmarks using MASE.
- "Can you use K-fold cross-validation on time series?" — Not in general: shuffled folds interpolate and see the future. Exception: a purely autoregressive model with uncorrelated errors on a stationary series (Bergmeir et al. 2018).
- "MAPE or RMSE?" — It depends on the cost of errors. RMSE rewards the mean, MAE the median, MAPE a biased low value and fails near zero. For many series of different scales use MASE or WAPE.
- "Your model has great backtest results but fails in production. Why?" — Leakage: preprocessing on all data, future-filled missing values, revised data, covariates not known in time, tuning on the test period; or a backtest that did not match the production delay (a missing gap).
10. Practice #
The notebook for this lesson runs in Colab. It has five exercises, each with a check cell and a folded solution:
- Write
mean_forecast,naive,snaiveanddriftfor a horizon , and check them on the worked example. - Write
rolling_origin_splits(n, initial, horizon, step, gap, expanding)and check it againstTimeSeriesSplitwhere the two agree. - Write
mase(y_train, y_test, y_pred, m)and check it on the worked example. - Backtest the four benchmarks on monthly Mauna Loa CO₂ data (1980–2001) and make a table of MASE by horizon.
- Reproduce the optimism of random K-fold with a k-nearest-neighbour model on lags, and compare it with a rolling origin and with a true future block.
11. Watch and read #
- Hyndman and Athanasopoulos, Forecasting: Principles and Practice, 3rd ed., free online: §5.2 simple methods, §5.4 residual diagnostics, §5.8 accuracy, §5.10 time series cross-validation.
- Hyndman and Koehler (2006), Another look at measures of forecast accuracy, International Journal of Forecasting 22(4): the paper that introduced MASE.
- Bergmeir, Hyndman and Koo (2018), A note on the validity of cross-validation for evaluating autoregressive time series prediction, Computational Statistics and Data Analysis 120.
- Tashman (2000), Out-of-sample tests of forecasting accuracy: an analysis and review, International Journal of Forecasting 16(4): rolling origins and their variants.
- Makridakis, Spiliotis and Assimakopoulos (2020), The M4 Competition: 100,000 time series and 61 forecasting methods, International Journal of Forecasting 36(1).
- Diebold and Mariano (1995), Comparing predictive accuracy, Journal of Business and Economic Statistics 13(3).
- scikit-learn,
TimeSeriesSplit.
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.