Deep learning for forecasting: RNNs, temporal CNNs, transformers and foundation models
Before this lesson: lesson 03 (baselines, backtesting, MASE), lesson 08 (windows as a table, recursive and direct strategies, global models) and lesson 07 (for the paragraph on state-space layers). From the deep-learning track: convolutions, recurrent networks and the LSTM, attention, the transformer and state-space models. Time: about 2 hours, plus the notebook.
Why this matters #
- Many related series. Retailers, cloud providers and energy companies forecast thousands to millions of series at once. One global network trained on all of them shares patterns between series and can forecast a new product with little history. DeepAR (Salinas et al. 2017) was built for this setting and is a built-in algorithm of Amazon SageMaker.
- Long contexts and rich covariates. Hourly load, traffic and sensor data have daily and weekly cycles, holidays and weather. Convolutions, patched transformers and models such as the Temporal Fusion Transformer handle long windows and many inputs.
- Pretrained models change the workflow. A zero-shot model (Chronos, TimesFM, Moirai, TiRex, ...) gives a probabilistic forecast for any series in one call, with no training. This is the newest and fastest-moving part of the field, so you need to know how these models work and how to test them.
- The evidence is mixed. On one short series, exponential smoothing, ARIMA (lessons 04 and 06) and gradient boosting (lesson 08) are hard to beat, and on standard long-horizon benchmarks a one-layer linear model beat several published transformers (Zeng et al. 2023). Knowing why protects you from using a big model where a small one is better.
1. Predict first #
2. The picture #
A forecasting network in one picture #
Every model in this lesson has the same outer shape:
- Cut out the context. At the forecast origin , take the last values . is the lookback or context length. (In this lesson is the largest horizon, not the observation matrix of lesson 07.)
- Scale the window with statistics of the window only, for example with .
- Run the network on (plus covariates such as calendar features).
- Read the head. A point head outputs numbers; a distribution head outputs parameters such as a mean and a scale; a quantile head outputs, for example, the 10%, 50% and 90% quantiles.
- Undo the scaling: multiply by (and add back a shift, if one was removed).
Training uses many windows: every position of the origin in every training series gives one example, as in the "window to table" reduction of lesson 08. The network either outputs all steps at once (multi-output, the direct strategy) or one step at a time and feeds its output back (autoregressive, the recursive strategy).
Recurrent networks: one step at a time, and samples instead of a single path #
A recurrent network reads in order and updates a hidden state , a summary of the past (the cell equations are in deep-learning lesson 08). DeepAR (Salinas et al. 2017) puts a probability distribution on top: at each step the network outputs the parameters of a distribution for the next value, for example a mean and a standard deviation .
The important idea is the difference between training and prediction:
- Training (teacher forcing). The inputs at every step are the true previous values. Each step is a one-step-ahead prediction, and the loss is the negative log-likelihood of the true value.
- Prediction (ancestral sampling). After the forecast origin there are no true values. The model draws a value from its own distribution, feeds it back as the next input, and repeats. One run gives one possible future, a sample path. Many runs give many paths; their spread at each horizon is the forecast uncertainty.
Switch between the two phases. In training, every orange one-step prediction uses the true blue values as inputs. In prediction, press Draw one path and watch the model read its own last samples (the lags in yellow rings) after the forecast origin. Then draw 100 paths: the band widens with the horizon, because early random draws feed into later steps. Feed back the mean gives one dashed path with no spread. A fixed autoregressive model with a Gaussian head, , plays the role of the trained network.
Convolutions that only look back #
A convolution layer slides a small filter along the series. For forecasting it must be causal: the output at time may use but never , because that value does not exist at forecast time. A dilated convolution skips inputs: with dilation and kernel size , the output at reads . Stacking layers with dilations makes the window that one output can see, its receptive field, grow exponentially with depth while the number of weights grows only linearly. This is the design of WaveNet (van den Oord et al. 2016) and of the temporal convolutional network (TCN; Bai, Kolter and Koltun 2018).
Change the kernel size, the depth and the dilations. The orange output at time (the yellow line) depends on the aqua hidden values and on the yellow inputs; all other blue inputs cannot change it. Compare "1, 1, 1, …" with "1, 2, 4, 8, …" at the same depth. Then choose centered (the "same" padding of many libraries): magenta edges now reach inputs after time , which is leakage from the future.
With and dilations the readout gives : this answers question 1 of section 1. Four layers with dilation 1 would see only 5 values.
A causal convolutional network has 3 layers with kernel size and dilations 1, 3 and 9. How many consecutive time steps does its receptive field cover?
. The tempting 13 is the sum of the dilations without the factor and the . With and dilations that triple, the offsets with are exactly the numbers 0 to 26 written in base 3, so there are no holes.
Tokens for a transformer: time steps, patches or bins #
A transformer works on a sequence of tokens and compares every pair of tokens with attention (deep-learning lesson 09). With tokens, one attention layer computes scores. There are three common ways to make tokens from a window of length :
- one token per time step (): simple, but a single number carries little information, and long contexts are expensive;
- patches (PatchTST, Nie et al. 2023): cut the window into pieces of values with stride ; each piece becomes one token, so and the attention cost drops by about ;
- quantised values (Chronos, Ansari et al. 2024): divide by the mean absolute value of the context, then replace each value by the index of the nearest of a few thousand bins. The series becomes a "sentence" over a fixed vocabulary, and a language-model architecture can be trained on it.
Switch between the three kinds of tokens. With patches, change and and watch the number of tokens and the attention cost . The grey dashed part is the padding at the end (PatchTST repeats the last value times). With quantised values, lower the number of bins : the orange quantised values snap to the bin centres and the reconstruction error grows, but it always stays below .
At prediction time, what does DeepAR use as the input for step when it forecasts from origin ?
The true is unknown at forecast time. Feeding back a random draw (ancestral sampling) makes each run one sample from the joint distribution of the future; many runs give the fan. Feeding back the mean gives one path without uncertainty, and for a nonlinear network it is not even the mean forecast.
3. Definitions and main results #
3.1 Windows, scaling and output heads #
Data. A training set has one or more series. A training window at origin is the pair (context , target ), plus covariates: static ones (store id), ones known in advance (calendar, planned prices) and ones observed only in the past (weather measurements); see lesson 08. Windows from all series are mixed in mini-batches; this is a global model.
Per-window scaling. Series differ in level and spread, and one series changes its level over time. So each window is normalised with its own statistics, computed on the context only:
- mean scaling (DeepAR, Chronos): with (DeepAR uses for counts). It keeps zeros at zero, which matters for sales and solar power.
- standard scaling, called reversible instance normalisation (RevIN, Kim et al. 2022) when it is undone at the output: with the mean and standard deviation of the window; the forecast is , where is the network.
Proposition (scaling makes the forecaster equivariant). Let with any network . For every and , .
Proof.
- The mean of is , and its standard deviation is (because ).
- So : the network sees the same input.
- Then .
So a series in kilowatts and the same series in megawatts get the same forecast, in their own units. The same argument with shows that mean scaling gives for .
Output heads and losses. The head decides what the model estimates:
| Head | Training loss | What the minimiser estimates |
|---|---|---|
| point | MSE | the conditional mean |
| point | MAE | the conditional median |
| Gaussian | NLL | mean and variance |
| Student's t, negative binomial, mixtures | their NLL | heavy tails; counts; several shapes |
| quantile | pinball loss at levels (lesson 10) | the quantiles |
Why the Gaussian NLL estimates the mean and the variance
Fix the inputs and let be the target, with mean and variance . The expected loss is
because .
- For any , the only term with is , smallest at .
- With , the loss is . Its derivative in is , which is zero at (a minimum: negative before, positive after).
Channel independence. A multivariate series has variables (channels). A channel-independent model applies the same univariate network to each channel separately (shared weights, no information between channels). A channel-mixing model reads all channels together. Channel independence gives times more training windows and overfits less; it cannot use cross-channel effects. PatchTST is channel-independent; iTransformer and Chronos-2 mix channels with attention.
3.2 Recurrent networks and DeepAR #
The LSTM (long short-term memory) keeps a hidden state and a cell state . With input (a row vector) and the logistic sigmoid , in the notation of deep-learning lesson 08:
The forget gate decides how much of the old memory stays; the input gate decides how much of the candidate is written; the output gate decides what is shown as . With near 1 the memory lasts about steps; the interactive LSTM cell in deep-learning lesson 08 shows this. A GRU is a lighter variant with two gates.
Encoder–decoder. An encoder RNN reads the context and passes its final state to a decoder RNN, which produces the future steps (with known future covariates as decoder inputs). This sequence-to-sequence design was the standard neural forecaster before transformers.
DeepAR. Let be series at time , with covariates and scale . One RNN with shared weights runs over all series:
where is a likelihood with parameters : Gaussian for real values (, , so ), negative binomial for counts; the outputs are multiplied back by . The paper uses .
Theorem (teacher forcing is maximum likelihood). For an autoregressive model, . So minimising the sum of one-step negative log-likelihoods, each computed with the true previous values as inputs, is exactly maximum likelihood (see the probability-and-statistics track).
Proof. Apply the chain rule of probability times and take logarithms.
Theorem (ancestral sampling gives samples of the joint forecast distribution). Draw , then , and so on up to . Then is one sample from .
Proof. By induction on . For it is the definition. If the first draws have the joint law , the next draw multiplies it by , and the chain rule says that this product is .
So from paths you can estimate any summary: the quantiles at each horizon, the distribution of a sum over the horizon (total demand next month), or the probability of a stock-out. This is why DeepAR returns sample paths and not only marginal quantiles.
Echo state networks: a recurrent model trained without backpropagation
An echo state network (Jaeger 2001) fixes a random recurrent layer, the reservoir: , with scaled so that its spectral radius is below 1 (then the state forgets its initial value: the "echo state property"). Only the linear readout is trained, by ridge regression (linear-algebra lesson 12 for least squares). It is a fast way to get a nonlinear recurrent forecaster in NumPy, and you build one in the notebook. On one short series it does not beat simple baselines reliably, which is the general lesson of this section.
3.3 Temporal convolutional networks #
Definition. A causal dilated convolution with kernel and dilation maps an input sequence to
A network stacks such layers (with nonlinearities between them), with dilations .
Theorem (receptive field and causality). The output of layer at time depends only on the inputs with , where
It never depends on an input after .
Proof.
- Let be the set of offsets such that the output of layer at can depend on . For one layer, .
- Layer at time reads layer at times , . Each of those depends on inputs at offsets from its own time. So .
- All offsets are (every term is ): no future input is ever used. This is causality.
- The largest offset grows by per layer, so . The inputs from offset 0 to are consecutive time steps.
Corollary (doubling dilations). With , . The receptive field grows exponentially in the depth , but the number of weights per channel is only . To cover a context of length you need about layers.
Counting a real TCN. In the TCN of Bai et al. (2018), one residual block contains two causal dilated convolutions with the same dilation (with weight normalisation, ReLU, dropout and a convolution on the skip path when the widths differ). So a stack of blocks with dilations has . WaveNet stacks layers with and dilations : samples per stack.
Convolutions are fast to train (all time steps in parallel, unlike an RNN) and they see a fixed, known window. They cannot look further back than : choose the depth so that covers the longest pattern you need, for example a weekly cycle of 168 hours.
3.4 Linear and MLP models: DLinear and N-BEATS #
DLinear (Zeng, Chen, Zhang and Xu, AAAI 2023). Let be the moving-average matrix (kernel 25 in the reference code, the ends padded with copies of the first and last value). Split the context into a trend and a remainder , and apply one linear layer to each:
NLinear, from the same paper, subtracts the last value of the window before one linear layer and adds it back after.
Proposition (DLinear is a linear map of the window). The set of DLinear forecasters equals the set of all affine maps from to .
Proof.
- Every DLinear forecaster is affine: it equals with .
- Every affine map is a DLinear forecaster: take ; then .
So, fitted by plain least squares, DLinear and a linear regression on the window give the same forecast. The decomposition changes only the training: the penalty, the gradient-descent path and early stopping see different parameters. Its real message is different: a linear map of the last values is already a strong forecaster, because it can learn "the value one season ago, plus the trend over the last year".
Change the lookback, the forecast origin and the ridge strength. The orange forecast is a weighted sum of the yellow context window; the aqua line is its moving-average trend; the dashed line is the seasonal naive forecast. Below, each bar is the weight of one lag for the chosen horizon : the yellow bars are the lags with the same month as the target. Switch to Linear: with small the forecast barely moves, as the proposition says. Fitted in the browser by ridge regression on the "monthly demand" series.
In their experiments on nine long-horizon benchmarks, these one-layer linear models were more accurate than the transformer models they compared (FEDformer, Autoformer, Informer, Pyraformer, LogTrans). The authors argue that attention is permutation-invariant, so ordering information must be added back and is partly lost. Later transformers (PatchTST, iTransformer) beat DLinear on most of these benchmarks, especially the large ones, so the right conclusion is not "transformers are useless" but "always include a linear baseline". TSMixer (Chen et al. 2023) stacks MLPs that mix along time and along channels.
N-BEATS (Oreshkin et al. 2020) is a deep stack of fully connected blocks. Block reads its input and outputs a backcast (its explanation of the input) and a forecast . The next block gets the residual , and the final forecast is . In the interpretable version, the outputs are expansions in fixed bases: low-degree polynomials (trend) and Fourier terms (seasonality), like the decomposition of lesson 01. N-BEATS was more accurate than the winner of the M4 competition on the M4 data. N-HiTS (Challu et al. 2023) adds pooling of the input at several rates and interpolation of the outputs, for long horizons.
3.5 Transformers for time series #
Self-attention over tokens of width costs time and memory for the score matrix (deep-learning lesson 11). Early long-horizon models changed the attention: Informer (Zhou et al. 2021) keeps only the most informative queries ("ProbSparse", ); Autoformer (Wu et al. 2021) builds the trend–seasonal decomposition into the network and replaces attention by an auto-correlation over time lags.
PatchTST (Nie et al., ICLR 2023) changes the tokens instead:
- Normalise each channel's window (RevIN-style instance normalisation).
- Pad the window with copies of its last value and cut it into patches of length with stride :
- Map each patch linearly to a -dimensional token, add a position embedding, and run a transformer encoder.
- Flatten the output tokens and map them linearly to the forecasts. All channels share the weights (channel independence).
Since , the number of attention scores drops by a factor of about ; with , , there are 42 tokens. A patch of 16 values also carries local shape (a rise, a peak), which a single value does not.
iTransformer (Liu et al., ICLR 2024) inverts the roles: each variable's whole context becomes one token, and attention runs across variables. The Temporal Fusion Transformer (TFT; Lim et al. 2021) combines LSTM layers for local processing, attention for long-range patterns, gating, and a variable-selection network for static, known-future and observed-only covariates; it outputs quantiles, and its attention weights and variable weights are used to interpret the forecast.
3.6 State-space layers #
S4 and Mamba (deep-learning lesson 16) are layers built on a linear state-space recurrence , : the same form as the state equation of lesson 07, but without the noise terms and without a Kalman filter. They are deep layers trained by gradient descent; a time-invariant one can be computed as one long convolution (parallel training) or as a recurrence (cheap step-by-step prediction). In forecasting they are one more backbone, between RNNs and transformers in cost.
3.7 Foundation models for time series #
A time-series foundation model is a large network pretrained on many series from many domains (and often on synthetic series), and then used on new series. Zero-shot forecasting means: no gradient update on the target data; the model reads only the context of the target series at prediction time, like in-context learning in a language model. Most models can also be fine-tuned on the target data.
Step through the models by date, or click a dot. Each dot is one model, placed by how it turns the context into tokens (columns) and what its head predicts (rows); the colour is the backbone (blue encoder–decoder, aqua encoder-only, orange decoder-only, violet recurrent, dark grey tabular in-context model; a ring marks a mixture of experts). The panel gives a one-sentence summary and the source. As of 2026; versions change fast, so check the date of every claim.
The map shows three design choices:
- Input representation. Quantised values with a fixed vocabulary (Chronos); patches of values (TimesFM, Moirai, MOMENT, Chronos-Bolt, Chronos-2, TiRex, Sundial, Toto, Moirai 2.0); single values (Time-MoE); lag features (Lag-Llama); or tabular features for a pretrained tabular model (TabPFN-TS, which uses TabPFN-v2).
- Output head. A categorical distribution over bins, sampled token by token (Chronos); a point forecast (TimesFM 1.0, Time-MoE); a parametric distribution (Lag-Llama: Student's t; Moirai and Moirai-MoE: a mixture; Toto: a mixture of Student's t); quantiles for many steps at once (Chronos-Bolt, Chronos-2, TiRex, Moirai 2.0, TimesFM 2.5); or a generative flow-matching head that samples whole patches (Sundial).
- Architecture. Mostly transformers (encoder–decoder T5 for Chronos; encoder-only for Moirai and Chronos-2; decoder-only for TimesFM, Lag-Llama, Moirai 2.0, Sundial, Toto), sometimes with a sparse mixture of experts (Time-MoE, Moirai-MoE), a recurrent xLSTM (TiRex), or an in-context tabular model (TabPFN-TS). Chronos-2 adds "group attention" across related series and covariates, so it can use multivariate inputs and covariates zero-shot.
TimeGPT-1 (Garza et al. 2023) was presented by its authors as the first foundation model for time series.
Chronos tokenisation. Given a context :
- Mean scaling: (if , use ), and .
- Quantisation: choose bin centres evenly spaced on , so the spacing is ; the token of is the index of the nearest centre. Chronos uses bins plus two special tokens (PAD for padding and missing values, EOS for the end), a vocabulary of 4096.
- Model: a T5 encoder–decoder is trained with cross-entropy to predict the next token, like a language model.
- Forecast: sample tokens autoregressively, map each token back to its centre, multiply by .
Proposition (precision of the tokens). If , the value recovered from the token, , satisfies .
Proof. The scaled value lies in , so it is between two neighbouring centres at distance , and the nearest centre is at most away: . Multiply by .
Two consequences follow. Values outside are clipped to the end bins, so a strong trend that grows beyond 15 times the context's mean level cannot be forecast. And precision is relative to the level, not to the variation: a series near 1000 that moves by has and a bin width of about , so these movements fall into one or two bins and are lost (Ansari et al. 2024, section 5.7, discuss this limitation).
A context has mean absolute value . With Chronos tokenisation ( bins on ), what is the largest error made when a value is replaced by its bin centre?
The spacing of the centres is in scaled units, so the largest error is half of it, , times : about . The tempting 0.0037 forgets to multiply by ; 0.37 is the full bin width , not half of it.
Evaluation as of 2026. Pretrained models are compared on public benchmarks such as GIFT-Eval (Aksu et al. 2024: 23 datasets, about 144,000 series, with a separate non-leaking pretraining corpus) and fev-bench (Shchur et al. 2025: 100 tasks, 46 with covariates, with bootstrapped confidence intervals). Three cautions:
- Contamination. If a model's pretraining data overlap with a benchmark's test data, the "zero-shot" score is really an in-domain score. The Chronos paper itself reports its in-domain benchmark separately from its zero-shot benchmark; GIFT-Eval publishes a non-leaking pretraining set for this reason.
- Ranks change monthly. New versions appear several times a year (for example TimesFM 1.0 in 2023 and the 2.5 checkpoint in 2025). Name the version and the date whenever you report a result.
- Your data are not the benchmark. Always backtest the model on your own series with a rolling origin (lesson 03) against seasonal naive, ETS (lesson 04) and a tuned boosting model (lesson 08).
Answers to section 1. (1) 16, shown in section 2. (2) The linear layer: in Zeng et al. (2023), DLinear and NLinear were more accurate than the long-horizon transformers they compared on all nine benchmarks. (3) Two values closer than about (one bin width) can fall into the same bin; each is recovered within about .
DLinear and an ordinary linear regression on the same window are both fitted by unregularised least squares on the same training windows. How do their forecasts compare?
is linear in , and any is reached with . Same model class and same loss give the same best fit. The moving average runs inside the context window, so it uses no future values; the split only changes training with penalties or gradient descent.
A team says their pretrained model forecasts your store's sales "zero-shot". What does this mean?
Zero-shot refers to the target data: no training (no gradient steps) on it. The model may well have seen retail data in pretraining (that can even overlap with public benchmarks: contamination), and it always needs the context of the series it forecasts.
4. Worked example #
(a) Receptive field and causality. Take and dilations (one convolution per layer).
The output at depends on : offsets 0 to 30. The offsets are with . The largest is , and every number from 0 to 30 has this form. For example, for 29 take the largest coefficient that fits at each dilation, from the top: , , , , so and ✓. No offset is negative, so no input after is used. As TCN residual blocks (two convolutions per block, same dilations), the receptive field becomes .
(b) Patches. PatchTST with , , :
Attention compares pairs instead of : times fewer.
(c) Tokenising four values. Context . To compute by hand, use a toy grid of centres on (spacing ) instead of the real one.
- Scale: , so .
- Nearest centres: ; (distance , versus to ); (distance , versus to ); . With centres numbered from 0 at , the tokens are .
- Back to values: . The errors are , all below the bound .
- With the real grid ( on ) the bound is ; the largest error for these four values is .
(d) One LSTM step. Scalar LSTM with input , previous , , and weights chosen by hand: , , , (the terms vanish because ).
- Gates: , , , .
- Cell: .
- Hidden state: .
The old memory survives at 88% because the forget-gate bias is 2.
5. In code #
NumPy checks the four parts of the worked example, and the DLinear proposition on the "monthly demand" series.
import numpy as np
# (a) receptive field of stacked causal dilated convolutions, by an impulse test
def causal_conv(x, w, d):
"""y[t] = sum_j w[j] * x[t - d*j] (zero padding on the left: only the past is used)."""
y = np.zeros(len(x))
for j, wj in enumerate(w):
y[d * j:] += wj * x[: len(x) - d * j]
return y
rng = np.random.default_rng(0)
k, dil, T = 3, [1, 2, 4, 8], 64
W = [rng.normal(size=k) for _ in dil]
def net(x):
for w, d in zip(W, dil):
x = np.tanh(causal_conv(x, w, d))
return x
t = 40
seen = [s for s in range(T) if net(np.eye(T)[s])[t] != net(np.zeros(T))[t]]
print(len(seen), min(seen), max(seen)) # 31 10 40 -> r = 1 + (k-1)*15 = 31, nothing after t
# (b) Chronos-style tokenization: mean scaling + uniform bins on [-15, 15]
def tokenize(ctx, B=4094, lo=-15., hi=15.):
s = np.mean(np.abs(ctx)) or 1.0
centres = np.linspace(lo, hi, B)
ids = np.abs(ctx[:, None] / s - centres[None, :]).argmin(axis=1)
return ids, s, centres
ctx = np.array([12., 15., 9., 14.])
ids, s, c = tokenize(ctx, B=13, lo=-3., hi=3.) # the toy grid of the worked example
print(s, ids, c[ids] * s) # 12.5 [8 8 7 8] [12.5 12.5 6.25 12.5 ]
ids, s, c = tokenize(ctx) # the real grid: B = 4094
print(np.abs(c[ids] * s - ctx).max().round(4), round(15 * s / 4093, 4)) # 0.0436 0.0458
# (c) one LSTM step with scalar weights (gate order i, f, g, o)
sig = lambda z: 1 / (1 + np.exp(-z))
x, h, c0 = 2.0, 0.0, 1.0
i, f = sig(1 * x - 1), sig(0 * x + 2)
g, o = np.tanh(0.5 * x), sig(0 * x + 0)
c1 = f * c0 + i * g
print(np.round([i, f, g, o, c1, o * np.tanh(c1)], 3)) # [0.731 0.881 0.762 0.5 1.438 0.447]
# (d) DLinear and a plain linear map on the window give the same least-squares fit
tt = np.arange(1, 121)
y = 100 + 0.5 * tt + 10 * np.sin(2 * np.pi * tt / 12) + np.random.default_rng(0).normal(0, 3, 120)
Lw, H, kma = 24, 12, 23
A = np.zeros((Lw, Lw)) # moving average, ends padded by copies
for r in range(Lw):
for q in range(r - kma // 2, r + kma // 2 + 1):
A[r, min(max(q, 0), Lw - 1)] += 1 / kma
X = np.array([y[s:s + Lw] for s in range(108 - Lw - H + 1)])
Y = np.array([y[s + Lw:s + Lw + H] for s in range(108 - Lw - H + 1)])
one = np.ones((len(X), 1))
F_lin = np.hstack([X, one])
F_dl = np.hstack([X - X @ A.T, X @ A.T, one]) # remainder part, trend part, bias
ctx = np.r_[y[108 - Lw:108]]
f_lin = np.r_[ctx, 1] @ np.linalg.lstsq(F_lin, Y, rcond=None)[0]
f_dl = np.r_[ctx - A @ ctx, A @ ctx, 1] @ np.linalg.lstsq(F_dl, Y, rcond=None)[0]
print(np.abs(f_lin - f_dl).max() < 1e-6) # True: same function class, same fit
scale = np.mean(np.abs(y[12:108] - y[:96])) # MASE scale: in-sample seasonal naive
print(round(np.mean(np.abs(f_lin - y[108:])) / scale, 2),
round(np.mean(np.abs(y[96:108] - y[108:])) / scale, 2)) # 0.51 1.2
The window here is 24 months, so the moving-average kernel is 23 (the largest odd number not above ). The linear model's MASE of 0.51 against 1.2 for seasonal naive comes from one origin only; the notebook repeats it with a rolling origin. The notebook builds every model of this lesson in NumPy (no deep-learning library), and an optional cell shows how to call a pretrained model in Colab.
6. Where it shows up #
- Retail and supply chains. DeepAR-style global models with negative binomial or Student's t heads forecast demand for many products; the sample paths give the distribution of total demand over a lead time, which sets safety stock. In the M5 competition (lesson 08) most top entries used gradient boosting (LightGBM), and some of them combined it with neural networks.
- Energy and traffic. Hourly load, solar and wind power, and road occupancy are the standard long-horizon benchmarks (electricity, traffic, weather) on which DLinear, PatchTST, iTransformer and N-HiTS were tested.
- Cloud and observability. Toto (Datadog, 2025) is pretrained on monitoring metrics and comes with the BOOM benchmark of observability series; forecasts and their intervals drive capacity planning and alerts (lesson 11).
- ML for science: hydrology. A single LSTM trained on 531 river basins of the CAMELS data set, with meteorological inputs and static catchment attributes, predicted river flow better than hydrological models calibrated basin by basin (Kratzert et al. 2019). This is the "global model" idea in a physical science.
- ML for science: weather and climate. Learned weather models are deep autoregressive forecasters of whole atmospheric fields: they apply the same network step after step, as in ancestral sampling, and ensembles of such runs give probabilistic forecasts (see the ml-for-science track).
- Forecasting tools. Pretrained models are available in libraries such as AutoGluon-TimeSeries (Chronos) and GluonTS (DeepAR, TFT and others), so a zero-shot forecast is often the first thing a team tries.
7. Common mistakes #
- A non-causal convolution or moving average. "Same" padding in a convolution, or a centred moving average, uses values after . The backtest looks excellent and the model fails in production. Pad on the left only.
- Scaling with statistics that include the future. Normalise each window with the context only, and invert the scaling on the output. Scaling with the whole series' mean and standard deviation is leakage.
- Counting one convolution per TCN block. A TCN residual block has two convolutions, so .
- Calling the "mean fed back" path a probabilistic forecast. Only sample paths (or a quantile or distribution head) give uncertainty, and for a nonlinear model the fed-back mean is not even the mean.
- Comparing a deep model only with other deep models. Include seasonal naive, ETS or ARIMA, a linear model on the window and a boosted model. Many published gains disappear against a tuned simple baseline.
- Trusting a zero-shot score on a benchmark that was in the pretraining data. Check the pretraining corpus, prefer benchmarks with non-leaking splits, and backtest on your own data.
- Feeding a trending series with a large offset to a mean-scaled tokeniser without thinking. Precision is about per bin, relative to the level ; small movements around a large level are lost, and values beyond are clipped.
- Training a large network on one short series. With 100 monthly values there are fewer than 100 training windows. A model with thousands of weights will fit noise; use a classical model, a linear model, or a pretrained model zero-shot.
8. Check yourself #
- A TCN has 3 residual blocks with kernel size 3 and dilations 1, 2 and 4 (two convolutions per block). What
is its receptive field? How many blocks would you need for a weekly cycle in hourly data (168 steps)?
Answer
. With blocks and doubling dilations, : gives , gives . So 6 blocks. - RevIN computes and of the context, feeds to the network and outputs
. Context ; the network outputs . What is the forecast?
What is it if every context value is increased by 100?
Answer
, . Forecast . After adding 100 the normalised input is the same, so the network gives the same output and the forecast is : the forecaster is shift-equivariant. - PatchTST with , , : how many tokens, and how many attention scores per head and
layer, compared with one token per time step?
Answer
(the "PatchTST/64" of the paper). scores instead of : 64 times fewer. - Why can a DeepAR model trained on 10,000 products forecast a new product that has only 8 weeks of history,
while an ARIMA model cannot?
Answer
DeepAR is a global model: its weights are shared across all series and learned from all of them, and the per-series scale puts the new series on the common scale. It only needs a short context to set the hidden state. ARIMA is a local model: its parameters must be estimated from the 8 values of the new series, which is far too few. - Write the DLinear forecast as one matrix times the window, and explain why the decomposition can still
change the result when the model is trained with weight decay.
Answer
, so . Weight decay penalises , which is not a function of alone: two parameter pairs with the same have different penalties. So the penalised optimum (and the path of gradient descent) depends on the parametrisation, while the set of reachable forecasters does not. - A vendor reports that its foundation model beats all others on a public benchmark. List three questions you
ask before you use it.
Answer
Was any of the benchmark's test data in the pretraining corpus (contamination)? Which model version and which date does the result refer to, and are the differences larger than their confidence intervals? How does it do on a rolling-origin backtest of *my* series against seasonal naive, ETS and a boosted model, for my horizons and my metric?
What is a causal convolution, and why must a forecaster use one?
Its output at time uses only inputs at times (padding on the left only). At forecast time the future values do not exist, so any dependence on them is leakage.
Give the receptive field of causal convolution layers with kernel size and dilations .
. With : .
Describe DeepAR in one sentence.
A global autoregressive RNN that outputs the parameters of a likelihood (Gaussian, negative binomial) at each step, is trained by maximum likelihood with teacher forcing, and forecasts by ancestral sampling.
Teacher forcing versus ancestral sampling: what is fed back at the next step?
Teacher forcing (training) feeds the true previous value; ancestral sampling (prediction) feeds a value drawn from the model's own predicted distribution.
What does per-window scaling such as RevIN do, and what must you not do with it?
It normalises each context with its own mean and standard deviation and undoes this on the forecast, so the model is equivariant to shift and scale. Never compute the statistics with values after the forecast origin.
PatchTST with , , : how many tokens?
, so attention computes about 64 times fewer scores than with 336 tokens.
What is channel independence?
Each variable of a multivariate series is forecast by the same univariate model with shared weights, without information flowing between variables.
How does Chronos turn a real value into a token?
Divide by , the mean absolute value of the context, then take the index of the nearest of about 4,000 uniform bin centres on .
What does "zero-shot forecasting" mean?
The pretrained model makes forecasts for a series without any parameter update on that series' data; it only reads the series' context.
What is benchmark contamination for a foundation model?
Overlap between the model's pretraining data and the benchmark's test data, which turns a "zero-shot" score into an in-domain score and inflates it.
9. Interview angle #
- "Would you use a transformer for this forecasting problem?" — It depends on the data: with one or a few short series, no (ETS, ARIMA, a linear model or a pretrained model zero-shot); with many related series, long contexts and covariates, a global deep model can help. In every case, compare with seasonal naive and a boosted model in a rolling-origin backtest.
- "Why can a linear model beat a transformer on long-horizon benchmarks?" — The series are dominated by trend and seasonality, which a linear map of the window captures; point-wise tokens carry little information and attention is permutation-invariant; the transformers overfit. Patching and channel independence (PatchTST) fixed much of this.
- "How do you get prediction intervals from a neural forecaster?" — A distribution head trained by NLL (DeepAR), a quantile head trained with the pinball loss (TFT, Chronos-Bolt), sample paths from ancestral sampling, or conformal intervals on top of any point forecaster (lesson 10).
- "Compute the receptive field of this TCN." — per convolution; count both convolutions in each residual block.
- "How do time-series foundation models tokenise numbers?" — Chronos: mean scaling plus uniform bins, then a language model with cross-entropy. Most others: patches of scaled values mapped linearly to embeddings, with a quantile, distribution or point head.
10. Practice #
The notebook for this lesson runs in Colab with NumPy and matplotlib only. It has five exercises, each with a check cell and a folded solution:
causal_dilated_conv(x, w, d)andreceptive_field(k, dilations), checked with an impulse response: only the inputs inside the receptive field change the output, and none after .lstm_cell(x, h, c, W, U, b): one forward step of an LSTM, checked against the worked example and a vector case.- An echo state network (a fixed random reservoir with a ridge-regression readout) on the "monthly demand" series, backtested with a rolling origin against seasonal naive.
dlinear_fit(y, L, H)by least squares with the moving-average split, compared with seasonal naive by rolling origin, and checked against plain linear regression.chronos_tokenize(context, n_bins, limits)anddetokenize, with the error bound and the clipping of out-of-range values.
11. Watch and read #
Papers (all free on arXiv).
- Salinas, Flunkert and Gasthaus, DeepAR: Probabilistic forecasting with autoregressive recurrent networks (2017; IJF 2020).
- Bai, Kolter and Koltun, An empirical evaluation of generic convolutional and recurrent networks for sequence modeling (2018), the TCN paper; van den Oord et al., WaveNet (2016).
- Oreshkin et al., N-BEATS (ICLR 2020); Challu et al., N-HiTS (AAAI 2023).
- Zeng, Chen, Zhang and Xu, Are transformers effective for time series forecasting? (AAAI 2023), the DLinear paper; Chen et al., TSMixer (2023).
- Zhou et al., Informer (AAAI 2021); Wu et al., Autoformer (NeurIPS 2021); Lim et al., Temporal Fusion Transformers (IJF 2021).
- Nie et al., A time series is worth 64 words (PatchTST) (ICLR 2023); Liu et al., iTransformer (ICLR 2024).
- Kim et al., Reversible instance normalization (RevIN) (ICLR 2022).
- Foundation models: TimeGPT-1, Lag-Llama, TimesFM, Moirai, MOMENT, Chronos, Time-MoE, Moirai-MoE, TabPFN-TS, Sundial, Toto, TiRex, Chronos-2, Moirai 2.0. Model cards: Chronos-Bolt, TimesFM 2.5.
- Benchmarks: Aksu et al., GIFT-Eval (2024) and its leaderboard; Shchur et al., fev-bench (2025) and its leaderboard (both accessed November 2026; ranks change often).
- Survey: Benidis et al., Deep learning for time series forecasting: tutorial and literature survey (ACM Computing Surveys 2022). Library: Alexandrov et al., GluonTS (JMLR 2020).
- Hydrology: Kratzert et al., Towards learning universal, regional, and local hydrological behaviors via machine learning applied to large-sample datasets (HESS 2019).
- Hyndman and Athanasopoulos, Forecasting: Principles and Practice, 3rd ed., free online: the benchmarks and evaluation that every deep model must beat.
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.