Part X โ€” Specialized Domains

Time Series Analysis
& Forecasting

Master the art and science of predicting the future from historical temporal data โ€” from classical ARIMA to deep learning LSTMs.

๐Ÿ“– Chapter 27 โฑ๏ธ 4 Hours ๐Ÿ”— Prereq: Ch 19 ๐Ÿ“Š 24 Sections
1

Learning Objectives

By the end of this chapter, you will be able to:

  1. Decompose a time series into its core components: trend, seasonality, cyclical, and noise.
  2. Test for stationarity using the ADF (Augmented Dickey-Fuller) and KPSS tests, and apply differencing/transformations to achieve stationarity.
  3. Interpret ACF and PACF plots to identify appropriate model orders for AR, MA, and ARIMA models.
  4. Build and tune ARIMA(p,d,q) models including seasonal variants (SARIMA) using the Box-Jenkins methodology.
  5. Apply Exponential Smoothing methods: Simple, Holt's Linear Trend, and Holt-Winters Seasonal models.
  6. Use Facebook Prophet for time series forecasting with trend changepoints, holiday effects, and custom seasonality.
  7. Design LSTM networks using TensorFlow/Keras for sequence-to-one and sequence-to-sequence forecasting.
  8. Understand multivariate time series analysis using Vector Autoregression (VAR).
  9. Detect anomalies in time series data using statistical and ML-based approaches.
  10. Evaluate forecasts with MAPE, RMSE, SMAPE, and other metrics, knowing their tradeoffs.
  11. Apply time series methods to real-world Indian and global case studies, including Nifty50 forecasting, monsoon prediction, and energy demand.
  12. Build end-to-end mini projects โ€” Stock Price Forecaster and Weather Predictor.
๐ŸŽฏ Exam Tip

University exams heavily test stationarity concepts, ARIMA order selection from ACF/PACF plots, and deriving forecast equations. Be ready to interpret plots and perform hand calculations for small series.

2

Introduction

Time series data is everywhere โ€” from the minute-by-minute stock prices on the Bombay Stock Exchange to daily temperatures recorded by the India Meteorological Department, monthly GST revenues, and the second-by-second sensor readings in a smart factory. Unlike cross-sectional data where observations are independent, time series data has temporal ordering, and that ordering contains crucial information.

Time series analysis is the discipline of extracting meaningful statistics and characteristics from time-ordered data, while time series forecasting uses historical observations to predict future values. The applications span virtually every industry:

๐Ÿ‡ฎ๐Ÿ‡ณ India Spotlight

India's UPI (Unified Payments Interface) processes over 10 billion transactions per month. Time series forecasting helps NPCI and banks predict transaction volumes, detect anomalies during festivals (Diwali spike!), and capacity plan server infrastructure. The Reserve Bank of India (RBI) uses time series models to forecast inflation (CPI) and GDP growth for monetary policy decisions.

This chapter walks through the entire landscape โ€” from classical decomposition and ARIMA to modern deep learning (LSTM) and Meta's Prophet. We adopt a practitioner's approach: understand the theory, implement from scratch, then use production-ready libraries.

๐ŸŽ“ Professor's Insight

The most common mistake students make is applying machine learning models directly to time series without checking for stationarity. A non-stationary series violates the fundamental assumptions of most models. Always start with visualization, stationarity tests, and decomposition before modeling.

3

Historical Background

The study of time series has deep roots in astronomy, economics, and meteorology.

Timeline of Key Developments

YearMilestoneContributor
1927Yule introduces autoregressive (AR) models for sunspot dataG. Udny Yule
1937Slutzky formalizes the moving average (MA) processEugen Slutzky
1938Wold's decomposition theoremHerman Wold
1957Exponential smoothing methods proposedC.C. Holt, R.G. Brown
1960Seasonal Holt-Winters methodPeter Winters
1970Box-Jenkins methodology for ARIMAGeorge Box & Gwilym Jenkins
1979Dickey-Fuller test for unit rootsDavid Dickey & Wayne Fuller
1980Vector Autoregression (VAR) modelsChristopher Sims
1982ARCH models for volatilityRobert Engle
1986GARCH models generalize ARCHTim Bollerslev
1992KPSS stationarity testKwiatkowski et al.
1997Long Short-Term Memory (LSTM) architectureHochreiter & Schmidhuber
2017Facebook Prophet for scalable forecastingSean Taylor & Ben Letham
2019Temporal Fusion TransformersLim et al. (Google)
2020N-BEATS: Neural basis expansion for time seriesOreshkin et al.
2023TimeGPT & foundation models for time seriesNixtla & others

The Box-Jenkins methodology (1970) was the watershed moment. It provided a systematic approach โ€” identify, estimate, diagnose โ€” that remains the gold standard for classical time series modeling. George Box famously said, "All models are wrong, but some are useful," which perfectly captures the forecasting philosophy.

๐Ÿ‡ฎ๐Ÿ‡ณ India Spotlight

The India Meteorological Department (IMD), established in 1875, is one of the oldest meteorological organizations. Indian statistician P.C. Mahalanobis (of Mahalanobis distance fame) at the Indian Statistical Institute pioneered statistical approaches to monsoon forecasting in the 1930s. Today, IMD uses ensemble models combining statistical and dynamical methods to issue Long Range Forecasts (LRF) for the Indian monsoon season.

4

Conceptual Explanation

4.1 Time Series Components

Every time series Y(t) can be decomposed into four fundamental components:

Two decomposition models are common:

Additive Decomposition
Y(t) = T(t) + S(t) + C(t) + ฮต(t)
Multiplicative Decomposition
Y(t) = T(t) ร— S(t) ร— C(t) ร— ฮต(t)

Use additive when seasonal fluctuations are roughly constant regardless of the level. Use multiplicative when seasonal variation grows proportionally with the level (e.g., airline passengers โ€” the seasonal swing is larger when overall traffic is higher).

4.2 Stationarity

A time series is stationary when its statistical properties (mean, variance, autocorrelation) do not change over time. Most forecasting models require stationarity.

Strict vs. Weak Stationarity

Testing for Stationarity

Augmented Dickey-Fuller (ADF) Test:

KPSS Test:

๐ŸŽ“ Professor's Insight

ADF and KPSS have opposite null hypotheses! Use both as a confirmatory pair. If ADF says stationary AND KPSS says stationary, you're confident. If they disagree, the series might be "near unit root" โ€” consider differencing or fractional integration.

4.3 Differencing and Transformations

To make a non-stationary series stationary:

4.4 ACF and PACF

Autocorrelation Function (ACF) measures the correlation between Y(t) and Y(t-k) for lag k. It includes indirect correlations through intermediate lags.

Partial Autocorrelation Function (PACF) measures the direct correlation between Y(t) and Y(t-k), removing the effect of all intermediate lags.

ModelACF BehaviorPACF Behavior
AR(p)Decays gradually (exponential/oscillating)Cuts off after lag p
MA(q)Cuts off after lag qDecays gradually
ARMA(p,q)Decays graduallyDecays gradually

4.5 ARIMA Models

AR(p) โ€” Autoregressive: Current value depends on p past values.

MA(q) โ€” Moving Average: Current value depends on q past error terms.

ARIMA(p,d,q): Combines AR, differencing (d times), and MA. The I stands for "Integrated" โ€” it reverses differencing.

4.6 SARIMA

SARIMA extends ARIMA for seasonal data: SARIMA(p,d,q)(P,D,Q,m) where uppercase letters are seasonal orders and m is the seasonal period (e.g., 12 for monthly data with annual seasonality).

4.7 Exponential Smoothing

4.8 Prophet

Developed by Meta (Facebook), Prophet uses a decomposable additive model: y(t) = g(t) + s(t) + h(t) + ฮต(t) where g(t) is a piecewise-linear or logistic growth trend, s(t) is seasonality modeled with Fourier terms, and h(t) captures holiday effects. Prophet is designed to handle missing data, changepoints, and multiple seasonalities automatically.

4.9 LSTM for Time Series

Long Short-Term Memory networks are a type of recurrent neural network (RNN) that can learn long-range dependencies. They use a gating mechanism (forget, input, output gates) to selectively remember or forget information. For time series, the input is a sliding window of past observations, and the output is the forecast.

4.10 VAR โ€” Vector Autoregression

When you have multiple interrelated time series (e.g., Nifty50 + USD/INR + gold prices), VAR models capture the linear interdependencies. Each variable is a linear function of past lags of itself AND all other variables.

4.11 Anomaly Detection in Time Series

Anomalies are observations that deviate significantly from expected patterns. Methods include: statistical thresholds (z-score, IQR), forecast-based (flag points with large residuals), isolation forests, autoencoders, and Prophet's built-in uncertainty intervals.

๐Ÿญ Industry Alert

In production systems, the choice between classical (ARIMA) and ML (LSTM, Prophet) depends on: (1) data volume โ€” LSTM needs thousands of data points, ARIMA works with fewer, (2) interpretability โ€” ARIMA provides coefficient-level insight, (3) automation โ€” Prophet is designed for "analyst in the loop" at scale, and (4) latency โ€” ARIMA is orders of magnitude faster to train than LSTM.

5

Mathematical Foundation

5.1 AR(p) Process

Autoregressive Model of Order p
Y(t) = c + ฯ†โ‚Y(t-1) + ฯ†โ‚‚Y(t-2) + ... + ฯ†โ‚šY(t-p) + ฮต(t)

where c is a constant, ฯ†โ‚...ฯ†โ‚š are AR coefficients, ฮต(t) ~ WN(0, ฯƒยฒ)

The process is stationary if all roots of the characteristic polynomial 1 - ฯ†โ‚z - ฯ†โ‚‚zยฒ - ... - ฯ†โ‚šzแต– = 0 lie outside the unit circle.

5.2 MA(q) Process

Moving Average Model of Order q
Y(t) = ฮผ + ฮต(t) + ฮธโ‚ฮต(t-1) + ฮธโ‚‚ฮต(t-2) + ... + ฮธโ‚‘ฮต(t-q)

where ฮผ is the mean, ฮธโ‚...ฮธโ‚‘ are MA coefficients, ฮต(t) ~ WN(0, ฯƒยฒ)

An MA(q) process is always stationary (finite linear combination of white noise). It is invertible if all roots of 1 + ฮธโ‚z + ฮธโ‚‚zยฒ + ... + ฮธโ‚‘zแต = 0 lie outside the unit circle.

5.3 ARIMA(p,d,q)

ARIMA Model
ฯ†(B)(1-B)แตˆ Y(t) = c + ฮธ(B) ฮต(t)

B is the backshift operator: BยทY(t) = Y(t-1)
ฯ†(B) = 1 - ฯ†โ‚B - ... - ฯ†โ‚šBแต– (AR polynomial)
ฮธ(B) = 1 + ฮธโ‚B + ... + ฮธโ‚‘Bแต (MA polynomial)
(1-B)แตˆ is the differencing operator applied d times

5.4 SARIMA(p,d,q)(P,D,Q)โ‚˜

Seasonal ARIMA
ฯ†(B) ฮฆ(Bแต) (1-B)แตˆ (1-Bแต)แดฐ Y(t) = c + ฮธ(B) ฮ˜(Bแต) ฮต(t)

ฮฆ(Bแต) = 1 - ฮฆโ‚Bแต - ... - ฮฆโ‚šBแดพแต (seasonal AR)
ฮ˜(Bแต) = 1 + ฮ˜โ‚Bแต + ... + ฮ˜QBQแต (seasonal MA)
m = seasonal period

5.5 Exponential Smoothing โ€” State Space Form

Simple Exponential Smoothing (SES)
ลท(t+1) = ฮฑy(t) + (1-ฮฑ)ลท(t), where 0 < ฮฑ โ‰ค 1
Holt's Linear Trend
Level: โ„“(t) = ฮฑy(t) + (1-ฮฑ)(โ„“(t-1) + b(t-1))
Trend: b(t) = ฮฒ(โ„“(t) - โ„“(t-1)) + (1-ฮฒ)b(t-1)
Forecast: ลท(t+h) = โ„“(t) + hยทb(t)
Holt-Winters (Additive Seasonality)
Level: โ„“(t) = ฮฑ(y(t) - s(t-m)) + (1-ฮฑ)(โ„“(t-1) + b(t-1))
Trend: b(t) = ฮฒ(โ„“(t) - โ„“(t-1)) + (1-ฮฒ)b(t-1)
Season: s(t) = ฮณ(y(t) - โ„“(t-1) - b(t-1)) + (1-ฮณ)s(t-m)
Forecast: ลท(t+h) = โ„“(t) + hยทb(t) + s(t+h-m)

5.6 Evaluation Metrics

Mean Absolute Percentage Error (MAPE)
MAPE = (100/n) ฮฃ |y(t) - ลท(t)| / |y(t)|
Root Mean Squared Error (RMSE)
RMSE = โˆš[(1/n) ฮฃ (y(t) - ลท(t))ยฒ]
Symmetric MAPE (SMAPE)
SMAPE = (100/n) ฮฃ |y(t) - ลท(t)| / ((|y(t)| + |ลท(t)|)/2)
๐ŸŽฏ Exam Tip

MAPE has issues when actual values are near zero (division by zero). SMAPE is bounded [0%, 200%] and handles this better. RMSE penalizes large errors more heavily due to squaring. In exams, know which metric is appropriate: RMSE for point accuracy, MAPE for relative comparison, SMAPE for symmetry.

5.7 ADF Test Statistic

Augmented Dickey-Fuller Regression
ฮ”Y(t) = ฮฑ + ฮฒt + ฮณY(t-1) + ฮฃแตข ฮดแตขฮ”Y(t-i) + ฮต(t)

Test statistic: ฯ„ = ฮณฬ‚ / SE(ฮณฬ‚)
Hโ‚€: ฮณ = 0 (unit root โ†’ non-stationary)

6

Formula Derivations

6.1 Deriving the AR(1) Autocorrelation Function

For AR(1): Y(t) = ฯ†Y(t-1) + ฮต(t), with |ฯ†| < 1 for stationarity.

Step 1: Variance โ€” ฮณ(0) = Var(Y(t)) = ฯ†ยฒVar(Y(t-1)) + ฯƒยฒ = ฯ†ยฒฮณ(0) + ฯƒยฒ

Therefore: ฮณ(0) = ฯƒยฒ / (1 - ฯ†ยฒ)

Step 2: Autocovariance at lag k โ€” Multiply Y(t) = ฯ†Y(t-1) + ฮต(t) by Y(t-k) and take expectations:

ฮณ(k) = E[Y(t)ยทY(t-k)] = ฯ†ยทE[Y(t-1)ยทY(t-k)] + E[ฮต(t)ยทY(t-k)] = ฯ†ยทฮณ(k-1) + 0 = ฯ†ยทฮณ(k-1)

By recursion: ฮณ(k) = ฯ†แต ยท ฮณ(0)

Step 3: Autocorrelation: ฯ(k) = ฮณ(k)/ฮณ(0) = ฯ†แต

AR(1) Autocorrelation
ฯ(k) = ฯ†แต โ€” exponential decay for 0 < ฯ† < 1, alternating decay for -1 < ฯ† < 0

6.2 Deriving MA(1) Autocorrelation

For MA(1): Y(t) = ฮต(t) + ฮธฮต(t-1)

Step 1: ฮณ(0) = Var(ฮต(t) + ฮธฮต(t-1)) = (1 + ฮธยฒ)ฯƒยฒ

Step 2: ฮณ(1) = Cov(ฮต(t) + ฮธฮต(t-1), ฮต(t-1) + ฮธฮต(t-2)) = ฮธฯƒยฒ

Step 3: ฮณ(k) = 0 for k โ‰ฅ 2 (non-overlapping noise terms)

MA(1) Autocorrelation
ฯ(1) = ฮธ / (1 + ฮธยฒ), ฯ(k) = 0 for k โ‰ฅ 2

6.3 Deriving Simple Exponential Smoothing

The SES forecast ลท(t+1) = ฮฑy(t) + (1-ฮฑ)ลท(t) can be expanded recursively:

ลท(t+1) = ฮฑy(t) + (1-ฮฑ)[ฮฑy(t-1) + (1-ฮฑ)ลท(t-1)]

= ฮฑy(t) + ฮฑ(1-ฮฑ)y(t-1) + (1-ฮฑ)ยฒลท(t-1)

Continuing infinitely:

SES as Weighted Average
ลท(t+1) = ฮฑ ฮฃแตขโ‚Œโ‚€^โˆž (1-ฮฑ)โฑ y(t-i)

Weights decay geometrically โ€” recent data gets more weight. The weights sum to 1 since ฮฑ ฮฃ(1-ฮฑ)โฑ = ฮฑ ยท 1/(1-(1-ฮฑ)) = 1

6.4 Box-Cox Transformation

Box-Cox Transform
y(ฮป) = { (yแต˜ - 1)/ฮป if ฮป โ‰  0
{ ln(y) if ฮป = 0

ฮป = 1: No transform | ฮป = 0.5: Square root | ฮป = 0: Log | ฮป = -1: Inverse

๐ŸŽ“ Professor's Insight

The optimal ฮป can be found by maximizing the log-likelihood of the transformed data. In practice, scipy's boxcox function handles this automatically. Always remember to inverse transform your forecasts back to the original scale!

7

Worked Numerical Examples

Example 1: AR(1) Forecast by Hand

Given: AR(1) model Y(t) = 5 + 0.7ยทY(t-1) + ฮต(t), with Y(100) = 20.

Task: Forecast Y(101), Y(102), Y(103).

Solution:

Note: Forecasts converge toward the long-run mean ฮผ = c/(1-ฯ†) = 5/(1-0.7) = 16.67.

Example 2: Simple Exponential Smoothing

Given: Sales data: [100, 120, 110, 130, 125]. ฮฑ = 0.3. Initial forecast ลท(1) = 100.

Solution:

Example 3: MAPE Calculation

Given: Actual = [100, 150, 200], Forecast = [110, 140, 180].

Solution:

MAPE = (100/3)(0.10 + 0.0667 + 0.10) = (100/3)(0.2667) = 8.89%

Example 4: Differencing by Hand

Given: Y = [10, 13, 18, 25, 34, 45]

First Difference: ฮ”Y = [3, 5, 7, 9, 11] โ€” still shows a trend

Second Difference: ฮ”ยฒY = [2, 2, 2, 2] โ€” constant! Series is now stationary.

Since d=2 differences were needed, the original series has a quadratic trend (Y โ‰ˆ tยฒ).

Example 5: ACF for MA(1)

Given: MA(1) model Y(t) = ฮต(t) + 0.6ฮต(t-1), ฯƒยฒ = 4.

Solution:

๐ŸŽฏ Exam Tip

For hand calculations, always show: (1) formula substitution, (2) intermediate arithmetic, (3) final answer with units/interpretation. For model identification, draw rough ACF/PACF sketches and match them to the table in Section 4.4.

8

Visual Diagrams

Time Series Decomposition
 Original Series Y(t)            Trend T(t)                 Seasonality S(t)           Residual ฮต(t)
 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
 โ”‚    โ•ญโ•ฎ  โ•ญโ•ฎ  โ•ญโ•ฎ   โ”‚            โ”‚             โ•ฑโ•ฑ   โ”‚       โ”‚  โ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎ  โ”‚       โ”‚ โ•ท  โ•ทโ•ต โ•ทโ•ตโ•ทโ•ต โ•ท   โ”‚
 โ”‚  โ•ญโ•ฏ โ•ฐโ•ฎโ•ฏ โ•ฐโ•ฎโ•ฏ โ•ฐโ•ฎ โ”‚            โ”‚         โ•ฑโ•ฑโ•ฑ     โ”‚       โ”‚ โ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏ โ”‚       โ”‚โ•ต โ•ตโ•ท  โ•ท  โ•ต  โ•ตโ•ท  โ”‚
 โ”‚โ•ญโ•ฏ    โ•ฐ   โ•ฐ    โ•ฐโ•ฎโ”‚     =      โ”‚     โ•ฑโ•ฑโ•ฑ         โ”‚   +   โ”‚  (repeating)    โ”‚   +   โ”‚  โ•ท โ•ตโ•ท โ•ตโ•ท  โ•ท โ•ต  โ”‚
 โ”‚โ•ฏ                โ•ฐโ”‚            โ”‚ โ•ฑโ•ฑโ•ฑ             โ”‚       โ”‚  โ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎโ•ญโ•ฎ  โ”‚       โ”‚โ•ต  โ•ท  โ•ต  โ•ตโ•ท  โ•ทโ•ต โ”‚
 โ”‚                  โ”‚            โ”‚โ•ฑ                 โ”‚       โ”‚ โ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏโ•ฐโ•ฏ โ”‚       โ”‚   โ•ต  โ•ตโ•ท โ•ท โ•ตโ•ท   โ”‚
 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        Time โ†’                         Time โ†’                     Time โ†’                    Time โ†’
ACF and PACF Patterns for Model Identification
   AR(2) Model                          MA(2) Model                         ARMA(1,1) Model
   โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                          โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•                         โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
   ACF: Gradual Decay                   ACF: Cuts off at lag 2              ACF: Gradual Decay
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ    โ”‚ lag 1                โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ”‚ lag 1               โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ   โ”‚ lag 1
   โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ      โ”‚ lag 2                โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ     โ”‚ lag 2               โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ      โ”‚ lag 2
   โ”‚โ–ˆโ–ˆโ–ˆโ–ˆ         โ”‚ lag 3                โ”‚โ”€ โ”€ โ”€ โ”€ โ”€ โ”€ โ”‚ lag 3 (โ‰ˆ0)          โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ        โ”‚ lag 3
   โ”‚โ–ˆโ–ˆ           โ”‚ lag 4                โ”‚โ”€ โ”€ โ”€ โ”€ โ”€ โ”€ โ”‚ lag 4 (โ‰ˆ0)          โ”‚โ–ˆโ–ˆโ–ˆ          โ”‚ lag 4
   โ”‚โ–ˆ            โ”‚ lag 5                โ”‚โ”€ โ”€ โ”€ โ”€ โ”€ โ”€ โ”‚ lag 5 (โ‰ˆ0)          โ”‚โ–ˆโ–ˆ           โ”‚ lag 5
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

   PACF: Cuts off at lag 2             PACF: Gradual Decay                 PACF: Gradual Decay
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ”‚ lag 1                โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ”‚ lag 1               โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ   โ”‚ lag 1
   โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ      โ”‚ lag 2                โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ      โ”‚ lag 2               โ”‚โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ        โ”‚ lag 2
   โ”‚โ”€ โ”€ โ”€ โ”€ โ”€ โ”€ โ”‚ lag 3 (โ‰ˆ0)          โ”‚โ–ˆโ–ˆโ–ˆโ–ˆ         โ”‚ lag 3               โ”‚โ–ˆโ–ˆโ–ˆ          โ”‚ lag 3
   โ”‚โ”€ โ”€ โ”€ โ”€ โ”€ โ”€ โ”‚ lag 4 (โ‰ˆ0)          โ”‚โ–ˆโ–ˆ           โ”‚ lag 4               โ”‚โ–ˆโ–ˆ           โ”‚ lag 4
   โ”‚โ”€ โ”€ โ”€ โ”€ โ”€ โ”€ โ”‚ lag 5 (โ‰ˆ0)          โ”‚โ–ˆ            โ”‚ lag 5               โ”‚โ–ˆ            โ”‚ lag 5
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
LSTM Cell Architecture
                              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                              โ”‚              LSTM Cell                      โ”‚
                              โ”‚                                             โ”‚
    c(t-1) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”คโ”€โ”€โ”€[ร—]โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€[+]โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ c(t)
                              โ”‚    โ”‚              โ”‚                          โ”‚
                              โ”‚    โ”‚              โ”‚                          โ”‚
                              โ”‚  โ”Œโ”€โ”ดโ”€โ”         โ”Œโ”€โ”ดโ”€โ”                       โ”‚
                              โ”‚  โ”‚ fโ‚œ โ”‚         โ”‚ iโ‚œ โ”‚ร—[cฬƒโ‚œ]                 โ”‚
                              โ”‚  โ”‚for-โ”‚         โ”‚inp-โ”‚                       โ”‚
                              โ”‚  โ”‚get โ”‚         โ”‚ut  โ”‚                       โ”‚
                              โ”‚  โ”‚gateโ”‚         โ”‚gateโ”‚                       โ”‚
                              โ”‚  โ””โ”€โ”ฌโ”€โ”˜         โ””โ”€โ”ฌโ”€โ”˜                       โ”‚
    h(t-1) โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค    โ”‚              โ”‚                          โ”‚
                 โ”‚            โ”‚    โ”‚              โ”‚         โ”Œโ”€โ”€โ”€โ”            โ”‚
                 โ”‚            โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค    tanhโ”€โ”ค   โ”‚โ”€โ”€[ร—]โ”€โ”€โ”€โ”€โ”€ h(t)
                 โ”‚            โ”‚    โ”‚              โ”‚         โ””โ”€โ”€โ”€โ”˜   โ”‚        โ”‚
                 โ”‚            โ”‚  โ”Œโ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”             โ”Œโ”ดโ”€โ”      โ”‚
                 โ”‚            โ”‚  โ”‚   ฯƒ    ฯƒ   tanh   โ”‚            โ”‚oโ‚œโ”‚      โ”‚
                 โ”‚            โ”‚  โ”‚  [fโ‚œ] [iโ‚œ] [cฬƒโ‚œ]  โ”‚            โ”‚outโ”‚      โ”‚
                 โ”‚            โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚putโ”‚      โ”‚
                 โ”‚            โ”‚          โ”‚                        โ”‚gteโ”‚      โ”‚
                 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                        โ””โ”€โ”€โ”€โ”˜      โ”‚
                              โ”‚                                             โ”‚
    x(t) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                             โ”‚
                              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

    fโ‚œ = ฯƒ(Wfยท[h(t-1), x(t)] + bf)     โ† Forget gate
    iโ‚œ = ฯƒ(Wiยท[h(t-1), x(t)] + bi)     โ† Input gate
    cฬƒโ‚œ = tanh(Wcยท[h(t-1), x(t)] + bc)  โ† Candidate cell state
    c(t) = fโ‚œ ร— c(t-1) + iโ‚œ ร— cฬƒโ‚œ        โ† New cell state
    oโ‚œ = ฯƒ(Woยท[h(t-1), x(t)] + bo)     โ† Output gate
    h(t) = oโ‚œ ร— tanh(c(t))              โ† Hidden state output
Sliding Window for Time Series โ†’ Supervised Learning
    Original Series: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    Window Size = 3, Horizon = 1

    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚   Features (X)       โ”‚ Target  โ”‚
    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
    โ”‚  [10,  20,  30]      โ”‚   40    โ”‚
    โ”‚  [20,  30,  40]      โ”‚   50    โ”‚
    โ”‚  [30,  40,  50]      โ”‚   60    โ”‚
    โ”‚  [40,  50,  60]      โ”‚   70    โ”‚
    โ”‚  [50,  60,  70]      โ”‚   80    โ”‚
    โ”‚  [60,  70,  80]      โ”‚   90    โ”‚
    โ”‚  [70,  80,  90]      โ”‚  100    โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

    โ†’ Converts time series into supervised learning problem
    โ†’ For LSTM: X reshaped to (samples, timesteps, features) = (7, 3, 1)
9

Flowcharts

Box-Jenkins Methodology Flowchart
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚                    START: Raw Time Series Data                       โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                   โ”‚
                                   โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Step 1: VISUALIZATION                                              โ”‚
    โ”‚  โ€ข Plot the series  โ€ข Look for trend, seasonality, outliers         โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                   โ”‚
                                   โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Step 2: STATIONARITY CHECK                                         โ”‚
    โ”‚  โ€ข ADF Test  โ€ข KPSS Test  โ€ข Visual inspection of mean/variance      โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                   โ”‚
                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                          โ”‚  Stationary?    โ”‚
                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         NO โ•ฑ      โ”‚       โ•ฒ YES
                           โ•ฑ       โ”‚        โ•ฒ
                          โ–ผ        โ”‚         โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚ Apply Transformations   โ”‚    โ”‚    โ”‚  Step 3: MODEL IDENTIFICATION  โ”‚
    โ”‚ โ€ข Differencing (d)      โ”‚    โ”‚    โ”‚  โ€ข Plot ACF โ†’ determine q      โ”‚
    โ”‚ โ€ข Log Transform         โ”‚โ”€โ”€โ”€โ”€โ”˜    โ”‚  โ€ข Plot PACF โ†’ determine p     โ”‚
    โ”‚ โ€ข Seasonal diff (D)     โ”‚         โ”‚  โ€ข d = number of diffs needed  โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                       โ”‚
                                                       โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Step 4: PARAMETER ESTIMATION                                       โ”‚
    โ”‚  โ€ข Fit ARIMA(p,d,q) or SARIMA(p,d,q)(P,D,Q,m)                     โ”‚
    โ”‚  โ€ข Use MLE (Maximum Likelihood Estimation)                         โ”‚
    โ”‚  โ€ข Compare AIC/BIC for candidate models                            โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                   โ”‚
                                   โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Step 5: DIAGNOSTIC CHECKING                                        โ”‚
    โ”‚  โ€ข Ljung-Box test on residuals (should be white noise)             โ”‚
    โ”‚  โ€ข Residual ACF plot (no significant lags)                         โ”‚
    โ”‚  โ€ข Q-Q plot (normality check)                                      โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                   โ”‚
                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                          โ”‚ Residuals OK?   โ”‚
                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         NO โ•ฑ      โ”‚       โ•ฒ YES
                           โ•ฑ       โ”‚        โ•ฒ
                          โ–ผ        โ”‚         โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚ Revise model orders     โ”‚    โ”‚    โ”‚  Step 6: FORECASTING           โ”‚
    โ”‚ Try different (p,d,q)   โ”‚โ”€โ”€โ”€โ”€โ”˜    โ”‚  โ€ข Generate point forecasts    โ”‚
    โ”‚ Consider SARIMA         โ”‚         โ”‚  โ€ข Compute confidence intervalsโ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ”‚  โ€ข Monitor performance         โ”‚
                                        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
Model Selection Decision Tree
                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                          โ”‚  Time Series Data    โ”‚
                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                     โ”‚
                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                          โ”‚  Univariate or       โ”‚
                          โ”‚  Multivariate?       โ”‚
                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         Uni โ•ฑ               โ•ฒ Multi
                            โ•ฑ                 โ•ฒ
                           โ–ผ                   โ–ผ
               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
               โ”‚ Has            โ”‚       โ”‚   VAR Model  โ”‚
               โ”‚ Seasonality?  โ”‚       โ”‚   or VECM    โ”‚
               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
              YES โ•ฑ         โ•ฒ NO
                 โ•ฑ           โ•ฒ
                โ–ผ             โ–ผ
     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚ Data Size?     โ”‚  โ”‚ Data Size?     โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
      <500โ•ฑ     โ•ฒ>500     <500โ•ฑ     โ•ฒ>500
          โ•ฑ       โ•ฒ          โ•ฑ       โ•ฒ
         โ–ผ         โ–ผ        โ–ผ         โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚ SARIMA  โ”‚ โ”‚ LSTM / โ”‚ โ”‚ARIMA โ”‚ โ”‚ LSTM /   โ”‚
    โ”‚ Holt-   โ”‚ โ”‚Prophet โ”‚ โ”‚ SES  โ”‚ โ”‚ Prophet  โ”‚
    โ”‚ Winters โ”‚ โ”‚ SARIMA โ”‚ โ”‚ Holt โ”‚ โ”‚ ARIMA    โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
Time Series Anomaly Detection Pipeline
    Raw Time Series
         โ”‚
         โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Decompose  โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚  Model the  โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚  Compute    โ”‚
    โ”‚  (STL /     โ”‚     โ”‚  Expected   โ”‚     โ”‚  Residuals  โ”‚
    โ”‚  seasonal_  โ”‚     โ”‚  (ARIMA /   โ”‚     โ”‚  r(t) =     โ”‚
    โ”‚  decompose) โ”‚     โ”‚  Prophet)   โ”‚     โ”‚  y(t) - ลท(t)โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                   โ”‚
                                                   โ–ผ
                                            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                            โ”‚  Flag where โ”‚
                                            โ”‚  |r(t)| >   โ”‚
                                            โ”‚  k ร— ฯƒ      โ”‚
                                            โ”‚  (k=2 or 3) โ”‚
                                            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                   โ”‚
                                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                          โ”‚ Anomaly?        โ”‚
                                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                        YES โ•ฑ           โ•ฒ NO
                                           โ•ฑ             โ•ฒ
                                          โ–ผ               โ–ผ
                                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                  โ”‚ Alert /      โ”‚  โ”‚ Normal   โ”‚
                                  โ”‚ Investigate  โ”‚  โ”‚ Continue โ”‚
                                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
10

Python Implementation (From Scratch)

10.1 Simple Exponential Smoothing from Scratch

PYTHON
import numpy as np

class SimpleExponentialSmoothing:
    """Simple Exponential Smoothing from scratch."""
    
    def __init__(self, alpha=0.3):
        self.alpha = alpha
        self.fitted_values = []
    
    def fit(self, series):
        """Fit the SES model to a time series."""
        self.series = np.array(series, dtype=float)
        n = len(self.series)
        self.fitted_values = np.zeros(n)
        
        # Initialize: first forecast = first observation
        self.fitted_values[0] = self.series[0]
        
        for t in range(1, n):
            self.fitted_values[t] = (
                self.alpha * self.series[t - 1] +
                (1 - self.alpha) * self.fitted_values[t - 1]
            )
        
        self.level = self.fitted_values[-1]
        return self
    
    def forecast(self, steps=1):
        """Forecast future values (SES gives flat forecast)."""
        last_smoothed = (
            self.alpha * self.series[-1] +
            (1 - self.alpha) * self.level
        )
        return np.full(steps, last_smoothed)
    
    def mape(self):
        """Calculate Mean Absolute Percentage Error."""
        actual = self.series[1:]
        forecast = self.fitted_values[1:]
        return np.mean(np.abs((actual - forecast) / actual)) * 100


# Example usage
data = [112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118]
model = SimpleExponentialSmoothing(alpha=0.3)
model.fit(data)
print("Fitted:", np.round(model.fitted_values, 2))
print("Forecast (next 3):", np.round(model.forecast(3), 2))
print(f"MAPE: {model.mape():.2f}%")

10.2 AR(1) Model from Scratch

PYTHON
import numpy as np

class AR1Model:
    """AR(1) model: Y(t) = c + phi * Y(t-1) + epsilon."""
    
    def __init__(self):
        self.phi = None
        self.c = None
        self.sigma2 = None
    
    def fit(self, series):
        """Estimate AR(1) parameters using OLS."""
        y = np.array(series, dtype=float)
        n = len(y)
        
        # Set up regression: y(t) = c + phi * y(t-1)
        Y = y[1:]      # dependent variable
        X = y[:-1]      # lagged variable
        
        # Add intercept
        X_design = np.column_stack([np.ones(n - 1), X])
        
        # OLS: beta = (X'X)^{-1} X'Y
        beta = np.linalg.solve(X_design.T @ X_design, X_design.T @ Y)
        self.c = beta[0]
        self.phi = beta[1]
        
        # Residuals
        residuals = Y - X_design @ beta
        self.sigma2 = np.var(residuals, ddof=2)
        self.last_value = y[-1]
        
        return self
    
    def forecast(self, steps=5):
        """Generate multi-step ahead forecasts."""
        predictions = []
        current = self.last_value
        for _ in range(steps):
            next_val = self.c + self.phi * current
            predictions.append(next_val)
            current = next_val
        return np.array(predictions)
    
    def long_run_mean(self):
        """E[Y] = c / (1 - phi) for stationary process."""
        if abs(self.phi) >= 1:
            return float('inf')
        return self.c / (1 - self.phi)
    
    def is_stationary(self):
        """Check stationarity condition: |phi| < 1."""
        return abs(self.phi) < 1


# Example: Fit AR(1) to synthetic data
np.random.seed(42)
n = 200
y = np.zeros(n)
y[0] = 10
for t in range(1, n):
    y[t] = 3 + 0.7 * y[t-1] + np.random.normal(0, 1)

model = AR1Model()
model.fit(y)
print(f"Estimated: c={model.c:.4f}, phi={model.phi:.4f}")
print(f"True:      c=3.0000, phi=0.7000")
print(f"Stationary: {model.is_stationary()}")
print(f"Long-run mean: {model.long_run_mean():.4f} (true: {3/(1-0.7):.4f})")
print(f"Forecast: {np.round(model.forecast(5), 2)}")

10.3 Augmented Dickey-Fuller Test from Scratch

PYTHON
import numpy as np

def adf_test_manual(series, max_lags=1):
    """
    Manual ADF test implementation.
    Tests H0: unit root (non-stationary) vs H1: stationary.
    """
    y = np.array(series, dtype=float)
    n = len(y)
    
    # Compute first differences
    dy = np.diff(y)
    
    # Lagged level
    y_lag = y[:-1]
    
    # Trim to account for lags
    if max_lags > 0:
        # Include lagged differences
        dy_lags = np.column_stack([
            dy[max_lags - i - 1: n - 1 - i - 1]
            for i in range(max_lags)
        ])
        dy_trimmed = dy[max_lags:]
        y_lag_trimmed = y_lag[max_lags:]
        
        X = np.column_stack([
            np.ones(len(dy_trimmed)),   # intercept
            y_lag_trimmed,               # gamma * y(t-1)
            dy_lags                      # lagged differences
        ])
    else:
        dy_trimmed = dy
        y_lag_trimmed = y_lag
        X = np.column_stack([np.ones(len(dy_trimmed)), y_lag_trimmed])
    
    # OLS estimation
    beta = np.linalg.solve(X.T @ X, X.T @ dy_trimmed)
    residuals = dy_trimmed - X @ beta
    
    # Standard error of gamma
    sigma2 = np.sum(residuals**2) / (len(dy_trimmed) - len(beta))
    cov_matrix = sigma2 * np.linalg.inv(X.T @ X)
    se_gamma = np.sqrt(cov_matrix[1, 1])
    
    # Test statistic
    gamma = beta[1]
    t_stat = gamma / se_gamma
    
    # Critical values (approximate, for n > 100 with intercept)
    critical_values = {
        '1%':  -3.43,
        '5%':  -2.86,
        '10%': -2.57
    }
    
    print(f"ADF Test Statistic: {t_stat:.4f}")
    print(f"Estimated gamma:    {gamma:.6f}")
    for level, cv in critical_values.items():
        reject = "REJECT H0 (Stationary)" if t_stat < cv else "Fail to reject H0"
        print(f"  {level} critical value: {cv:.2f} โ†’ {reject}")
    
    return t_stat, gamma


# Test with a stationary series
np.random.seed(42)
stationary = np.random.normal(0, 1, 200).cumsum()  # Random walk (non-stationary)
print("=== Random Walk (Non-Stationary) ===")
adf_test_manual(stationary)

print("\n=== White Noise (Stationary) ===")
white_noise = np.random.normal(0, 1, 200)
adf_test_manual(white_noise)

10.4 ACF/PACF Computation

PYTHON
import numpy as np

def compute_acf(series, max_lag=20):
    """Compute the Autocorrelation Function."""
    y = np.array(series, dtype=float)
    n = len(y)
    mean = np.mean(y)
    var = np.sum((y - mean) ** 2) / n
    
    acf_values = []
    for k in range(max_lag + 1):
        if k == 0:
            acf_values.append(1.0)
        else:
            cov = np.sum((y[k:] - mean) * (y[:-k] - mean)) / n
            acf_values.append(cov / var)
    
    return np.array(acf_values)


def compute_pacf(series, max_lag=20):
    """Compute PACF using the Durbin-Levinson algorithm."""
    acf = compute_acf(series, max_lag)
    n_lags = max_lag
    pacf_values = np.zeros(n_lags + 1)
    pacf_values[0] = 1.0
    pacf_values[1] = acf[1]
    
    phi = np.zeros((n_lags + 1, n_lags + 1))
    phi[1, 1] = acf[1]
    
    for k in range(2, n_lags + 1):
        # Numerator
        num = acf[k] - sum(phi[k-1, j] * acf[k-j] for j in range(1, k))
        # Denominator
        den = 1.0 - sum(phi[k-1, j] * acf[j] for j in range(1, k))
        
        phi[k, k] = num / den
        
        for j in range(1, k):
            phi[k, j] = phi[k-1, j] - phi[k, k] * phi[k-1, k-j]
        
        pacf_values[k] = phi[k, k]
    
    return pacf_values


# Example
np.random.seed(42)
ar1_data = np.zeros(500)
for t in range(1, 500):
    ar1_data[t] = 0.8 * ar1_data[t-1] + np.random.normal(0, 1)

acf = compute_acf(ar1_data, 10)
pacf = compute_pacf(ar1_data, 10)

print("Lag  |  ACF    |  PACF")
print("-" * 30)
for k in range(11):
    print(f"  {k:2d}  | {acf[k]:6.3f}  | {pacf[k]:6.3f}")
print("\nโ†’ ACF decays exponentially, PACF cuts off after lag 1 โ†’ AR(1) โœ“")
๐Ÿ’ป Code Challenge

Extend the AR(1) model to AR(p). Implement an AR class that accepts a parameter p, fits using OLS with p lagged columns, and forecasts iteratively. Test with p=3 on synthetic data generated from a known AR(3) process.

11

TensorFlow Implementation

11.1 LSTM Time Series Forecaster

TENSORFLOW / KERAS
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from tensorflow.keras.callbacks import EarlyStopping
from sklearn.preprocessing import MinMaxScaler

# =========================================================
# 1. Generate / Load Data
# =========================================================
# Synthetic: trend + seasonality + noise
np.random.seed(42)
t = np.arange(0, 500)
series = 0.05 * t + 10 * np.sin(2 * np.pi * t / 50) + np.random.normal(0, 2, 500)
series = series.reshape(-1, 1)

# =========================================================
# 2. Scale Data
# =========================================================
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(series)

# =========================================================
# 3. Create Sliding Window Dataset
# =========================================================
def create_sequences(data, window_size=30):
    X, y = [], []
    for i in range(window_size, len(data)):
        X.append(data[i - window_size:i, 0])
        y.append(data[i, 0])
    return np.array(X), np.array(y)

WINDOW = 30
X, y = create_sequences(scaled, WINDOW)

# Train-test split (80/20)
split = int(0.8 * len(X))
X_train, X_test = X[:split], X[split:]
y_train, y_test = y[:split], y[split:]

# Reshape for LSTM: (samples, timesteps, features)
X_train = X_train.reshape(-1, WINDOW, 1)
X_test = X_test.reshape(-1, WINDOW, 1)

# =========================================================
# 4. Build LSTM Model
# =========================================================
model = Sequential([
    LSTM(64, return_sequences=True, input_shape=(WINDOW, 1)),
    Dropout(0.2),
    LSTM(32, return_sequences=False),
    Dropout(0.2),
    Dense(16, activation='relu'),
    Dense(1)
])

model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
    loss='mse',
    metrics=['mae']
)

model.summary()

# =========================================================
# 5. Train
# =========================================================
early_stop = EarlyStopping(
    monitor='val_loss', patience=10, restore_best_weights=True
)

history = model.fit(
    X_train, y_train,
    epochs=100,
    batch_size=32,
    validation_split=0.2,
    callbacks=[early_stop],
    verbose=1
)

# =========================================================
# 6. Evaluate
# =========================================================
y_pred_scaled = model.predict(X_test)
y_pred = scaler.inverse_transform(y_pred_scaled)
y_actual = scaler.inverse_transform(y_test.reshape(-1, 1))

rmse = np.sqrt(np.mean((y_actual - y_pred) ** 2))
mape = np.mean(np.abs((y_actual - y_pred) / y_actual)) * 100
print(f"\nRMSE: {rmse:.4f}")
print(f"MAPE: {mape:.2f}%")

# =========================================================
# 7. Multi-Step Forecast
# =========================================================
def forecast_multistep(model, last_window, steps, scaler):
    """Iteratively forecast multiple steps ahead."""
    predictions = []
    current = last_window.copy()
    
    for _ in range(steps):
        pred = model.predict(current.reshape(1, -1, 1), verbose=0)
        predictions.append(pred[0, 0])
        current = np.append(current[1:], pred[0, 0])
    
    predictions = np.array(predictions).reshape(-1, 1)
    return scaler.inverse_transform(predictions)

future = forecast_multistep(model, scaled[-WINDOW:, 0], 10, scaler)
print(f"\nNext 10 forecasts: {future.flatten().round(2)}")

11.2 Bidirectional LSTM with Attention

TENSORFLOW / KERAS
from tensorflow.keras.layers import (
    Bidirectional, LSTM, Dense, Dropout,
    Attention, Input, Concatenate, Flatten
)
from tensorflow.keras.models import Model

def build_attention_lstm(window_size, n_features=1):
    """LSTM with simple attention mechanism for time series."""
    
    inp = Input(shape=(window_size, n_features))
    
    # Bidirectional LSTM
    lstm_out = Bidirectional(
        LSTM(64, return_sequences=True)
    )(inp)
    lstm_out = Dropout(0.2)(lstm_out)
    
    # Second LSTM layer
    lstm_out2 = Bidirectional(
        LSTM(32, return_sequences=True)
    )(lstm_out)
    
    # Simple attention: learn which timesteps matter most
    attention = Dense(1, activation='tanh')(lstm_out2)
    attention = Flatten()(attention)
    attention = Dense(window_size, activation='softmax')(attention)
    
    # Apply attention weights
    # Reshape attention for element-wise multiplication
    from tensorflow.keras.layers import RepeatVector, Permute, Multiply
    attention = RepeatVector(64)(attention)
    attention = Permute([2, 1])(attention)
    
    context = Multiply()([lstm_out2, attention])
    context = tf.keras.layers.GlobalAveragePooling1D()(context)
    
    # Output
    out = Dense(32, activation='relu')(context)
    out = Dropout(0.2)(out)
    out = Dense(1)(out)
    
    model = Model(inputs=inp, outputs=out)
    model.compile(optimizer='adam', loss='mse', metrics=['mae'])
    
    return model

# Build and display
attn_model = build_attention_lstm(window_size=30)
attn_model.summary()
๐ŸŽ“ Professor's Insight

LSTMs are powerful but come with caveats for time series: (1) They need thousands of data points โ€” don't use them on monthly data with only 60 observations. (2) They're a black box โ€” if interpretability matters (finance regulation), prefer ARIMA or Prophet. (3) Modern alternatives like Temporal Fusion Transformers and N-BEATS often outperform LSTMs. Always benchmark LSTM against a simple baseline like ARIMA first.

12

Scikit-Learn Pipeline

12.1 ARIMA with statsmodels + Prophet Pipeline

PYTHON
import numpy as np
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.stattools import adfuller, kpss
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import warnings
warnings.filterwarnings('ignore')

# =========================================================
# 1. Load and Prepare Data
# =========================================================
# Using airline passengers dataset as example
from statsmodels.datasets import co2
data = co2.load().data
data = data.resample('M').mean().ffill()
data.columns = ['co2']
print(f"Data shape: {data.shape}")
print(data.head())

# =========================================================
# 2. Stationarity Tests
# =========================================================
def stationarity_report(series, name="Series"):
    """Run ADF and KPSS tests and print results."""
    print(f"\n=== Stationarity Report: {name} ===")
    
    # ADF Test
    adf_result = adfuller(series.dropna(), autolag='AIC')
    print(f"ADF Statistic: {adf_result[0]:.4f}")
    print(f"ADF p-value:   {adf_result[1]:.6f}")
    print(f"ADF โ†’ {'Stationary' if adf_result[1] < 0.05 else 'Non-Stationary'}")
    
    # KPSS Test
    kpss_result = kpss(series.dropna(), regression='ct')
    print(f"KPSS Statistic: {kpss_result[0]:.4f}")
    print(f"KPSS p-value:   {kpss_result[1]:.4f}")
    print(f"KPSS โ†’ {'Non-Stationary' if kpss_result[1] < 0.05 else 'Stationary'}")

stationarity_report(data['co2'], "CO2 Levels")
stationarity_report(data['co2'].diff().dropna(), "CO2 First Difference")

# =========================================================
# 3. Decomposition
# =========================================================
decomp = seasonal_decompose(data['co2'], model='additive', period=12)
# decomp.plot()  # Uncomment in Jupyter

# =========================================================
# 4. Auto ARIMA using pmdarima
# =========================================================
# pip install pmdarima
import pmdarima as pm

auto_model = pm.auto_arima(
    data['co2'],
    seasonal=True,
    m=12,
    stepwise=True,
    suppress_warnings=True,
    trace=True,
    error_action='ignore',
    information_criterion='aic'
)
print(f"\nBest model: {auto_model.summary()}")

# =========================================================
# 5. Manual ARIMA Fit
# =========================================================
train = data['co2'][:'2000']
test = data['co2']['2001':]

model = ARIMA(train, order=(1, 1, 1), seasonal_order=(1, 1, 1, 12))
fitted = model.fit()
print(fitted.summary())

# Forecast
forecast = fitted.forecast(steps=len(test))
rmse = np.sqrt(np.mean((test.values - forecast.values) ** 2))
print(f"\nSARIMA RMSE: {rmse:.4f}")

# =========================================================
# 6. Exponential Smoothing
# =========================================================
from statsmodels.tsa.holtwinters import ExponentialSmoothing

hw_model = ExponentialSmoothing(
    train,
    trend='add',
    seasonal='add',
    seasonal_periods=12
).fit()

hw_forecast = hw_model.forecast(steps=len(test))
hw_rmse = np.sqrt(np.mean((test.values - hw_forecast.values) ** 2))
print(f"Holt-Winters RMSE: {hw_rmse:.4f}")

12.2 Prophet Pipeline

PYTHON
# pip install prophet
from prophet import Prophet
import pandas as pd
import numpy as np

# =========================================================
# Prophet requires columns 'ds' (date) and 'y' (value)
# =========================================================
# Prepare data
df = data.reset_index()
df.columns = ['ds', 'y']

# Train-test split
train_df = df[df['ds'] < '2001-01-01']
test_df = df[df['ds'] >= '2001-01-01']

# =========================================================
# Build Prophet Model
# =========================================================
prophet_model = Prophet(
    yearly_seasonality=True,
    weekly_seasonality=False,
    daily_seasonality=False,
    changepoint_prior_scale=0.05,    # flexibility of trend
    seasonality_prior_scale=10.0,    # flexibility of seasonality
    interval_width=0.95              # 95% prediction interval
)

# Add Indian holidays (example)
# prophet_model.add_country_holidays(country_name='IN')

prophet_model.fit(train_df)

# =========================================================
# Forecast
# =========================================================
future = prophet_model.make_future_dataframe(periods=len(test_df), freq='M')
forecast = prophet_model.predict(future)

# Evaluate
pred = forecast[forecast['ds'] >= '2001-01-01']['yhat'].values
actual = test_df['y'].values
rmse = np.sqrt(np.mean((actual - pred[:len(actual)]) ** 2))
mape = np.mean(np.abs((actual - pred[:len(actual)]) / actual)) * 100
print(f"Prophet RMSE: {rmse:.4f}")
print(f"Prophet MAPE: {mape:.2f}%")

# =========================================================
# Components
# =========================================================
# prophet_model.plot_components(forecast)  # Uncomment in Jupyter

# =========================================================
# Anomaly Detection with Prophet
# =========================================================
anomalies = forecast[
    (df['y'].values < forecast['yhat_lower'].values) |
    (df['y'].values > forecast['yhat_upper'].values)
]
print(f"\nDetected {len(anomalies)} anomalies")

12.3 VAR Model for Multivariate Forecasting

PYTHON
from statsmodels.tsa.api import VAR
import pandas as pd
import numpy as np

# Simulated multivariate data: Nifty50 + USD/INR
np.random.seed(42)
n = 300
nifty = np.cumsum(np.random.normal(0.5, 50, n)) + 15000
usd_inr = np.cumsum(np.random.normal(0.01, 0.5, n)) + 75
gold = np.cumsum(np.random.normal(0.1, 20, n)) + 50000

df = pd.DataFrame({
    'Nifty50': nifty,
    'USD_INR': usd_inr,
    'Gold': gold
})

# Differencing for stationarity
df_diff = df.diff().dropna()

# Fit VAR
var_model = VAR(df_diff)
# Select optimal lag order
lag_order = var_model.select_order(maxlags=15)
print("Optimal lag orders:")
print(lag_order.summary())

# Fit with optimal lag
fitted_var = var_model.fit(maxlags=5, ic='aic')
print(fitted_var.summary())

# Forecast
forecast_diff = fitted_var.forecast(df_diff.values[-5:], steps=10)
forecast_df = pd.DataFrame(forecast_diff, columns=df.columns)

# Invert differencing
last_values = df.iloc[-1]
forecast_levels = forecast_df.cumsum() + last_values.values
print("\nVAR Forecast (levels):")
print(forecast_levels.round(2))

# Granger Causality Test
from statsmodels.tsa.stattools import grangercausalitytests
print("\n=== Granger Causality: USD/INR โ†’ Nifty50 ===")
gc_result = grangercausalitytests(
    df_diff[['Nifty50', 'USD_INR']].dropna(),
    maxlag=5, verbose=True
)
๐Ÿš€ Career Path

Quantitative Analyst (Quant): At firms like Citadel, DE Shaw, or Indian hedge funds like Edelweiss, quants build time series models for algorithmic trading. Skills needed: ARIMA/GARCH for volatility, LSTM for price prediction, and VAR for cross-asset analysis. Compensation in India: โ‚น25-80 LPA for experienced roles.

13

Indian Case Studies

Case Study 1: Nifty50 Stock Index Forecasting

๐Ÿ‡ฎ๐Ÿ‡ณ India Spotlight

Context: The Nifty50 index represents the top 50 companies on the National Stock Exchange (NSE). Retail investors in India grew from 40 million in 2020 to over 130 million demat accounts by 2024.

Challenge: Build a daily Nifty50 closing price forecaster for short-term (5-day) predictions.

Approach:

Results:

Lesson: Stock price prediction is extremely difficult (Efficient Market Hypothesis). Models are more useful for volatility estimation and risk management than price direction.

Case Study 2: IMD Monsoon Rainfall Prediction

Context: The Indian monsoon delivers ~70% of annual rainfall between June-September, critical for agriculture (which employs ~42% of the workforce). IMD issues Long Range Forecasts (LRF) in April.

Approach:

Results: IMD's statistical model correctly categorizes monsoon in ~70% of years. The 2023 El Niรฑo year was correctly predicted as "below normal" with a 3-month lead time.

Case Study 3: COVID-19 India Curve Forecasting

Context: During the 2020-2021 COVID-19 waves, ICMR and IIT research teams built forecasting models to predict daily cases and guide lockdown decisions.

Approach:

Key findings: Prophet with manual changepoints at lockdown start/end dates outperformed pure ARIMA. LSTM required careful windowing โ€” the second wave (Delta variant, April 2021) had fundamentally different dynamics from the first wave, causing models trained on Wave 1 to severely underestimate Wave 2 peaks.

Lesson: Time series models assume the future resembles the past. Black swan events (new variants, policy changes) break this assumption. Ensemble methods with scenario analysis work best for crisis forecasting.

๐ŸŽ“ Professor's Insight

Indian time series often have unique challenges: (1) Missing data during holidays/hartals, (2) Structural breaks from demonetization (Nov 2016) and GST rollout (Jul 2017), (3) Festival-driven seasonality that follows the lunar calendar (Diwali date varies by 15+ days). Always account for these in your models.

14

Global Case Studies

Case Study 1: Weather Forecasting (NOAA / ECMWF)

Context: Modern weather forecasting combines physics-based Numerical Weather Prediction (NWP) with statistical/ML post-processing. The ECMWF (European Centre for Medium-Range Weather Forecasts) produces the world's best 10-day forecasts.

ML Role:

Metrics: RMSE for temperature (typically 1-2ยฐC for 24-hour forecasts), skill scores relative to climatological baselines.

Case Study 2: Energy Demand Forecasting (Electricity Grids)

Context: Power grid operators (like ISO New England, or POSOCO in India) must forecast electricity demand hourly to dispatch generation units efficiently. Over-forecasting wastes fuel; under-forecasting causes blackouts.

Approach:

Results: Modern ensembles achieve MAPE of 1-3% for day-ahead forecasting. The challenge grows with renewable energy integration โ€” solar and wind output depends on weather, adding another layer of uncertainty.

Case Study 3: Retail Sales Forecasting (Walmart / Amazon)

Context: Walmart manages inventory for 4,700+ stores across the US. Accurate demand forecasting reduces waste, prevents stockouts, and saves billions in supply chain costs.

Approach:

Results: Top solutions achieved WRMSSE (Weighted Root Mean Scaled Squared Error) of ~0.52. Key insight: simple lag features + gradient boosting beat deep learning in this competition.

๐Ÿญ Industry Alert

Amazon's demand forecasting system (used in 2023) runs a combination of DeepAR (autoregressive RNN) and classical methods on millions of SKUs. They published the DeepAR paper showing that training a single global model across all related time series outperforms fitting individual ARIMA models to each series โ€” a paradigm shift called "cross-learning."

15

Startup Applications

15.1 FinTech โ€” Cash Flow Forecasting

Startups: Razorpay, CashFlo, Recko (India)

Fintech startups help SMEs forecast cash flows using transaction history. Prophet models decompose revenue into trend + weekly + monthly seasonality. Alert systems flag anomalies (sudden drops in UPI collections) using residual-based detection.

15.2 AgriTech โ€” Crop Yield Prediction

Startups: CropIn, Fasal, DeHaat (India)

These startups use satellite imagery time series (NDVI index over crop growth cycles) + weather time series to forecast crop yields. Models include: SARIMA for rainfall patterns, LSTM for multi-source sensor data fusion, and Prophet for price forecasting to advise farmers on optimal selling times.

15.3 HealthTech โ€” Patient Volume Forecasting

Startups: Practo, 1mg

Hospital bed occupancy, emergency room visits, and appointment demand follow time series patterns with weekly seasonality (higher on Mondays), annual seasonality (flu season), and pandemic-driven anomalies. Accurate forecasting enables efficient staff scheduling.

15.4 E-Commerce โ€” Demand Sensing

Startups: Meesho, Udaan, Flipkart

Indian e-commerce faces extreme demand spikes during sales events (Big Billion Days, Great Indian Festival). Time series models augmented with event indicators and real-time search trend data enable "demand sensing" โ€” adjusting forecasts hours/days ahead of traditional weekly cycles.

๐Ÿš€ Career Path

Data Scientist โ€” Forecasting: Specialized roles at companies like Amazon, Flipkart, Uber, and OLA focus exclusively on time series forecasting. Required skills: statsmodels, Prophet, deep learning, and strong statistical foundations. These roles are among the highest-paying DS positions due to direct revenue impact.

16

Government Applications

16.1 RBI โ€” Inflation Forecasting

The Reserve Bank of India uses time series models to forecast CPI inflation for its monetary policy decisions. The RBI's Quarterly Projection Model combines ARIMA with structural economic models. Accurate inflation forecasts determine repo rate changes that affect every Indian borrower.

16.2 NITI Aayog โ€” GDP Forecasting

India's GDP forecasting uses VAR models with high-frequency indicators (IIP, PMI, GST collections, electricity consumption) as predictors. The "nowcasting" approach uses real-time data to estimate current-quarter GDP before official statistics are released.

16.3 Ministry of Health โ€” Epidemic Surveillance

IDSP (Integrated Disease Surveillance Programme) monitors weekly disease incidence across India. Time series anomaly detection flags unusual spikes in dengue, malaria, and respiratory illness cases at the district level, triggering rapid response.

16.4 Smart Cities Mission โ€” Traffic Forecasting

Cities like Pune, Hyderabad, and Bengaluru use traffic sensor time series data to forecast congestion, optimize signal timings, and plan infrastructure. SARIMA models capture daily and weekly patterns, while LSTM models incorporate weather and event data.

๐Ÿ‡ฎ๐Ÿ‡ณ India Spotlight

India's GST (Goods and Services Tax) collections are a key economic time series. Monthly collections crossed โ‚น2 lakh crore in April 2024. The Ministry of Finance uses time series analysis to forecast revenue and set fiscal targets for the Union Budget.

17

Industry Applications

17.1 Manufacturing โ€” Predictive Maintenance

Sensor time series (vibration, temperature, pressure) from machines are monitored using anomaly detection. LSTM autoencoders learn "normal" operating patterns and flag deviations. Companies like Tata Steel and Reliance Industries use this to prevent unplanned downtime worth crores per hour.

17.2 Telecom โ€” Network Traffic Forecasting

Jio, Airtel, and Vi forecast network traffic to plan capacity. Time series at the cell tower level show strong daily patterns (peaks at 8-10 PM) and weekly patterns (weekends vs. weekdays). SARIMA and Prophet handle this well, while LSTM captures special events like cricket match streaming.

17.3 Banking โ€” ATM Cash Demand

Banks forecast cash withdrawal patterns at each ATM to optimize replenishment schedules. The series shows strong patterns: salary days (1st and 15th), weekends, festivals, and even election days. Post-demonetization (Nov 2016), models had to rapidly adapt to fundamentally changed withdrawal patterns.

17.4 Pharma โ€” Drug Demand Forecasting

Pharmaceutical companies forecast drug demand considering: seasonal illness patterns (flu season), patent expiry impacts (generic entry), and supply chain lead times. Cipla and Sun Pharma use hierarchical time series models (bottom-up from SKU level to national).

17.5 Aviation โ€” Ticket Price Optimization

IndiGo, Air India, and SpiceJet use time series models for dynamic pricing. Historical booking curves (cumulative bookings vs. days before departure) are modeled per route-class combination. Forecasting residual demand enables revenue optimization (yield management).

IndustryTypical SeriesPreferred ModelForecast Horizon
FinanceStock prices, volatilityARIMA + GARCH1-5 days
RetailSKU-level salesProphet / LightGBM1-13 weeks
EnergyElectricity loadSARIMA + LSTM1-24 hours
WeatherTemperature, rainfallNWP + ML post-processing1-10 days
TelecomNetwork trafficSARIMA + ProphetHours to days
HealthcarePatient admissionsHolt-Winters1-4 weeks
ManufacturingSensor readingsLSTM AutoencoderReal-time
18

Mini Projects

๐Ÿ—๏ธ Mini Project 1: Stock Price Forecaster

Objective: Build an end-to-end system that forecasts the next 5 trading days of Nifty50/RELIANCE stock prices.

Steps:

  1. Data Collection: Use yfinance library to download 5 years of daily OHLCV data for RELIANCE.NS
  2. EDA: Plot closing prices, compute rolling statistics, check stationarity (ADF, KPSS)
  3. Feature Engineering: Log returns, 20/50/200-day moving averages, RSI, MACD, Bollinger Bands
  4. Model 1 โ€” ARIMA: Fit ARIMA on log prices, use auto_arima for order selection
  5. Model 2 โ€” Prophet: Fit Prophet with custom holiday for Indian market holidays (Republic Day, Diwali, etc.)
  6. Model 3 โ€” LSTM: Window=60 days, 2-layer LSTM (64, 32 units), train on 80% data
  7. Comparison: Evaluate all models on test set using RMSE, MAPE, directional accuracy
  8. Deployment: Create a simple Streamlit app showing forecasts with confidence intervals
PYTHON
# Starter code for Mini Project 1
import yfinance as yf
import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from prophet import Prophet

# Download data
ticker = "RELIANCE.NS"
df = yf.download(ticker, start="2019-01-01", end="2024-12-31")
print(f"Downloaded {len(df)} rows for {ticker}")

# Basic analysis
df['Log_Return'] = np.log(df['Close'] / df['Close'].shift(1))
df['MA_20'] = df['Close'].rolling(20).mean()
df['MA_50'] = df['Close'].rolling(50).mean()

# Train-test split
train = df[:'2024-06-30']
test = df['2024-07-01':]
print(f"Train: {len(train)}, Test: {len(test)}")

# ARIMA on log prices
log_price = np.log(train['Close'])
model = ARIMA(log_price, order=(2, 1, 2))
fitted = model.fit()
forecast_log = fitted.forecast(steps=len(test))
forecast_price = np.exp(forecast_log)

rmse = np.sqrt(np.mean((test['Close'].values - forecast_price.values) ** 2))
print(f"ARIMA RMSE: โ‚น{rmse:.2f}")

# TODO: Add Prophet and LSTM models, compare, build Streamlit app

Expected Deliverables: Jupyter notebook with visualizations, model comparison table, Streamlit dashboard, and a 2-page report discussing why stock prices are fundamentally hard to predict (EMH).

๐Ÿ—๏ธ Mini Project 2: Weather Predictor (Temperature Forecasting)

Objective: Forecast daily maximum temperature for an Indian city (Delhi/Mumbai/Bangalore) for the next 7 days.

Steps:

  1. Data: Download historical weather data from Open-Meteo API or Visual Crossing for 10+ years
  2. EDA: Annual seasonality (summer/winter), decompose into trend + season + residual
  3. Stationarity: After seasonal differencing (lag=365), check with ADF
  4. Model 1 โ€” SARIMA: SARIMA(p,d,q)(P,D,Q,365) โ€” challenging due to long seasonal period, consider seasonal_period=7 for weekly patterns
  5. Model 2 โ€” Holt-Winters: Additive seasonality with period=365
  6. Model 3 โ€” Prophet: Captures yearly + weekly seasonality automatically
  7. Model 4 โ€” LSTM: Window=90 days, include humidity and wind speed as extra features
  8. Ensemble: Simple average of top 2 models' forecasts
PYTHON
# Starter code for Mini Project 2
import pandas as pd
import numpy as np
import requests

# Fetch data from Open-Meteo API
url = "https://archive-api.open-meteo.com/v1/archive"
params = {
    "latitude": 28.6139,  # Delhi
    "longitude": 77.209,
    "start_date": "2014-01-01",
    "end_date": "2024-12-31",
    "daily": "temperature_2m_max,temperature_2m_min,precipitation_sum",
    "timezone": "Asia/Kolkata"
}
response = requests.get(url, params=params)
data = response.json()

df = pd.DataFrame({
    'date': pd.to_datetime(data['daily']['time']),
    'temp_max': data['daily']['temperature_2m_max'],
    'temp_min': data['daily']['temperature_2m_min'],
    'precip': data['daily']['precipitation_sum']
})
df.set_index('date', inplace=True)
print(f"Delhi weather data: {len(df)} days")
print(df.describe())

# Prophet model
from prophet import Prophet
prophet_df = df[['temp_max']].reset_index()
prophet_df.columns = ['ds', 'y']

model = Prophet(yearly_seasonality=True, weekly_seasonality=True)
model.fit(prophet_df)

future = model.make_future_dataframe(periods=7)
forecast = model.predict(future)
print("\nNext 7-day Temperature Forecast:")
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(7))

Expected Deliverables: Complete notebook, model comparison with RMSE/MAPE, visualization of forecast vs actual for test period, and discussion of which model handles Delhi's extreme summer (45ยฐC+) best.

๐Ÿ—๏ธ Mini Project 3: Anomaly Detection in Server Metrics

Objective: Build a real-time anomaly detection system for server CPU/memory time series.

Steps:

  1. Generate synthetic server metrics with injected anomalies (spikes, level shifts, trend changes)
  2. Implement statistical method: Z-score on rolling window residuals
  3. Implement Prophet-based method: Flag points outside prediction intervals
  4. Implement LSTM Autoencoder: Reconstruction error-based anomaly scoring
  5. Compare precision/recall/F1 on known anomalies
  6. Build a dashboard showing real-time metric with anomaly highlights
19

Exercises

Exercise 1 Easy

Given the series [10, 12, 15, 19, 24, 30], compute the first and second differences by hand. Is the first difference stationary? Is the second?

Exercise 2 Easy

For an AR(1) model Y(t) = 2 + 0.5Y(t-1) + ฮต(t), compute: (a) the long-run mean, (b) ฯ(1), ฯ(2), ฯ(3), (c) Y(t+1) if Y(t) = 8.

Exercise 3 Easy

Explain the difference between ACF and PACF. How do you use them together to identify ARIMA orders?

Exercise 4 Medium

For an MA(1) model Y(t) = 10 + ฮต(t) + 0.4ฮต(t-1) with ฯƒยฒ=9, compute: (a) E[Y(t)], (b) Var(Y(t)), (c) ฯ(1), (d) ฯ(2).

Exercise 5 Medium

Apply SES with ฮฑ=0.2 to [200, 180, 190, 210, 195, 205, 220]. Start with ลท(1)=200. Compute all forecasts and the final forecast for period 8.

Exercise 6 Medium

A series has ADF p-value = 0.34 and KPSS p-value = 0.01. What do you conclude? What action should you take?

Exercise 7 Medium

You see ACF that decays gradually and PACF that cuts off sharply at lag 3. What model would you identify? Write the model equation.

Exercise 8 Medium

Explain why a random walk Y(t) = Y(t-1) + ฮต(t) is non-stationary. What is its variance at time t?

Exercise 9 Medium

Compute MAPE, RMSE, and SMAPE for: Actual = [50, 60, 70, 80, 90], Forecast = [52, 58, 73, 76, 95].

Exercise 10 Medium

What is the difference between additive and multiplicative decomposition? Give a real-world Indian example where multiplicative is preferred.

Exercise 11 Medium

Write Python code to perform seasonal decomposition on monthly airline passenger data using statsmodels. Plot and interpret each component.

Exercise 12 Medium

For SARIMA(1,1,1)(1,1,1,12), how many parameters need to be estimated? Write out the full model equation using backshift notation.

Exercise 13 Hard

Prove that the variance of an AR(1) process Y(t) = ฯ†Y(t-1) + ฮต(t) is ฯƒยฒ/(1-ฯ†ยฒ). What happens as |ฯ†| โ†’ 1?

Exercise 14 Hard

Implement Holt-Winters (additive) from scratch in Python. Test on a series with clear trend and seasonality. Compare your output with statsmodels.

Exercise 15 Hard

Build an LSTM model in TensorFlow for multi-step forecasting (predict 7 days ahead simultaneously). Compare seq2one (iterate) vs seq2seq (direct) approaches.

Exercise 16 Medium

Use Prophet to forecast Indian GST monthly collections. Add custom holidays for Diwali, Eid, and Republic Day. How do holidays affect GST?

Exercise 17 Hard

Implement a VAR(2) model for Nifty50 and USD/INR exchange rate. Perform Granger causality tests. Does one "cause" the other?

Exercise 18 Medium

Create a time series anomaly detector using z-scores on rolling window residuals. Test it on synthetic data with 5 injected anomalies.

Exercise 19 Hard

Compare AIC and BIC for model selection. Fit ARIMA(1,1,0), ARIMA(0,1,1), ARIMA(1,1,1), and ARIMA(2,1,1) on a dataset. Which does AIC prefer? Which does BIC prefer? Why might they differ?

Exercise 20 Easy

What is the Box-Cox transformation? If the optimal ฮป=0.5, what transformation is applied? How do you inverse-transform forecasts?

Exercise 21 Hard

Build an LSTM autoencoder for time series anomaly detection. Train on normal data only, then use reconstruction error to flag anomalies in a test set containing anomalies.

Exercise 22 Medium

Explain cross-validation for time series. Why can't you use standard k-fold? Implement expanding window and sliding window CV schemes.

20

Multiple Choice Questions

Q1. In the ADF test, a p-value of 0.02 indicates:
  • A) The series is non-stationary
  • B) The series is stationary (reject Hโ‚€ of unit root)
  • C) The test is inconclusive
  • D) The series has seasonal patterns
โœ… B) The series is stationary. ADF Hโ‚€ = unit root exists. p-value < 0.05 โ†’ reject Hโ‚€ โ†’ series is stationary.
Q2. If the ACF of a stationary series cuts off after lag 2 and the PACF decays gradually, the appropriate model is:
  • A) AR(2)
  • B) MA(2)
  • C) ARMA(2,2)
  • D) ARIMA(0,1,2)
โœ… B) MA(2). ACF cuts off โ†’ MA order q=2. PACF decays โ†’ confirms MA, not AR.
Q3. In ARIMA(1,2,1), the value d=2 means:
  • A) Two autoregressive lags are used
  • B) The series was differenced twice to achieve stationarity
  • C) Two moving average terms are included
  • D) The seasonal period is 2
โœ… B) The series was differenced twice. The 'd' in ARIMA(p,d,q) = order of differencing.
Q4. Simple Exponential Smoothing with ฮฑ close to 1 gives:
  • A) More weight to recent observations
  • B) More weight to older observations
  • C) Equal weight to all observations
  • D) More weight to the initial observation only
โœ… A) ฮฑ close to 1 means the forecast is dominated by the most recent observation. The weights (1-ฮฑ)^i decay very fast, so old data is essentially forgotten.
Q5. Which metric has a problem when actual values are zero or near zero?
  • A) RMSE
  • B) MAE
  • C) MAPE
  • D) MSE
โœ… C) MAPE divides by |actual|, so it becomes undefined or infinite when actual = 0. Use SMAPE or RMSE instead.
Q6. Prophet by Meta models the trend component as:
  • A) An ARIMA process
  • B) A piecewise-linear or logistic growth function
  • C) A polynomial regression
  • D) A random walk
โœ… B) Prophet models trend as either piecewise-linear (default) or logistic growth (for saturating trends). Changepoints automatically detect where the trend slope changes.
Q7. In an LSTM cell, the forget gate determines:
  • A) What new information to add to the cell state
  • B) What information to discard from the cell state
  • C) What part of the cell state to output
  • D) The learning rate
โœ… B) The forget gate (f_t = ฯƒ(W_fยท[h_{t-1}, x_t] + b_f)) outputs values in [0,1] that multiply the previous cell state, determining what to forget (0 = forget, 1 = keep).
Q8. A VAR(1) model with 3 variables has how many parameters (excluding intercepts)?
  • A) 3
  • B) 6
  • C) 9
  • D) 12
โœ… C) 9. Each of the 3 equations has 3 coefficients (one for each variable's lag 1). Total = 3 ร— 3 = 9 AR parameters. (Plus 3 intercepts if counted.)
Q9. What is the KPSS test's null hypothesis?
  • A) The series has a unit root
  • B) The series is stationary
  • C) The series has no autocorrelation
  • D) The residuals are normally distributed
โœ… B) KPSS tests Hโ‚€: series is stationary vs Hโ‚: unit root (non-stationary). This is the opposite of ADF! If KPSS rejects Hโ‚€, the series is non-stationary.
Q10. Which of the following is NOT a component of the Prophet model?
  • A) Trend g(t)
  • B) Seasonality s(t)
  • C) Autoregressive term ฯ†Y(t-1)
  • D) Holiday effects h(t)
โœ… C) Prophet does NOT include autoregressive terms. It uses y(t) = g(t) + s(t) + h(t) + ฮต(t). This is a key difference from ARIMA โ€” Prophet is regression-based, not autoregressive.
Q11. When using time series cross-validation, which approach is correct?
  • A) Standard k-fold with random splits
  • B) Expanding/sliding window maintaining temporal order
  • C) Leave-one-out with random selection
  • D) Stratified k-fold based on target values
โœ… B) Time series must preserve temporal order. Expanding window (train on all data up to cutoff, test on next h steps) or sliding window (fixed train window moves forward) are correct. Random splits cause data leakage!
21

Interview Questions

Interview Q1
What is stationarity and why is it important for time series modeling?

Model Answer: A stationary time series has constant mean, variance, and autocovariance over time. Most classical models (ARIMA, VAR) assume stationarity because their parameters are estimated from the entire series โ€” if statistical properties change over time, the estimated parameters are meaningless averages. Non-stationary series also lead to spurious regression (two unrelated trending series appear correlated). We achieve stationarity through differencing, log transforms, or detrending.

Interview Q2
Explain the difference between AR, MA, and ARIMA models.

Model Answer: AR(p) models the current value as a linear function of p past values โ€” it captures momentum/persistence. MA(q) models the current value as a function of q past forecast errors โ€” it captures shocks. ARIMA(p,d,q) combines both with d rounds of differencing to handle non-stationarity. AR captures gradual effects (autocorrelation), MA captures sudden effects (error corrections), and the I (Integration) handles trends.

Interview Q3
How would you handle a time series with both trend and seasonality?

Model Answer: Options include: (1) SARIMA with seasonal differencing and seasonal AR/MA terms, (2) Holt-Winters with explicit trend and seasonal components, (3) Prophet which models trend (piecewise-linear) and seasonality (Fourier terms) separately, (4) STL decomposition to remove trend/season, then model residuals with ARIMA. For large datasets, LSTM with calendar features works well. I'd start with decomposition to understand the components, then choose the model based on data size and forecasting horizon.

Interview Q4
When would you choose Prophet over ARIMA? When would you choose ARIMA?

Model Answer: Choose Prophet when: you have multiple seasonalities (daily + weekly + yearly), many missing values, you need to add holiday effects easily, or when you're forecasting at scale (thousands of series with minimal tuning). Choose ARIMA when: you have few data points (<100), you need a purely statistical approach with confidence intervals grounded in theory, or when the series is well-modeled by a low-order ARIMA (interpretable coefficients). ARIMA is also faster for single-series inference.

Interview Q5
How do you handle missing values in time series?

Model Answer: (1) Forward fill (locf) โ€” carry last observation forward, (2) Linear interpolation โ€” works for gradual changes, (3) Seasonal interpolation โ€” fill with value from same season last year, (4) Model-based imputation โ€” fit ARIMA on available data, fill gaps with predictions, (5) Prophet handles missing values natively. The key is understanding whether missingness is random (MCAR) or systematic (sensor failure = extended gaps). Never drop rows in time series โ€” it destroys temporal structure.

Interview Q6
Explain the concept of Granger Causality. Does it imply true causation?

Model Answer: Granger Causality tests whether past values of series X improve the forecast of series Y beyond what past values of Y alone provide. If including lagged X significantly reduces the forecast error (F-test p-value < 0.05), we say X "Granger-causes" Y. However, it does NOT imply true causation โ€” it's about predictive information, not causal mechanism. Two series could be Granger-causal because of a confounding third variable. It's a statistical concept, not a causal one.

Interview Q7
How do you evaluate a time series model? Why can't you use standard cross-validation?

Model Answer: Standard k-fold CV randomly shuffles data, breaking temporal dependencies and causing data leakage (future data used to predict past). Instead, use: (1) Train-test split preserving order (last 20% as test), (2) Expanding window CV โ€” train on data up to time t, test on t+1 to t+h, then expand, (3) Sliding window CV โ€” fixed-size training window moves forward. Metrics: RMSE for magnitude, MAPE for relative error, SMAPE for symmetry, and directional accuracy for trading applications.

Interview Q8
What are the limitations of LSTM for time series forecasting?

Model Answer: (1) Data hungry โ€” needs thousands of points, unsuitable for short series, (2) Black box โ€” no interpretable coefficients, problematic for regulated industries, (3) Training time and compute cost โ€” much slower than ARIMA, (4) Sensitive to hyperparameters โ€” window size, layers, units, learning rate, (5) Multi-step forecasting error compounds โ€” iterative forecasting accumulates errors, (6) Doesn't inherently model seasonality โ€” must be engineered as features, (7) Modern alternatives (Transformers, N-BEATS) often outperform on benchmarks.

Interview Q9
How would you detect anomalies in a time series at scale (millions of series)?

Model Answer: At scale, I'd use a multi-tier approach: (1) Statistical baselines โ€” rolling z-score (fast, no training), flag |z| > 3, (2) Seasonal-aware โ€” STL decomposition to remove season, then z-score on residuals, (3) For important series โ€” Prophet with uncertainty intervals, or Isolation Forest on feature-engineered representation, (4) Training a single LSTM autoencoder on all "normal" series and using reconstruction error, (5) Streaming approaches โ€” online algorithms (ADWIN) for concept drift detection. The key is balancing precision (avoiding false alarms) with recall (catching real anomalies).

Interview Q10
A time series shows high ADF p-value (0.6) and low KPSS p-value (0.01). What does this mean?

Model Answer: ADF p-value 0.6 โ†’ fail to reject Hโ‚€ (unit root), so ADF says non-stationary. KPSS p-value 0.01 โ†’ reject Hโ‚€ (stationary), so KPSS also says non-stationary. Both tests agree: the series is non-stationary. Action: apply differencing (d=1), then retest. If the disagreement case arose (ADF says stationary, KPSS says not, or vice versa), the series is "near unit root" โ€” consider fractional differencing or detrending as alternatives to full differencing.

Interview Q11
How does the Holt-Winters method differ from ARIMA? When would you prefer one over the other?

Model Answer: Holt-Winters directly models level, trend, and seasonality with smoothing equations โ€” it's intuitive and computationally light. ARIMA models the differenced series through AR and MA terms โ€” more flexible, with formal diagnostic tools (Ljung-Box, AIC/BIC). Prefer Holt-Winters when: the series has clear trend + seasonality, you need quick results, or for production systems needing fast updates. Prefer ARIMA when: the series is complex (multiple differencing needed), you need formal statistical inference, or for academic rigor.

22

Research Problems

๐Ÿ”ฌ Research Problem 1: Foundation Models for Indian Time Series

Problem: Large language models have been adapted for time series (TimeGPT, Chronos). Can a foundation model pre-trained on diverse Indian time series (weather, stocks, agriculture, telecom) transfer knowledge across domains? How does cross-domain pre-training compare to domain-specific models?

Approach: Collect a large corpus of Indian time series data across 5+ domains. Pre-train a Transformer-based model. Evaluate zero-shot and few-shot performance on held-out series from each domain. Compare with domain-specific ARIMA and LSTM models.

References: Ansari et al. (2024) "Chronos: Learning the Language of Time Series"; Garza & Mergenthaler-Canseco (2023) "TimeGPT-1".

๐Ÿ”ฌ Research Problem 2: Causal Discovery in Multivariate Indian Economic Time Series

Problem: India's economic indicators (CPI, WPI, repo rate, GDP, Nifty50, USD/INR, crude oil) form a complex web of causal relationships. Can we move beyond Granger causality to discover true causal structure using modern causal inference methods (PCMCI, Convergent Cross-Mapping)?

Approach: Apply PCMCI (Runge et al., 2019) to monthly data from RBI, MOSPI, and NSE. Compare causal graphs with Granger causality results. Validate against known economic mechanisms (e.g., RBI rate โ†’ lending rates โ†’ GDP).

๐Ÿ”ฌ Research Problem 3: Forecasting Indian Monsoon Extremes with Deep Learning

Problem: Climate change is making Indian monsoon patterns more erratic. Can attention-based deep learning models (Temporal Fusion Transformers) improve prediction of extreme rainfall events (>100mm/day) at the district level, with lead times of 1-7 days?

Approach: Use IMD gridded rainfall data (0.25ยฐ resolution), ERA5 reanalysis data, and sea surface temperature as inputs. Train a TFT with custom loss function penalizing missed extremes. Compare with IMD's current NWP-based warnings.

๐Ÿ”ฌ Research Problem 4: Explainable Time Series Anomaly Detection for Smart Cities

Problem: Current anomaly detection in urban sensor networks (traffic, pollution, water quality) produces alerts but rarely explains WHY an anomaly occurred. Can we build interpretable anomaly detectors that provide natural language explanations linking anomalies to root causes?

Approach: Combine SHAP-based feature attribution on gradient boosting models with LLM-generated explanations. Train on labeled historical anomalies from Pune Smart City data where root causes are known (water main break, festival traffic, industrial pollution event). Evaluate explanation quality with domain experts.

23

Key Takeaways

๐Ÿ“Š
Decomposition First: Every time series has trend, seasonality, cyclical, and noise components. Always decompose and visualize before modeling โ€” understanding the components guides model selection.
๐Ÿ“ˆ
Stationarity is Non-Negotiable: Most classical models require stationarity. Use ADF + KPSS together for robust testing. Apply differencing (d for trend, D for seasonal) and transforms (log, Box-Cox) as needed.
๐Ÿ“‰
ACF/PACF are Your Friends: ACF decays + PACF cuts off โ†’ AR(p). ACF cuts off + PACF decays โ†’ MA(q). Both decay โ†’ ARMA(p,q). These plots are the foundation of model identification.
๐Ÿ”ง
Box-Jenkins is Systematic: Identify โ†’ Estimate โ†’ Diagnose โ†’ Forecast. Check residuals with Ljung-Box test. If residuals aren't white noise, revise the model. Use AIC/BIC for model comparison.
โšก
Match Model to Context: ARIMA for small data + interpretability. SARIMA/Holt-Winters for clear seasonal patterns. Prophet for multiple seasonalities + holidays at scale. LSTM for large data + complex nonlinear patterns. VAR for multivariate interdependencies.
๐Ÿ“
Metrics Matter: RMSE penalizes large errors. MAPE gives relative accuracy but fails near zero. SMAPE is symmetric and bounded. Always use multiple metrics and a naive baseline (persistence model) for context.
โš ๏ธ
No Time Travel in Validation: Never use standard k-fold CV on time series. Use expanding window or sliding window cross-validation that preserves temporal order. Future data must never leak into training.
๐Ÿง 
LSTMs Need Care: They require large datasets (1000+ points), careful windowing, proper scaling (MinMaxScaler), and they're black boxes. Modern alternatives (TFT, N-BEATS, Chronos) often outperform. Always benchmark against ARIMA.
๐Ÿšจ
Anomaly Detection is Dual-Use: The same forecast residual-based approach serves both forecasting (is my model accurate?) and anomaly detection (is this data point unusual?). Prophet's prediction intervals make this easy.
๐Ÿ‡ฎ๐Ÿ‡ณ
Indian Data Has Unique Challenges: Lunar calendar holidays, demonetization/GST structural breaks, monsoon-dependent agriculture, high festival seasonality. Domain knowledge is crucial โ€” no model can replace understanding of Indian economic and cultural patterns.
24

References

Foundational Texts

  1. Box, G.E.P., Jenkins, G.M., Reinsel, G.C., & Ljung, G.M. (2015). Time Series Analysis: Forecasting and Control, 5th Edition. Wiley. โ€” The classic reference.
  2. Hyndman, R.J. & Athanasopoulos, G. (2021). Forecasting: Principles and Practice, 3rd Edition. OTexts. Free online: otexts.com/fpp3 โ€” The best modern textbook.
  3. Hamilton, J.D. (1994). Time Series Analysis. Princeton University Press. โ€” Graduate-level econometric treatment.
  4. Shumway, R.H. & Stoffer, D.S. (2017). Time Series Analysis and Its Applications, 4th Edition. Springer.

Key Research Papers

  1. Dickey, D.A. & Fuller, W.A. (1979). "Distribution of the Estimators for Autoregressive Time Series with a Unit Root." JASA, 74(366), 427-431.
  2. Kwiatkowski, D. et al. (1992). "Testing the null hypothesis of stationarity against the alternative of a unit root." J. of Econometrics, 54(1-3), 159-178.
  3. Hochreiter, S. & Schmidhuber, J. (1997). "Long Short-Term Memory." Neural Computation, 9(8), 1735-1780.
  4. Taylor, S.J. & Letham, B. (2018). "Forecasting at Scale." The American Statistician, 72(1), 37-45. โ€” The Prophet paper.
  5. Salinas, D. et al. (2020). "DeepAR: Probabilistic Forecasting with Autoregressive Recurrent Networks." International J. of Forecasting, 36(3), 1181-1191.
  6. Lim, B. et al. (2021). "Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting." International J. of Forecasting, 37(4), 1748-1764.
  7. Oreshkin, B.N. et al. (2020). "N-BEATS: Neural Basis Expansion Analysis for Interpretable Time Series Forecasting." ICLR 2020.
  8. Lam, R. et al. (2023). "Learning Skillful Medium-Range Global Weather Forecasting." Science, 382(6677), 1416-1421. โ€” GraphCast.
  9. Ansari, A.F. et al. (2024). "Chronos: Learning the Language of Time Series." arXiv:2403.07815.

Indian Context References

  1. Rajeevan, M. et al. (2012). "Analysis of variability and trends of extreme rainfall events over India using 104 years of gridded daily rainfall data." Geophysical Research Letters, 39(6).
  2. Reserve Bank of India (2023). "Report on Currency and Finance 2022-23." RBI Publications. โ€” Contains RBI's forecasting methodology.
  3. Indian Meteorological Department (2024). "End of Season Report โ€” Southwest Monsoon 2023." IMD, Ministry of Earth Sciences.
  4. Sahoo, B.B. et al. (2019). "Long short-term memory (LSTM) recurrent neural network for low-flow hydrological time series forecasting." Acta Geophysica, 67, 1471-1481.

Software & Libraries

  1. statsmodels: statsmodels.org โ€” Python statistical models including ARIMA, VAR.
  2. Prophet: facebook.github.io/prophet โ€” Meta's forecasting library.
  3. pmdarima: alkaline-ml.com/pmdarima โ€” Auto-ARIMA for Python.
  4. TensorFlow/Keras: tensorflow.org โ€” LSTM implementation.
  5. Nixtla: github.com/Nixtla โ€” TimeGPT and StatsForecast libraries.
  6. Darts: unit8co.github.io/darts โ€” Unified time series library supporting many models.

Online Resources

  1. Kaggle โ€” M5 Forecasting Competition: kaggle.com/c/m5-forecasting-accuracy
  2. IITM Pune โ€” Indian Rainfall Data: tropmet.res.in
  3. NSE India Historical Data: nseindia.com
๐ŸŽ“ Professor's Insight โ€” Final Words

Time series forecasting is where theory meets humility. George Box's famous quote โ€” "All models are wrong, but some are useful" โ€” is most true here. No model can predict a pandemic, a demonetization, or a war. The best forecasters combine statistical rigor with domain knowledge, scenario planning, and honest uncertainty quantification. As you build your career, remember: a simple model with good uncertainty intervals is more useful than a complex model that's overconfident.