Cheat sheets

Time Series Fundamentals

Check stationarity, build lag features, validate walk-forward, beat naive baselines. Random walks and Markov chains.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

From series to honest forecast#

driftsfoldsmust beatRaw seriesplot it firstStationaritycheckrolling mean andstdDifferencingat most two roundsLag featuresvalues at t-1 orearlierwalk_forward_splittrain before testModelRidge, SimpleAR,ARIMABaselinespersistence,seasonal naiveScoreMAE, RMSE, MAPEdriftsfoldsmust beatRaw seriesplot it firstStationarity checkrolling mean and stdDifferencingat most two roundsLag featuresvalues at t-1 orearlierwalk_forward_splittrain before testModelRidge, SimpleAR, ARIMABaselinespersistence, seasonalnaiveScoreMAE, RMSE, MAPE

From Lesson 02.15, 02.15 code/time_series.py

Walk-forward validation#

1Trainfit on data up to time t.2Predictforecast t+1, or t+1 to t+k for multi-step.3Slidemove the window forward.4Repeateach test fold comes after all its trainingdata.5Expanding windowtraining set grows. Use it when old data staysrelevant.6Sliding windowfixed size. Use it when the world changes andold data hurts.

From Lesson 02.15

Tasks in code#

TaskCode
Remove a trenddifference(series, order=1)
Rolling stats and a verdictcheck_stationarity(series, window=50)
ACF up to a lagautocorrelation(series, max_lag=20)
Series to X and ymake_lag_features(series, n_lags)
Time-ordered foldswalk_forward_split(n_samples, n_splits=5, min_train=50)
AR on lag featuresSimpleAR(n_lags=5).fit_series(series)
Recursive multi-stepforecast(last_values, n_steps)
Percent error, skips zerosmape(y_true, y_pred)

From 02.15 code/time_series.py

Library versions#

X, y = make_lag_features(series, n_lags=10)
for train_idx, test_idx in walk_forward_split(len(X)):
model = Ridge(alpha=1.0)
model.fit(X[train_idx], y[train_idx])
predictions = model.predict(X[test_idx])
model = ARIMA(train_series, order=(5, 1, 2))p, d, q
fitted = model.fit()
forecast = fitted.forecast(steps=30)30 steps ahead
tscv = TimeSeriesSplit(n_splits=5)sklearn walk-forward
scores = cross_val_score(model, X, y, cv=TimeSeriesSplit(n_splits=5))

From Lesson 02.15

Core definitions#

Components
trend, seasonality and residual. A white-noise residual means the split worked.
Stationary
mean, variance and autocorrelation do not change over time.
Differencing
\text{diff}[t] = \text{value}[t] - \text{value}[t-1]
ACF
correlation of the series with a lagged copy. Use lags up to where it is negligible.
PACF
autocorrelation at lag k after the effect of shorter lags is removed.
ARIMA(p, d, q)
p past values, d rounds of differencing, q past errors.
MAE / RMSE / MAPE
mean absolute error, squared error root, percent error.
Target alignment
target at t. Every feature uses t-1 or earlier.

From Lesson 02.15

Pick an approach#

CommandWhat it does
Lag features + MLMany external features. Strongest start with boosting
ARIMAOne univariate series, short term. SARIMA for seasons
Exponential smoothingSimple trend + seasonality with Holt-Winters
Neural networksLong sequences, many series
Recursive forecastFeeds predictions back. Use for 1-5 steps
Direct forecastOne model per horizon. Use for long horizons
Multi-outputOne model outputs all horizons

From Lesson 02.15

Defaults and numbers#

SettingDefaultNote
check_stationarity window50Rolling window size
Mean shift limit0.5Times the series std, half against half
Variance ratio limit2.0Above it, flagged non-stationary
ADF p-value0.05Below it, reject non-stationary
max_lag20Autocorrelation default
n_splits, min_train5min_train=50 rows before the first test
Rolling windows7 and 14Mean, std, min, max in days
Weekly seasonalitylag 7Possibly 14 too

From Lesson 02.15, 02.15 code/time_series.py

Mistakes and fixes#

SymptomCauseFix
Random split MSE lowerFuture leakageWalk-forward or temporal split
Near-perfect backtestFeature at time t includedAudit every feature alignment
Misses the seasonal patternTest set shorter than one cycleHold out a full seasonal cycle
Revenue doubles, model lagsAbsolute scale changedModel percentage change
Overfit with many lags"More history is better"Pick lags from the ACF
Linear model driftsTrend not removedDifference first, model second
Loses to seasonal naiveLeakage, wrong eval, or random seriesFix the bug before tuning
Errors rise in productionWorld changedRetrain on recent data

From Lesson 02.15, 02.15 code/time_series.py

Stochastic processes in code#

positions = random_walk_1d(n_steps, seed=None)std grows as sqrt(n)
mc = MarkovChain(P, state_names=names)rows of P sum to 1
pi = mc.stationary_distribution()left eigenvector, eigenvalue 1
states = mc.simulate(start_state=0, n_steps=100000, seed=42)
traj = langevin_dynamics(grad_U, x0, dt, temperature, n_steps)
samples, acc_rate = metropolis_hastings(
target_log_prob=bimodal_log_prob,
proposal_std=2.0, x0=np.array([0.0]), n_samples=100000, seed=42)
samples_flat = samples[10000:, 0]burn-in discarded

From 01.22 code/stochastic.py, Lesson 01.22

Random walks and Markov chains#

Random walk
mean 0, standard deviation \sqrt{n}. 10000 steps gives about 100.
Markov property
the next state depends only on the current state.
Stationary distribution
\pi P = \pi. Weather chain gives [0.55, 0.18, 0.27].
Convergence
needs an irreducible and aperiodic chain.
Spectral gap
1 minus the second eigenvalue. A gap of 0.2 mixes in about 5 steps.
Brownian step
B(t + dt) = B(t) + \sqrt{dt} \, z
Langevin
x_{t+1} = x_t - dt \, \nabla U(x_t) + \sqrt{2 T \, dt} \, z_t
Metropolis-Hastings
accept with \min(1, a). Aim for about 23% acceptance.

From Lesson 01.22

Anomalies in time#

  • 90 degrees is normal in summer and anomalous in winter. Contextual anomalies need time features.
  • Collective anomalies need sequence-aware methods. Fifty failed logins in a row is an attack.
  • Add rolling statistics, ratios and time-since-last-event features.
  • Rolling statistics over 30 days need 30 days of buffered history at scoring time.
  • Track the anomaly score distribution. A fixed threshold drifts out of date.

From Lesson 02.16

Questions#

Why not k-fold?
Samples are not independent. Random folds leak the future into training.
How many differences?
Most real series need at most two rounds.
How many lags?
Use the ACF. Spikes at lag 12 on monthly data mean yearly seasonality.
Do trees need differencing?
Tree models handle trends. Linear models need stationarity.
Skewed revenue?
Forecast in log space, then exponentiate.
Which baseline first?
Last value, then seasonal naive, then moving average.

From Lesson 02.15