Time Series Forecasting 📈

Class 12Age 16-17Lesson 09 of 12🆓 Free
Class 12 Lesson 09 hero — Anjali, Delhi
Watch first - 2-3 minutes

Class 12 Lesson 9 - Time Series Forecasting

No sign-in needed - English narration - Safe for all school ages

Story
Anjali's Mithai Shop Forecast
👩‍💼 Anjali · Delhi · Age 17

Anjali's family runs a sweet shop in Karol Bagh. They threw away ₹40,000 of unsold mithai every month — and ran out of besan ladoo on Diwali two years running. Anjali built a forecasting system using Prophet (with Indian holidays) and N-BEATS.

Eight months later: waste down to ₹3,000/month, zero stockouts on festivals, and her father uses the dashboard daily. Total saving: ~₹3 lakhs/year.

Theory
Components of a Time Series

Every time series can be decomposed into three signals:

  1. Trend: The long-term direction. Anjali's shop grew 8% YoY.
  2. Seasonality: Repeating patterns. Weekly (weekend spike), yearly (Diwali, Holi, Karva Chauth), and even hourly.
  3. Residual: What's left after removing trend + seasonality. Often modelled as noise or with autoregression.
MethodWhen to UseProsCons
ARIMAShort series, simple seasonalityInterpretable, classicManual order tuning
ProphetDaily data with holidaysAuto-tunes, handles holidaysLimited features
N-BEATSLong series, complex patternsSOTA accuracy, no feature engineeringLess interpretable
TFT (Temporal Fusion Transformer)Multi-variate, multi-horizonHandles many features + attention explanationsCompute heavy
Chronos / TimeGPT (foundation models)Zero-shot forecastingNo training neededBlack box, costly API
Code
Prophet with Indian Holidays
!pip install -q prophet

import pandas as pd
from prophet import Prophet
from prophet.make_holidays import make_holidays_df

# Load 3 years of daily ladoo sales
df = pd.read_csv("ladoo_sales.csv")  # columns: ds, y
df["ds"] = pd.to_datetime(df["ds"])

# Indian holidays — built-in support
holidays = make_holidays_df(year_list=[2023, 2024, 2025, 2026], country="IN")

# Add custom mithai-relevant events
custom = pd.DataFrame({
    "holiday": "raksha_bandhan_week",
    "ds": pd.to_datetime(["2024-08-19", "2025-08-09", "2026-08-28"]),
    "lower_window": -3, "upper_window": 1,  # spike starts 3 days before
})
holidays = pd.concat([holidays, custom])

m = Prophet(
    holidays=holidays,
    yearly_seasonality=True,
    weekly_seasonality=True,
    daily_seasonality=False,
    seasonality_mode="multiplicative",  # spikes scale with trend
    changepoint_prior_scale=0.05,       # default; raise to fit faster trend changes
)
m.fit(df)

future = m.make_future_dataframe(periods=60)        # 60-day forecast
forecast = m.predict(future)

# yhat = point estimate, yhat_lower / yhat_upper = 80% confidence interval
print(forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail(10))
m.plot(forecast)
m.plot_components(forecast)  # trend / weekly / yearly / holidays
Code
N-BEATS for Higher Accuracy
!pip install -q neuralforecast

from neuralforecast import NeuralForecast
from neuralforecast.models import NBEATS

# Same dataframe but renamed to neuralforecast convention
df_nf = df.rename(columns={"ds": "ds", "y": "y"})
df_nf["unique_id"] = "ladoo"   # one series — could be many if multi-shop

model = NBEATS(
    h=60,                       # forecast horizon = 60 days
    input_size=180,             # use last 180 days as input
    max_steps=2000,
    stack_types=["trend", "seasonality"],
    n_blocks=[3, 3],
    mlp_units=[[256, 256], [256, 256]],
    learning_rate=1e-3,
    early_stop_patience_steps=20,
)
nf = NeuralForecast(models=[model], freq="D")
nf.fit(df_nf)

predictions = nf.predict()
print(predictions.head())

N-BEATS often beats Prophet on long, noisy series because it learns trend and seasonality basis functions directly from data rather than assuming a fixed parametric form.

Production
Evaluation, Drift, and Inventory Decisions

Right metrics:

Drift handling: Retail patterns shift (new metro line opens, competitor closes). Anjali retrains weekly and runs a drift detector — if MAPE jumps 30% above baseline for 3 consecutive days, alert.

From forecast to inventory: Raw forecasts mislead. Anjali uses the upper 80% confidence interval for perishable items (better to slightly over-stock than stockout) and the lower 60% for non-perishable packaging (cash-flow optimisation). The forecast is one input — final order quantity also factors in: shelf life, safety stock, supplier lead time, cash on hand.

Anjali's outcome: ₹40,000 → ₹3,000/month waste. Zero Diwali stockouts. The dashboard runs on a ₹4,500 Raspberry Pi in the shop. Her father — who never used a computer — checks tomorrow's forecast every evening at 9 PM.

📝 Check Your Understanding (8 Questions)

1. What are the three components of a classical time-series decomposition?
a) Mean, variance, and skewness
b) Trend (long-term direction), seasonality (repeating patterns at fixed periods), and residual (everything left over after removing trend + seasonality)
c) Past, present, and future
d) X-axis, Y-axis, and Z-axis
2. Why does Anjali use Prophet's built-in Indian holiday list plus custom events?
a) Prophet refuses to fit data without a holiday parameter
b) Mithai sales spike sharply on Diwali, Raksha Bandhan, Karva Chauth, etc.; without holidays, the model would treat these spikes as noise and over- or under-forecast around them. Custom 'lower_window=-3' captures the pre-festival ramp-up
c) Indian holidays are required for Prophet to converge
d) Prophet only supports holiday-based forecasts
3. What does seasonality_mode='multiplicative' mean in Prophet?
a) The model multiplies the data by 2 before fitting
b) Seasonal effects scale proportionally with the trend — a 50% Diwali spike on a ₹10K baseline becomes a 50% spike on a ₹15K baseline next year, not a fixed ₹5K spike. Right for retail; wrong for stationary processes
c) It enables multi-output forecasting
d) It runs the model on multiple GPUs
4. Why does N-BEATS often outperform Prophet on long, noisy series?
a) N-BEATS uses GPU acceleration
b) N-BEATS learns trend and seasonality basis functions directly from data via stacked residual blocks, instead of assuming a fixed parametric form (Fourier series + piecewise-linear trend). It captures patterns Prophet's prior assumptions miss
c) N-BEATS does not need any training data
d) N-BEATS only handles English text inputs
5. What does MASE < 1 indicate?
a) The model has overfit
b) The model is more accurate than the naive baseline (predicting today's value will equal yesterday's). MASE >= 1 means you have not beaten the trivial 'no model' forecast and your model adds no value
c) The model uses less than 1 GB of memory
d) The data has fewer than 1,000 points
6. Why does Anjali order based on the upper 80% confidence interval for perishables but the lower 60% for packaging?
a) It is the only choice the Prophet API allows
b) For perishables, the cost of stockout (lost sale + customer disappointment) is higher than the cost of slight overstock — so she orders for the optimistic case; for packaging (non-perishable), cash flow matters more, so she orders conservatively. The right quantile depends on cost asymmetry
c) Higher percentiles use more memory
d) 80% is the default and 60% is the minimum
7. What is concept drift in time-series forecasting and why does it matter?
a) A bug in the Prophet library
b) The underlying pattern changes (new metro station opens, competitor closes, pandemic) so the model trained on old data systematically errs; detect by monitoring MAPE vs baseline and trigger a retrain when drift exceeds a threshold for several consecutive days
c) When the time-series data is shuffled accidentally
d) It happens only in financial time series
8. Why is the forecast only one input to Anjali's final order quantity?
a) Because forecasts are always wrong
b) A point forecast ignores shelf life, supplier lead time, safety stock policy, cash on hand, and the asymmetric cost of stockout vs waste — the final inventory decision combines forecast + business constraints + risk preference
c) Because she does not trust her own model
d) Because Prophet outputs are illegal in India
← Lesson 8: AI at Scale Lesson 10: AI Product Management →