Time Series Forecasting

By the end of this lesson you'll break a series into trend, seasonality, and noise, smooth it, build a forecast, split it correctly for time, and measure how good your prediction is.

Learn Time Series Forecasting in our free AI & Machine Learning course — a beginner-friendly interactive lesson with worked examples, a practice exercise and…

Part of the free AI & Machine Learning course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

🌦️ Real-World Analogy: Predicting the Weather

Guessing tomorrow's weather is like driving while glancing at the rear-view mirror. You read recent patterns — the last few days were warm, summer is the warm season , today was a fluke cold snap — and project them forward.

Time-series forecasting formalises that intuition. It splits the past into three parts and projects each one ahead:

The crucial difference from ordinary machine learning: observations are not independent . Yesterday's value heavily shapes today's, so order is everything. Lose the order and you lose the signal.

1 The Three Building Blocks: Trend, Seasonality, Noise

Any series can be thought of as those three pieces added together: value = trend + seasonality + noise . Pulling them apart is called decomposition , and it tells you what you can actually predict (trend and seasonality) versus what you can't (noise).

If the seasonal swing grows as the level grows (e.g. a busy shop's December spike gets bigger every year), the pieces multiply instead of adding — that's a multiplicative model. Otherwise it's additive .

2 Smoothing: Moving Averages and Exponential Smoothing

Raw data is jagged. Smoothing averages nearby points so the underlying shape shows through. A moving average (MA) replaces each point with the mean of itself and the previous few — a window of, say, 3. A bigger window is smoother but lags further behind turns.

Exponential smoothing is the smarter cousin: instead of treating every value in the window equally, it weights recent values more, with the weight decaying as you go back. One number, alpha (between 0 and 1), controls it — high alpha reacts fast to recent change, low alpha stays calm and slow. The formula is just s = alpha * actual + (1 - alpha) * previous .

The worked example below uses plain Python so you can see exactly how a moving average is computed — then it builds the simplest possible forecast.

🎯 Your Turn 1: Compute a Moving Average

Fill in the two blanks so the function returns a 3-day moving average. One blank is the divisor that turns a sum into an average; the other is the window size.

3 Lag Features: Turning a Series into an ML Table

Ordinary ML models expect a table of rows and feature columns — they don't understand "time". The trick is to build lag features : for each row, the inputs are the previous values (t-1, t-2, t-3…) and the target is the current value. Once your series looks like a normal table, you can throw any model at it — linear regression, random forest, XGBoost.

In pandas, .shift(1) pushes the series forward one step (so each row sees the past), and .rolling(3).mean() adds a rolling average feature. The early rows are NaN until enough history exists.

4 Stationarity: Why Classical Models Want a Flat Series

A series is stationary when its statistical behaviour doesn't drift: the mean, the variance, and the way values relate to their neighbours all stay roughly constant over time. A series with a clear upward trend is not stationary — its mean keeps climbing.

Classical models like ARIMA assume stationarity, so you make a series stationary by differencing it: replace each value with the change from the previous value ( y[t] - y[t-1] ). That removes a linear trend. You can test for stationarity with the Augmented Dickey-Fuller (ADF) test — a p-value below 0.05 means "stationary enough".

5 Train / Test Split for Time — Never Shuffle!

In normal ML you shuffle your data before splitting. For time series you must not. The whole point is to predict the future from the past, so your test set has to be strictly later in time than your training set. Train on the earliest 80%, evaluate on the most recent 20%.

Shuffling — or using scikit-learn's default train_test_split(..., shuffle=True) — lets the model peek at future values during training. That's look-ahead leakage , and it produces beautiful accuracy that collapses in production.

🎯 Your Turn 2: Naive Forecast + MAE

Build a 1-step naive forecast (tomorrow = today) by shifting the series, then measure its Mean Absolute Error. Fill in the two blanks and check the expected output.

6 Classical Models: ARIMA & Exponential Smoothing

ARIMA(p, d, q) combines three ideas: AR (predict from p past values), I (difference the series d times to make it stationary), and MA (correct using q past forecast errors). It's a strong, interpretable baseline for trended data.

Exponential smoothing (in its full Holt-Winters form) tracks a smoothed level, a trend, and a seasonal component, weighting recent data most. It's often the easiest way to get a solid seasonal forecast.

🤖 ML and Deep Learning: When to Reach for an LSTM

7 Evaluating a Forecast: MAE, RMSE, MAPE

A forecast is only as good as the number you score it with. Three metrics cover most cases, all computed on the test set (the future the model didn't see):

8 Common Errors (And How to Fix Them)

These four mistakes ruin more forecasts than any modelling choice:

A random split scatters future rows into the training set:

✅ Fix: split by position, keeping time order:

Building a feature that includes the value you're predicting (or scaling using the whole dataset):

✅ Fix: shift first so every feature is strictly past:

A plain trend model misses the weekly/yearly cycle and forecasts a smooth line through every peak and dip.

✅ Fix: model the season — use a seasonal-naive baseline, Holt-Winters with seasonal_periods , or add a month / day_of_week feature.

A strong trend with d=0 gives wild, drifting forecasts.

✅ Fix: difference the series (raise d ) until the ADF p-value drops below 0.05, then fit.

📋 Quick Reference

Method

Best For

Limitation

Naive / seasonal-naive

The baseline you must beat

Ignores trend & structure

Moving average

Visualising trend, smoothing

Lags behind, no forecast

Exponential smoothing

Short-term, seasonal forecasts

No external features

ARIMA

Trended, near-stationary data

Needs differencing / tuning

Lag features + ML

Adding calendar / external data

Feature-engineering effort

LSTM / GRU

Long, complex sequences

Needs lots of data

Metric

Meaning

Use when

MAE

Avg absolute error (data units)

You want a plain, robust number

RMSE

Like MAE but penalises big misses

Large errors are costly

MAPE

Avg error as a %

Comparing across series (actuals not near 0)

❓ Frequently Asked Questions

🎯 Mini-Challenge: Seasonal-Naive Forecast + RMSE

Support is faded now — only a comment outline is given. Write a seasonal-naive forecast (this period equals the value one full season ago) and score it with RMSE. The expected answer is in the comments so you can self-check.

Lesson 20 complete — you can forecast the future!

You can decompose a series into trend, seasonality, and noise; smooth it with moving averages and exponential smoothing; build lag features; split correctly by time without leakage; choose between ARIMA, exponential smoothing, and an LSTM; and score the result with MAE, RMSE, and MAPE.

🚀 Up next: Advanced Neural Networks — go deeper into the architectures (including the LSTMs you just met) that power modern sequence models.

Practice quiz

What three components is a time series commonly decomposed into?

  • Mean, median, and mode
  • Input, hidden, and output
  • Trend, seasonality, and noise
  • Train, validation, and test

Answer: Trend, seasonality, and noise. Decomposition splits a series into trend (slow drift), seasonality (repeating cycle), and noise (the unpredictable residual).

Why must you NOT shuffle time-series data before splitting train/test?

  • Shuffling lets the model see future values during training, causing look-ahead leakage
  • Shuffling is too slow on large datasets
  • Shuffling changes the data types
  • Shuffling is fine for time series

Answer: Shuffling lets the model see future values during training, causing look-ahead leakage. Order carries the signal; shuffling leaks future information into training, giving fake-high accuracy that collapses in production. Split by time instead.

What does it mean for a series to be stationary?

  • It never changes value
  • It has exactly one season per year
  • It contains no noise
  • Its mean, variance, and autocorrelation stay roughly constant over time

Answer: Its mean, variance, and autocorrelation stay roughly constant over time. A stationary series has constant statistical behaviour over time — no trend or changing seasonality. ARIMA assumes stationarity.

How do you typically make a trended series stationary for ARIMA?

  • Multiply every value by a constant
  • Difference it: replace each value with the change from the previous value
  • Shuffle the values randomly
  • Take the logarithm of the index

Answer: Difference it: replace each value with the change from the previous value. Differencing (y[t] - y[t-1]) removes a linear trend; the 'I' (integrated) term in ARIMA(p, d, q) controls how many times you difference.

What do the p, d, and q in ARIMA(p, d, q) stand for?

  • AR lagged values, number of differences, and MA lagged errors
  • Precision, depth, and quality
  • Periods, days, and quarters
  • Probability, distance, and quantile

Answer: AR lagged values, number of differences, and MA lagged errors. p = autoregressive lagged values, d = times to difference for stationarity, q = moving-average lagged forecast errors.

How does exponential smoothing differ from a simple moving average?

  • It weights every value in the window equally
  • It ignores recent values
  • It weights recent values more heavily, controlled by alpha
  • It only works on stationary series

Answer: It weights recent values more heavily, controlled by alpha. A moving average weights all window values equally and lags; exponential smoothing weights recent values more (via alpha), reacting faster.

What is the naive (lag-1) forecast?

  • The average of all past values
  • Tomorrow's prediction equals today's actual value
  • A forecast from a neural network
  • The median of the test set

Answer: Tomorrow's prediction equals today's actual value. The naive forecast simply says 'tomorrow = today' (forecast[t] = actual[t-1]). It is the baseline any real model must beat.

What is the key difference between RMSE and MAE?

  • RMSE is always negative
  • MAE can only be used on percentages
  • They are identical
  • RMSE squares errors so it punishes large misses more than MAE

Answer: RMSE squares errors so it punishes large misses more than MAE. MAE is the mean absolute error; RMSE squares the errors before averaging and rooting, so big misses are penalised more heavily.

When is MAPE (Mean Absolute Percentage Error) problematic?

  • When the data has a trend
  • When actual values are near zero, because the percentage blows up
  • When you compare across different series
  • When the series is stationary

Answer: When actual values are near zero, because the percentage blows up. MAPE expresses error as a percentage of the actual value, so it becomes unstable or huge when actuals are close to zero.

When does reaching for an LSTM pay off over ARIMA or exponential smoothing?

  • Always — LSTMs beat classical models on every dataset
  • Only on stationary series with no seasonality
  • Only with long, complex sequences and thousands of observations
  • When you have fewer than 50 data points

Answer: Only with long, complex sequences and thousands of observations. On small business datasets a naive baseline plus ARIMA or smoothing usually wins; LSTMs only pay off with long, complex sequences and lots of data.

Continue this course