A sentence arrives pre-chopped into words. A photograph arrives on a bounded grid. A time series arrives as an unbounded stream of real numbers with no alphabet at all — which is exactly why it was the last modality to get a foundation model, and why the three papers here are really three answers to one question: what is a token?
You own forecasting at a mid-size retailer. Forty thousand products, each with a weekly demand history. Every Sunday night a job wakes up, and for each of those forty thousand series it fits a model: an exponential smoothing state-space model, or an ARIMA whose orders are chosen by a search over a grid. Forty thousand independent fits. Forty thousand sets of parameters. The job takes six hours and it is the single most brittle thing in your stack, because when a series is new — a product launched on Tuesday — there is nothing to fit.
Down the hall, a colleague working on language models has not fitted anything to anything in two years. She downloads a checkpoint, types a sentence, gets an answer. The model was trained once, by someone else, on a corpus she has never seen, and it works on her sentence because her sentence is made of the same stuff as the corpus: words.
The obvious question — obvious enough that a dozen groups asked it simultaneously in 2023 — is why forecasting cannot work that way. Train one model, once, on a huge pile of time series from every domain anyone has ever measured. Ship the weights. When a new series arrives, feed it in and read the forecast out. No fitting. No parameter search. No six-hour Sunday job.
Language got a foundation model in 2018. Vision got one in 2021. Audio got one in 2022. Time series — arguably the oldest quantitative modelling problem in the world, with a century of statistical machinery behind it — did not get a credible one until 2023. That lag is not an accident of attention. It is a consequence of what a time series actually is.
Take the thing that makes a language model possible and try to find its analogue.
| What a foundation model needs | Language has it | Images have it | Time series… |
|---|---|---|---|
| A finite alphabet of atoms | ~50,000 subword tokens, fixed forever | Pixels in [0, 255], patches of 16×16 | None. The atoms are real numbers on an unbounded line |
| Scale-free inputs | "cat" is "cat" in every document | Pixel values are bounded by construction | No. One series lives near 10−3, the next near 106 |
| A single notion of "next" | The next word | Not applicable — images are not sequential | Ambiguous. Next hour? Next year? Both, in one corpus |
| Fixed input dimensionality | One stream of tokens | 3 colour channels, always | No. 1 variate, or 7, or 862, task by task |
| Semantics carried by the atom | "catastrophe" means something alone | A patch of sky is recognisable alone | No. The number 37.2 means nothing without context |
Read the last row twice, because it is the deepest one. In language, a token carries meaning by itself — that is why an embedding table works at all. In a time series, a single observation carries almost nothing. 37.2 could be a body temperature in Celsius (perfectly normal), a stock price, a wind speed in metres per second (a storm), or a warehouse's Tuesday order count. Meaning lives in the local shape — is it rising, is it oscillating, did it just jump — and shape is a property of a window, not a point.
Before any machinery, look at what each proposal literally does to the same forty-eight numbers. The simulation below takes one series and tokenises it three ways. Watch what happens to the token count, and watch what each token is.
The same 48-point series, tokenised three ways. Point is the naive choice most early time-series Transformers made. Patch is PatchTST and TimesFM. Bin is Chronos. Read the token count in the header — it is the number the attention cost squares.
Three things to notice. First, point tokenisation keeps every number but produces the most tokens, and attention cost grows with the square of that count. Second, patching collapses sixteen numbers into one vector — the token count drops by a factor of the stride, and each token now carries a shape rather than a value. Third, binning does something categorically different: it throws away the real line entirely and replaces each number with an integer, at which point the sequence is literally a sentence, and any language model will eat it without modification.
| Model | Year | A token is… | Objective | Size | Pretraining corpus |
|---|---|---|---|---|---|
| PatchTST Nie, Nguyen, Sinthong, Kalagnanam | 2022 | A window of P = 16 consecutive values, stride S = 8 | MSE on the horizon; or masked patch reconstruction | ~1M (3 layers, D = 128) | One dataset at a time — not a foundation model, but the tokenizer everything else uses |
| TimesFM Das, Kong, Sen, Zhou (Google) | 2023 | An input patch of 32 values; the output patch is 128 | MSE on the next output patch, decoder-only | 200M (20 layers, d = 1280, 16 heads) | O(100B) timepoints: Google Trends, Wiki pageviews, M4, plus synthetic |
| Chronos Ansari, Stella, Türkmen et al. (Amazon) | 2024 | A bin index in a 4096-word vocabulary | Cross-entropy over bins — regression by classification | 20M – 710M (T5 family, unmodified) | 28 public datasets, 10M TSMixup augmentations, 1M synthetic GP series |
| MOMENT Goswami et al. (CMU) | 2024 | A non-overlapping patch of 8 values | Masked patch reconstruction, 30% masked | 40M / 125M / 385M | The Time Series Pile — assembled from public archives |
| Moirai Woo et al. (Salesforce) | 2024 | A patch whose size depends on the frequency | Negative log-likelihood of a mixture distribution | 14M / 91M / 311M | LOTSA — over 27B observations across nine domains |
PatchTST is in this table under slightly false pretenses and it is important to say so up front: PatchTST is not a foundation model. It is trained per dataset, evaluated per dataset, and its paper never claims otherwise. It is here because it contributed the tokenizer — patching plus channel independence — that TimesFM, MOMENT and Moirai all adopted. The genealogy is explicit: TimesFM's own text says "Inspired by the success of patch based modeling in the recent long horizon forecasting work [24] we also choose to break down the time-series into patches," where [24] is PatchTST.
Zero-shot in this literature means: no gradient step is taken on the target series or its dataset. You load weights, you feed a context window, you read a horizon. It does not mean the model has never seen a series that looks like yours — on the contrary, the whole bet is that it has seen millions of series that look a bit like yours, which is what makes contamination such a live worry (Chapter 6 returns to it with teeth).
| Setting | Fits per new series | Data needed from you | Latency at deploy | Cold start? |
|---|---|---|---|---|
| Local statistical (ARIMA, ETS) | One fit per series | The series itself, long enough to identify orders | Seconds to minutes per series | Impossible — nothing to fit |
| Global deep (DeepAR, PatchTST) | One training run per dataset | The full dataset, plus a train/val split | Milliseconds after training | Works only if the new series joins a trained panel |
| Foundation model, zero-shot | Zero | A context window. That is all | Tens of ms to a few seconds | Yes — day-one forecasts |
| Foundation model, fine-tuned | One short run per dataset | A modest slice of the dataset | Same as zero-shot afterwards | Yes, then improves |
That last row matters more than it looks. Chronos's own experiment is blunt about it: they fine-tuned the smallest useful model, Chronos-T5 (Small, 46M), on individual held-out datasets for 1000 steps, and it "takes the top spot on Benchmark II overall, overtaking both larger (zero shot) Chronos models and the best task-specific models." A thousand steps. If you have any data at all, zero-shot is a floor, not a ceiling.
It is tempting to argue about which model wins on which metric. Practitioners who adopted these models mostly did not adopt them for accuracy. They adopted them for what the diagram below does to an operations page.
The cost is real and Chapter 6 will price it: inference is slower per series than evaluating a fitted ETS model, these models take no covariates, and the failure modes are unfamiliar. But the operational simplification is why this line of work matters even where the accuracy gain is a wash.
Chapter 0 asserted that time series lacks a vocabulary. This chapter makes that concrete, because each missing property maps to a specific engineering decision in each of the three papers — and if you understand the four obstacles you can practically re-derive the models.
Start with what a language model does on its very first layer. The token cat has an integer id, say 4826, and that id indexes a row of an embedding matrix E of shape (V, d) — a lookup, nothing more. The row was learned. Crucially, every time cat appears anywhere in the corpus it retrieves the same row, so the model accumulates evidence about that atom across billions of occurrences.
Now try it on a series. What is the id of 37.2? There isn't one; the reals are uncountable. You could round — and hold that thought, because that is exactly what Chronos does — but round to what precision, and relative to what? 37.2 in a body-temperature series is routine; 37.2 in a series whose values are usually 0.001 is a catastrophic spike.
So the first layer cannot be a lookup. It has to be a projection: a learned linear map from a vector of raw values into the model dimension. Which immediately raises the question of what goes into the vector.
| Choice | First layer | Tokens for L = 512 | Attention cells | What one token means |
|---|---|---|---|---|
| One token per timepoint | Linear: R1 → RD | 512 | 262,144 | A single scalar — almost nothing |
| Patch of 16, stride 8 | Linear: R16 → RD | 64 | 4,096 | A local shape: level, slope, wiggle |
| Patch of 32, no overlap | Linear: R32 → RD | 16 | 256 | A longer motif |
| Quantized bin (Chronos) | Lookup: id → row of E | 512 | 262,144 | "The scaled value is about 0.87" |
The pointwise row is the design that early time-series Transformers — Informer, Autoformer, FEDformer — used, and it is the one PatchTST attacks. A linear map from R1 into R128 is a rank-one operation: every token embedding is the same vector scaled by the value. Whatever structure attention then discovers, it had to discover from scaled copies of a single direction. PatchTST's ablation is stark: strip patching out, keep everything else, and several configurations do not merely get worse — they run "out of GPU memory (NVIDIA A40 48GB) even with batch size 1."
Suppose your pretraining corpus contains hourly electricity load in kilowatt-hours (values around 3,000), daily website conversions (values around 12), and a sensor's drift in volts (values around 0.0004). All three enter the same batch, hit the same first linear layer, and their gradients are summed into the same weights.
Written out, the first layer computes Wpxpatch. If xpatch has entries near 3,000 the pre-activation is near 3,000·‖W‖; if near 0.0004 it is seven orders of magnitude smaller. One of the two produces gradients that dominate; the other produces gradients that are numerically invisible. No amount of training fixes this, because the problem is in the inputs, not the parameters.
The fix everyone uses is instance normalisation: normalise each series (or each context window) by its own statistics before it enters the model, then invert the transform on the output. There are three flavours in these papers and the differences matter.
| Scheme | Transform | Used by | Property worth knowing |
|---|---|---|---|
| Standardisation (RevIN) | x̃ = (x − μ) / σ, per window | PatchTST, MOMENT, TimesFM (mean and std of the first input patch) | Centres and rescales; destroys the meaning of zero |
| Mean scaling | x̃ = x / s, with s = (1/C) ∑|xi|, no centring | Chronos | Preserves zeros. Zero sales stays zero; zero solar output at night stays zero |
| Min-max | x̃ = (x − min) / (max − min) | Rare here | Bounded output, but one outlier compresses everything else |
Chronos's justification for mean scaling is one line and it is a genuinely good piece of domain thinking: "An attractive feature of mean scaling is that it preserves zero values in the time series, which are often semantically meaningful, such as zero sales for a product or zero solar energy generation at night." Subtracting a mean turns "we sold nothing" into "we sold 1.4 below average", which is a different fact.
Work one instance by hand. Take a context of eight weekly demand values:
Mean scaling sets m = 0 and s = the mean absolute value: (10 + 12 + 8 + 14 + 11 + 15 + 9 + 13) / 8 = 92 / 8 = 11.5. Dividing through:
Now multiply every original value by 1,000 — a different unit, a different product, a different domain. The mean absolute value becomes 11,500, and x̃ comes out identical to four decimal places. That is the whole point: the model never sees the unit. It sees shape. Keep this exact vector; Chapter 4 turns it into tokens.
Three real-shaped series with wildly different magnitudes. Toggle the normalisation and watch the range readout under each panel — that range is literally what the model's first linear layer receives. Note what happens to the dashed zero line under standardisation versus mean scaling.
Drag the sparsity slider up and watch series 3 fill with zeros. Under mean scaling the zeros stay pinned to the zero line no matter how sparse the series gets. Under standardisation they lift off it, and they lift further the sparser the series becomes — the mean of a mostly-zero series is small, but the standard deviation is smaller still, so the zeros drift to a large negative z-score. Chapter 4 shows the exact failure this causes once you then quantize.
A language model's notion of "next" is fixed by the tokenizer. A forecaster's is fixed by whoever installed the sensor. Within one pretraining corpus you have 5-minute traffic counts, hourly electricity, daily page views, weekly sales, monthly tourism, and yearly macroeconomic indicators — and the seasonal period, the thing a forecaster most needs to detect, is a different integer in each: 288, 24, 7, 52, 12, and none.
| Response | Who | Mechanism | Cost |
|---|---|---|---|
| Ignore frequency entirely | Chronos, TimesFM | The model must infer the period from the context. Frequency is never an input | Needs a context long enough to contain several periods — a hard constraint at high frequency |
| Balance the mixture | TimesFM | The loader gives "equal weights to the groups: hourly + sub-hourly, daily, weekly, and monthly"; 80% real data, 20% synthetic | A curation decision that is invisible at inference but shapes everything |
| Condition on frequency | Moirai | Patch size is chosen by frequency — larger patches for high-frequency data, smaller for low — with a separate projection layer per patch size | You must know and supply the frequency; more parameters |
TimesFM's context-length choices show how sharp the constraint is in practice. It trains "with a maximum context length of 512 whenever the length of the time-series allows that. For weekly granularity we do not have sufficiently long time-series; therefore a maximum context length of 256 is used. For the same reason, a maximum context length of 64 is used while training on ≥ monthly granularity data." A 64-step context on monthly data is five years and four months — barely five annual cycles. There is no way around it: the data simply does not exist.
A multivariate series has M simultaneous measurements per timestep: the Weather dataset has 21, ETTh1 has 7, Traffic has 862. The obvious instinct is to let the model see all channels at once so it can exploit cross-channel structure — if road sensor 41 spikes, sensor 42 spikes eight minutes later.
The obvious instinct is mostly wrong, and PatchTST is where that became consensus. Its second contribution is channel independence: split the M-variate series into M univariate series, run each through the same shared Transformer independently, and never let them attend to each other.
Why does throwing away cross-channel information help? Three reasons that stack.
One — the parameter count of channel mixing scales with M, and M is dataset-specific. A channel-mixing first layer maps RM into RD, so its shape depends on the dataset. A channel-independent one maps RP into RD, and P is your hyperparameter, identical everywhere. This alone is why every foundation model in the table adopted it: you cannot pretrain across datasets with different M unless the weights are M-agnostic.
Two — it multiplies the effective dataset size by M. ETTh1 with 7 channels is one 7-channel training sequence per window under mixing, but seven univariate sequences per window under independence. PatchTST's Figure 7 shows the consequence directly: channel mixing "quickly overfits the data", while channel independence "contributes to a quicker convergence as more training data is available."
Three — the cross-channel signal is often weaker than the within-channel signal. For long-horizon forecasting, the dominant structure is each channel's own seasonality and trend. Spending capacity on cross-channel attention buys a small gain at a large overfitting risk.
| Obstacle | PatchTST | Chronos | TimesFM |
|---|---|---|---|
| No vocabulary | Patch of 16, linear projection | Invent one: 4096 bins | Patch of 32, MLP residual block |
| Scale | RevIN standardisation | Mean scaling (zero-preserving) | Standardisation using the first patch's statistics |
| Frequency | Not applicable — one dataset at a time | Infer from context; context length 512 | Balance the loader; cap context by granularity |
| Channels | Channel independence — the contribution | Univariate only; multivariate listed as future work | Univariate only; covariates listed as a limitation |
Look at the bottom row. Two of the three foundation models simply declined the multivariate problem. Chronos's discussion says so plainly: "we have focused on univariate forecasting of uniformly-spaced time series since it constitutes the most common of real-world time series use-cases", and lists covariates and multivariate forecasting as open. TimesFM's limitations section says "the model is not pretrained with covariates as one of the key challenges is finding large volumes of pretrained data with meaningful covariates." When you deploy one of these and it ignores your promotion calendar, that is not a bug. It is the scope.
The title of the PatchTST paper is "A Time Series is Worth 64 Words." That is not a flourish; it is the arithmetic result of the paper's central choice, and by the end of this chapter you will be able to produce the number 64 yourself from the look-back window and two hyperparameters.
The setup. You are given a multivariate series with look-back window L — L past timesteps — and asked to forecast T future steps. Each timestep xt is a vector of dimension M. Formally: given (x1, …, xL), predict (xL+1, …, xL+T).
Before anything else, the M-variate input is split into M univariate series, each of shape (1, L). Each goes through the backbone independently, and the backbone's weights are shared across all of them. In tensor terms this is a reshape that folds the channel axis into the batch axis:
That single line is the whole of channel independence as an implementation. A batch of 32 samples from ETTh1, which has M = 7, becomes 224 univariate sequences. The Transformer never learns that there were seven of anything.
Each univariate window is instance-normalised — zero mean, unit standard deviation, with the statistics stashed so they can be added back to the output — and then cut into patches. Two hyperparameters govern the cut:
If S < P the patches overlap; if S = P they tile exactly; if S > P you skip data. PatchTST's default is P = 16, S = 8 — fifty percent overlap.
The number of patches is given in the paper as
and the "+ 2" deserves a full explanation, because it looks like a fudge and is not. Count carefully. Patches start at index 1, 1 + S, 1 + 2S, … The last patch that fits entirely inside a window of length L starts at 1 + kS where kS + P ≤ L, so k = ⌊(L − P)/S⌋, giving k + 1 patches. The extra one is the padded tail: PatchTST appends S copies of the final value xL before patching, so one more patch fits, and it is anchored on the most recent observation. That is the "+ 2" — (k + 1) real patches plus 1 padded patch.
Do the two configurations the paper actually ships. PatchTST/42 uses the default long-horizon look-back L = 336 — fourteen days at hourly resolution:
PatchTST/42 — the default configuration, by handL = 336, P = 16, S = 8 L - P = 336 - 16 = 320 (L - P) / S = 320 / 8 = 40 # exact; no flooring needed here floor(...) = 40 N = 40 + 2 = 42 # hence the name PatchTST/42 # and the larger variant: L = 512, P = 16, S = 8 (512 - 16) / 8 = 496 / 8 = 62 N = 62 + 2 = 64 # "A Time Series is Worth 64 Words"
There is the title. Sixty-four words is L = 512 with P = 16 and S = 8. Now the payoff, which is why anyone cares:
what patching buys — attention cost# self-attention builds an N x N matrix. Cost is quadratic in the TOKEN count. pointwise, L = 512 : 512 * 512 = 262,144 attention cells patched, N = 64 : 64 * 64 = 4,096 attention cells --------------------- 64x fewer # the reduction factor is (L/N)^2 ~ S^2 for large L, since N ~ L/S. # S = 8 -> 64x. S = 16 -> 256x. S = 32 -> 1024x.
The paper measures the wall-clock consequence rather than only the FLOP count: "By setting patch length P = 16 and stride S = 8 with L = 336, the training time is significantly reduced as much as 22 time on large datasets." Twenty-two times faster, measured, on the Traffic dataset with its 862 channels.
This is the part that separates reading the paper from being able to write it. Track one univariate series through the whole forward pass with PatchTST/42 numbers and D = 128:
| Stage | Operation | Shape out | Note |
|---|---|---|---|
| Input | — | (B, M, 336) | B samples, M channels, L = 336 |
| Channel split | reshape | (B·M, 336) | Channels folded into batch. Nothing learned here |
| Instance norm | (x − μ) / σ per row | (B·M, 336) | μ, σ stashed for the inverse at the end |
| Pad | repeat xL S = 8 times | (B·M, 344) | So the final patch is anchored at the forecast origin |
| Patch | unfold(size = 16, step = 8) | (B·M, 42, 16) | N = 42 tokens, each a 16-vector |
| Project | Wp ∈ R128×16 | (B·M, 42, 128) | 2,048 weights. This is the entire "embedding table" |
| Position | + Wpos ∈ R128×42 | (B·M, 42, 128) | Learned, additive, 5,376 parameters |
| Encoder | 3 vanilla Transformer layers | (B·M, 42, 128) | Multi-head attention + FFN, with BatchNorm, not LayerNorm |
| Flatten | reshape | (B·M, 5376) | 42 × 128 = 5,376 |
| Head | Linear 5376 → T | (B·M, T) | For T = 96 that is 516,096 weights — the biggest single block |
| Denorm + unfold | ·σ + μ, reshape | (B, M, T) | Back to the caller's shape |
Two details in that table are worth stopping on.
The projection is 2,048 parameters. That is the entire mechanism by which raw numbers become tokens: one 128×16 matrix. Compare a language model's embedding table at 50,000 × 4,096 = 205 million. The tokenizer here is five orders of magnitude smaller than the thing it replaces, because it does not have to memorise atoms — it has to compute them.
BatchNorm, not LayerNorm. The paper's footnote cites Zerveas et al.: "BatchNorm outperforms LayerNorm in time series Transformer." This is a genuine departure from NLP practice and it is a consequence of the domain. LayerNorm normalises across the feature dimension of a single token — but a patch's features are 16 consecutive time values, and normalising across them would destroy the level and slope information that makes the patch meaningful in the first place. BatchNorm normalises each feature across the batch, leaving the within-patch shape intact.
Drag L, P and S and watch the patch boundaries move. The readout gives N from the paper's formula, the token tensor shape, and the attention-cell count against the pointwise baseline. Push S down to 1 to see what "no patching" costs; push P above S to open the overlap.
Here is the experiment that motivates the whole design, and it is small and sharp. Everyone knew that longer look-back windows should help — more history, more information. Everyone also observed that pointwise Transformers got worse as the look-back grew, because the token count grew with it and the model overfitted.
PatchTST ran the control that separates the two effects. Take L = 380, but subsample it — keep every 4th point, plus the last one — so the token count is 96, the same as a pointwise model with L = 96. Same number of tokens, four times the span. Result: MSE 0.447 with the long-span subsampled input against 0.518 with the recent-96 input.
With that established, the look-back curve inverts. PatchTST sweeps L ∈ {24, 48, 96, 192, 336, 720} and reports that "our model gains performance improvement with increasing look-back window", while the Transformer baselines flatten or degrade. The default of 336 and the large variant at 512 are chosen on that curve.
On the eight standard long-horizon benchmarks — Weather, Traffic, Electricity, ILI and the four ETT datasets — against FEDformer, Autoformer, Informer, Pyraformer, LogTrans and DLinear:
| Variant | Look-back | Tokens | MSE reduction vs best Transformer | MAE reduction |
|---|---|---|---|---|
| PatchTST/64 | L = 512 | 64 | 21.0% | 16.7% |
| PatchTST/42 | L = 336 | 42 | 20.2% | 16.4% |
A twenty percent MSE reduction is a large number in this literature. But an aggregate improvement never tells you which idea earned it, so the paper runs the 2×2 ablation: patching on or off, channel independence on or off.
| Configuration | Patching | Channel independence | Outcome reported |
|---|---|---|---|
| P + CI (full PatchTST) | Yes | Yes | Best across the board |
| CI only (P = S = 1) | No | Yes | Works, clearly worse, far slower |
| P only | Yes | No | Worse than P + CI |
| Neither (original TST) | No | No | Worst; several settings report "—" — out of GPU memory on an A40 48GB at batch size 1 |
The dashes in that table are the most eloquent entry. Without patching, a Transformer over Traffic's 862 channels and a 336-step window does not merely underperform. It does not run.
And one more control that is easy to miss: the paper trains PatchTST with and without instance normalisation and finds it "improves the forecasting performance slightly", concluding that "the improvement mainly comes from patching and channel-independence." That is a rare and honest sentence — the authors explicitly deny credit to one of their own components.
You have hourly data and want a context spanning four full weeks, so L = 672. Your GPU budget allows at most 2,500 attention cells per head per layer. (1) Find the smallest stride S, with P = 2S so overlap stays at 50%, that fits the budget. (2) Give N, the patch tensor shape for a batch of 16 samples from a 21-channel dataset, and the size of Wp for D = 128. (3) State one thing you have lost relative to S = 8.
Answer. (1) N2 ≤ 2500 means N ≤ 50. With P = 2S, N = ⌊(672 − 2S)/S⌋ + 2, which for S dividing 672 is (672/S − 2) + 2 = 672/S. Need 672/S ≤ 50, so S ≥ 13.44; take S = 14, P = 28, giving N = 48 and 2,304 cells. (2) The patch tensor is (16·21, 48, 28) = (336, 48, 28), and Wp is 128×28 = 3,584 weights. (3) Each token now averages 28 timesteps rather than 16, so the finest structure the model can resolve inside a token is coarser — a sharp one-hour spike is one twenty-eighth of a token's content rather than one sixteenth, and the linear projection must compress it into the same 128 dimensions. You bought span with resolution.
Everything in Chapter 2 was supervised: patches in, horizon out, MSE against the truth. That is a forecaster, not a foundation model. The difference is one sentence long — a foundation model learns a representation before it learns a task — and the second half of PatchTST is where that transition happens for time series.
This chapter is the pivot of the lesson. It is also where the tensor shapes get interesting, because the choice of head turns out to constrain the choice of objective far more tightly than anyone expected.
Go back to the shape table. Three Transformer layers at D = 128 come to roughly 600,000 parameters. The flatten-and-project head, for a single horizon T:
head parameter count — flatten (N x D), then Linear to TN = 42, D = 128 -> flattened width = 42 * 128 = 5,376
T = 96 : 5,376 * 96 = 516,096 params (0.52 M)
T = 192 : 5,376 * 192 = 1,032,192 params (1.03 M)
T = 336 : 5,376 * 336 = 1,806,336 params (1.81 M)
T = 720 : 5,376 * 720 = 3,870,720 params (3.87 M)
At T = 720 the head is roughly six times the size of the backbone. Worse, it is horizon-specific: the supervised PatchTST trains a separate model for every prediction length, because the output width is baked into a weight matrix.
Now recall the alternative the paper argues against — the pointwise masked-autoencoder design of Zerveas et al., where every timestep is a token. Its head has to map L·D features to M·T outputs:
the head PatchTST is arguing againstW has shape (L * D) x (M * T) L = 512, D = 128, M = 7, T = 96 -> (512 * 128) x (7 * 96) = 65,536 x 672 = 44,040,192 params (44.0 M) # 85x the patched head, for the same task
The paper's phrasing is dry — "This matrix can be particularly oversized if either one or all of these four values are large. This may cause overfitting when the number of downstream training samples is scarce" — but the factor is 85×. Patching shrinks the head as a side effect of shrinking the sequence, and that is what makes a reusable backbone practical.
Swap the objective. Remove the forecasting head. Attach instead a linear layer of shape D × P — one that maps each token's representation back to the P raw values it came from. Then:
Their representation-learning configuration is L = 512 with patch size 12, non-overlapping. That gives 512 / 12 = 42.67, so 42 complete patches (the paper reports 42; the trailing 8 values do not form a full patch). Head size: 128 × 12 = 1,536 parameters — four orders of magnitude smaller than the 44M pointwise head, and about a thousandth of the T = 336 forecasting head.
This is the sharpest argument in the paper and it generalises far beyond forecasting. Mask a single timestep in a smooth series and ask a model to recover it. Its neighbours are right there. Linear interpolation between xt−1 and xt+1 recovers xt to within the local curvature — no understanding required.
Make it numeric. Let the series be a smooth sinusoid sampled at 24 points per period, so consecutive samples differ in phase by 2π/24 = 0.2618 radians. Mask xt. The midpoint of its neighbours is
The interpolation is off by 3.4% of the amplitude, and that is the entire difficulty of the task. The paper says it exactly: masked values "can be easily inferred by interpolating with the immediate proceeding or succeeding time values without high level understanding of the entire sequence, which deviates from our goal of learning important abstract representation."
Now mask a whole patch of 12 consecutive points. Interpolation across a 12-step gap in a period-24 sinusoid spans half a cycle — a straight line between the endpoints misses the entire hump, and the error is on the order of the amplitude itself, not 3.4% of it. To fill it you must recognise the periodicity from the unmasked patches and extrapolate the phase. That is a representation.
A pretraining objective is only worth anything if the frozen representation is useful. PatchTST measures this three ways, and the ordering is the point:
| Protocol | What trains | Epochs | Result reported |
|---|---|---|---|
| Supervised from scratch | Everything, from random init | Full run per horizon | The Chapter 2 baseline |
| Linear probing | The head only; backbone frozen | 20 | "already comparable with training the entire network from scratch and better than DLinear" |
| Fine-tuning | Probe for 10 epochs, then everything for 20 | 30 | Best. "on large datasets our pre-training procedure contributes a clear improvement compared to supervised training from scratch" |
Linear probing matching from-scratch supervision is the load-bearing result. It says the frozen features already contain what the forecasting task needs; the head is only reading them out. That is precisely the property that makes a backbone worth shipping as a checkpoint.
The two-stage schedule — probe first, then unfreeze — is not incidental either. The paper cites Kumar et al.: "a two-step strategy with linear probing followed by fine-tuning can outperform only doing fine-tuning directly." The reason is that a randomly initialised head produces large, meaningless gradients on the first steps, and those gradients flow straight into the pretrained backbone and damage it. Ten epochs of probing lets the head become sane before it is allowed to speak to the backbone.
The experiment that points directly at TimesFM and Chronos: pretrain on Electricity, fine-tune on the others. The result is honest and modest — "overall the fine-tuning MSE is lightly worse than pre-training and fine-tuning on the same dataset, which is reasonable", and sometimes worse than supervised training — but "the forecasting performance is still better than other models", and at a fraction of the compute, since only the head or a few epochs are retrained.
And the structural observation buried in that section is the one that made everything after it possible:
Two objectives are now on the table, and the three foundation models split between them. This fork determines everything downstream, so lay it out plainly.
| Masked reconstruction | Causal next-patch prediction | |
|---|---|---|
| Attention | Bidirectional — a token sees the future | Causal — a token sees only the past |
| Supervision per sequence | Only the masked positions (40% or 30%) | Every position — N predictions per sequence |
| Natural downstream tasks | Imputation, anomaly detection, classification, embedding | Forecasting, at any horizon, by rollout |
| Forecasting needs | A head, plus a decision about how the horizon enters | Nothing — just keep decoding |
| Variable context length | Free — mask whatever you like | Free only with care — see Chapter 5's masking trick |
| Chosen by | PatchTST (SSL variant), MOMENT, Moirai | TimesFM, Chronos |
The second row decides most arguments. In a causal model every one of the N tokens produces a training signal on every sequence; in a masked model only the masked fraction does. For the same number of tokens processed, causal training extracts roughly 2.5× more supervision at a 40% mask rate. That efficiency is exactly why language models converged on causal decoding, and it is why both models that set out to be forecasters chose it.
But look at row three. If you want the checkpoint to be useful for classification, imputation and anomaly detection — which is MOMENT's entire thesis — bidirectional reconstruction is the better objective, because those tasks are all instances of "fill in what is missing given everything else". Chapter 7 returns to this with numbers.
"Roughly 2.5× more supervision" was a hand-wave. Count it properly, because the real number is much larger than that and it explains a design choice in Chapter 5 that otherwise looks arbitrary.
Take a 512-point training sequence and ask, for each objective, how many numbers the loss is computed on.
supervised values per 512-point sequence# A. masked reconstruction, PatchTST SSL config: P = 12, disjoint, 40% maskedpatches = 512 / 12 = 42 masked patches = 0.40 * 42 = 17 supervised values = 17 * 12 = 204 # 0.40x the observations # B. causal next-patch, output patch equal to input patch: p = h = 32tokens = 512 / 32 = 16 # token j predicts steps 32j+1 .. 32j+32, and the last one falls off the endsupervised values = 15 * 32 = 480 # 0.94x the observations # C. causal next-patch, TimesFM's actual config: p = 32, h = 128tokens = 16 # token j predicts steps 32j+1 .. 32j+128 — targets OVERLAPtokens 1..12 : 128 valid targets each = 1,536 token 13 : 96 token 14 : 64 token 15 : 32 token 16 : 0 = 192 supervised values = 1,728 # 3.38x the observations # ratio C : A = 1,728 / 204 = 8.5x more supervision from the same data
And notice what this does to the data problem. Time-series corpora are small compared with text: Chronos trains on a corpus assembled from 28 public datasets, and MOMENT had to build the Time Series Pile from four archives because nothing suitable existed. When data is the binding constraint, an objective that extracts 3.4 targets per observation instead of 0.4 is worth more than an extra billion parameters.
The counter-argument, for balance: those four lessons about step 300 are highly correlated, so eight and a half times the targets is not eight and a half times the information. It is closer to a curriculum — the same target, at four difficulties — and curricula have diminishing returns. But the gradient signal is real, and it is free.
You are pretraining on 10-minute weather data. Your patches are 12 points (two hours) and you mask 40% of them. A colleague reports that the model reconstructs masked patches almost perfectly after one epoch, and yet the frozen features are useless for forecasting. Diagnose it, and give two fixes.
Answer. The correlation length of 10-minute weather far exceeds two hours — temperature at 14:00 is very well predicted by temperature at 12:00 and 16:00. So a two-hour mask is still inside the interpolable regime, and the model has learned an interpolator, not a representation. This is the point-masking failure at a coarser grain. Fixes: (1) increase the mask span — mask contiguous runs of several patches so the gap exceeds the correlation length, which is what a 75% image-masking ratio achieves; (2) change what is predicted — move to causal next-patch prediction, where the right-hand context is unavailable by construction, so interpolation is impossible. And a cheaper diagnostic to run first: compute the reconstruction MSE of plain linear interpolation on the same masked positions. If your model is not comfortably beating it, the task is too easy and no amount of training will make the features better.
Every paper so far has answered "what is a token?" by building something — a projection, a residual block, an architecture. Chronos answers it by refusing to build anything at all.
The proposal, in one sentence: round the numbers to a fixed grid, call each grid cell a word, and hand the resulting sentence to an unmodified language model. The paper's own summary is almost defiantly plain: Chronos "tokenizes time series values using scaling and quantization into a fixed vocabulary and trains existing transformer-based language model architectures on these tokenized time series via the cross-entropy loss."
Not a new architecture. Not even a new loss. T5, exactly as published, with one change: the embedding table is resized. The paper is explicit that "No modifications are required to the language model architecture, except adjusting the vocabulary size to |Vts|… Concretely, adjusting the vocabulary size entails truncating (or extending) the input and output embedding layers of the language model."
Recall the mean-scaling transform. Given a context x1:C, set m = 0 and
and keep our eight weekly demand values from Chapter 1:
These are still real numbers. A language model cannot read them. That is what step two is for.
Pick B bin centers c1 < c2 < … < cB on the real line, with B − 1 edges bi sitting between consecutive centers. The quantization function q maps a real to an integer, and the dequantization function d maps it back:
Two decisions remain: where to put the centers, and how many.
Where. You could space them by quantiles of the training data — more resolution where values are dense. Chronos deliberately does not: "Since the distribution of values for unseen downstream datasets can differ significantly from the training distribution, we opt for uniform binning." This is a foundation-model decision, not a compression decision. Quantile bins are optimal for the corpus you have and mis-shaped for the corpus you have not seen. Uniform bins are never optimal and never catastrophic.
So the centers are uniformly spaced on [c1, cB] = [−15, +15], with edges exactly midway: bi = (ci + ci+1) / 2.
How many. The vocabulary size is 4096, "including the special tokens (PAD and EOS)". Subtract those two and you get B = 4094 numeric bins — the number the paper uses in its own error analysis.
Now the spacing falls out. With B centers spanning a range of 30, there are B − 1 gaps:
and the i-th center (1-indexed) is ci = −15 + (i − 1)Δ.
To turn a scaled value v into an index, invert that formula and round to the nearest center:
Do the first one completely, digit by digit. v = 0.8696:
quantizing one value, every step shownv + 15 = 0.8696 + 15 = 15.8696 (v + 15) / delta = 15.8696 / 0.00732959 = 2164.87 round(...) = 2165 index i = 2165 + 1 = 2166 # check by going back: the center of bin 2166 is c_2166 = -15 + 2165 * 0.00732959 = -15 + 15.868563 = 0.868563 # and un-scaling by s = 11.5: c_2166 * s = 0.868563 * 11.5 = 9.9884 # true value was 10 error = -0.0116 # 0.12% of the value
The whole context, tokenised:
| x | x̃ = x / 11.5 | Token id | Bin center ci | Dequantized ci·s | Error |
|---|---|---|---|---|---|
| 10 | 0.8696 | 2166 | 0.868563 | 9.9884 | −0.0116 |
| 12 | 1.0435 | 2190 | 1.044466 | 12.0114 | +0.0114 |
| 8 | 0.6957 | 2142 | 0.692646 | 7.9654 | −0.0346 |
| 14 | 1.2174 | 2214 | 1.220376 | 14.0343 | +0.0343 |
| 11 | 0.9565 | 2178 | 0.956511 | 10.9999 | −0.0001 |
| 15 | 1.3043 | 2225 | 1.301002 | 14.9615 | −0.0385 |
| 9 | 0.7826 | 2154 | 0.780601 | 8.9769 | −0.0231 |
| 13 | 1.1304 | 2202 | 1.132421 | 13.0228 | +0.0228 |
So the sentence a T5 encoder sees is literally
and the worst error in the table is 0.0385 out of a value of 15 — 0.26%. The theoretical bound is half a bin width: Δ/2 = 0.003665 in scaled units, which is 0.003665 × 11.5 = 0.0421 in original units, and every row respects it.
The top panel shows the raw series and, over it, the dequantized reconstruction Chronos would see. The bottom shows the token ids. Shrink the vocabulary and watch the reconstruction step; switch to the sparse-spike or offset-sine series and watch the two documented failure modes appear on screen. The readouts under the panels are computed live from the same arithmetic you just did by hand.
Token ids in, T5 out. The only architectural surgery is the embedding table, and it is worth seeing what that does to the parameter counts, because it explains a footnote that otherwise reads as a typo.
| Chronos variant | Base architecture | Params | Note |
|---|---|---|---|
| Chronos-T5 (Mini) | T5 encoder-decoder | 20M | The paper flags that "These numbers differ from the original sizes of the T5 models… due to the change in the vocabulary size." T5's text vocabulary is 32,128; the time-series vocabulary is 4,096, so the input and output embedding tables shrink by roughly 87% |
| Chronos-T5 (Small) | T5 encoder-decoder | 46M | |
| Chronos-T5 (Base) | T5 encoder-decoder | 200M | |
| Chronos-T5 (Large) | T5 encoder-decoder | 710M | |
| Chronos-GPT2 | GPT-2, decoder-only | 90M | Included to show the recipe is architecture-agnostic — encoder-decoder or decoder-only, both work |
The context length is 512 — "the default for T5 models" — and the prediction length is 64, "a value greater than the prediction lengths of all tasks we consider in our evaluation." Note that these are timepoints, not patches: Chronos spends one token per observation, which is the price of using a language model verbatim. Chapter 1's high-frequency squeeze is exactly this constraint.
The output distribution is a categorical over the 4096 vocabulary entries, and the loss is ordinary cross-entropy. The paper names the paradigm: "Chronos uses a categorical distribution to model the observations, performing regression via classification."
Work an instance. Suppose at some position the model's logits over five neighbouring bins are (0.4, 2.1, 3.6, 1.9, 0.2), and the true next value quantizes to the middle bin.
cross-entropy at one position, by handlogits = [ 0.4 , 2.1 , 3.6 , 1.9 , 0.2 ] subtract max = [-3.2 ,-1.5 , 0.0 ,-1.7 ,-3.4 ] # numerically safe softmax exp = [0.0408, 0.2231, 1.0000, 0.1827, 0.0334] sum Z = 1.4799 probabilities = [0.0275, 0.1508, 0.6757, 0.1234, 0.0226] truth = middle bin -> loss = -ln(0.6757) = 0.3920 # and here is the point: truth = next bin over -> loss = -ln(0.1234) = 2.0920 truth = four bins away -> loss = -ln(0.0275) = 3.5920 # the guessing baseline for a 4096-way softmax is ln(4096) = 8.3178
Notice the middle line. Being one bin off — an error of 0.0073 in scaled units, utterly negligible — costs 2.09 nats, while being four bins off costs 3.59. The ratio is not 4:1, or 16:1, or anything proportional to the distance. It is whatever the softmax happens to produce, because cross-entropy has no notion of distance between classes. A conventional forecasting loss like MSE punishes errors quadratically by construction; this one does not punish by magnitude at all.
And the paper is candid that this is unfinished business: "An in-depth theoretical and empirical analysis of the regression-via-classification paradigm in the context of time series forecasting would constitute interesting future research."
Because the output is a categorical distribution and generation is autoregressive sampling, a probabilistic forecast requires no extra machinery at all. Draw a token, dequantize it, append it to the context, draw the next, and repeat to the horizon. Do that 20 times — the paper's setting — and you have 20 sample paths. Read quantiles off them.
This is a real advantage over TimesFM, whose base model emits point forecasts and would need extra quantile heads (its paper notes this as a straightforward extension). It also costs something: a point forecast from Chronos requires aggregating over samples, which the discussion section lists as a target for future speedups.
Chronos's public pretraining data is smaller than TimesFM's by orders of magnitude — 28 public datasets, not 100 billion timepoints from Google's logs. Two augmentation schemes make up the difference.
TSMixup. Sample k ~ U{1, K} series of a common length from different datasets, scale each, and take a convex combination:
with K = 3 in the main runs. Because k can be 1, "original time series are adequately represented since they are included in the TSMixup augmentations with probability 1/3." The purpose is stated as pattern diversity: a mixture of a traffic series and a retail series is a series with two simultaneous seasonalities, which is a pattern the corpus does not otherwise contain.
KernelSynth. Build a bank of Gaussian-process kernels — linear for trend, RBF for smooth local variation, periodic for seasonality — then sample j ~ U{1, J} of them, combine with random + or × operations, and draw a sample from the resulting GP prior. The paper credits the Automatic Statistician for the idea and notes that it is running it backwards: that system searches over compositional kernels to explain a series, and "We use the inverse of this process — randomly compose GP kernels to generate new time series."
Chronos has an honest limitations section, and both failure modes are direct consequences of the arithmetic above. They are worth knowing before you deploy it, because both are silent.
Failure 1 — overflow on sparse series. The representable range in original units is [−15s, +15s]. If s is tiny relative to the peaks, the peaks fall off the end of the vocabulary. The paper's own example: unit spikes every n observations, so s = 1/n.
the intermittent-demand failure, by handspikes of height 1.0, one every n observations s = mean|x| = 1/n maximum representable original value = 15 * s = 15/n n = 10 : 15/10 = 1.50 -> spike of 1.0 fits (OK) n = 20 : 15/20 = 0.75 -> spike of 1.0 CLIPS (top bin) n = 50 : 15/50 = 0.30 -> spike of 1.0 CLIPS badly # the paper: "When 1 > 15/n then the model cannot possibly capture # the spikes appropriately... since their value is not represented # accurately by tokens."
Intermittent demand — the spare part that sells four units a year — is one of the most common real forecasting problems there is, and it is precisely where mean scaling collapses. This is the single most practically important sentence in the Chronos paper.
Failure 2 — precision loss on offset series. The opposite regime. If s is large relative to the variance, the interesting variation is smaller than one bin. Token spacing in original units is 30s / (B − 1):
| Series | s ≈ | Token spacing 30s / 4093 | Distinct tokens across a peak-to-peak swing of 2.0 |
|---|---|---|---|
| sine of amplitude 1, offset μ = 1 | 1 | 0.00733 | 273 — plenty |
| sine of amplitude 1, offset μ = 10 | 10 | 0.07330 | 27 |
| sine of amplitude 1, offset μ = 50 | 50 | 0.36648 | 5.5 — the wave is a staircase |
A signal riding on a large DC offset — a temperature in Kelvin, a stock index, a cumulative counter — loses almost all its structure. The fix the paper offers is an inference-time heuristic, not a model change: "preprocess the time series using an alternative normalization scheme, such as standardization, for time series with large scale and small variance." In other words, centre it yourself before you hand it over.
The paper sweeps the vocabulary size on Chronos-T5 (Small) and reports something that is not a clean win: "modest improvements in the point forecasting metric (MASE) as the vocabulary size increases. In contrast, the WQL initially improves but deteriorates for larger vocabulary sizes."
Their explanation is a metric argument and it is worth internalising, because it is a trap you can fall into on any project. MASE is scale-invariant, and so is the training loss (which operates entirely on scaled values), so the two move together: more bins means finer resolution means better MASE. WQL is scale-dependent, so it does not track the training loss and "behaves less predictably as precision increases." The paper's conclusion is deliberately modest: selecting a vocabulary size "would pose a trade-off", between resolution and the number of examples the model sees for each token.
You are forecasting a warehouse temperature sensor reporting in Kelvin. Values sit between 291.0 K and 294.0 K. Compute the token spacing Chronos would use, the number of distinct tokens your entire signal can occupy, and then give the one-line preprocessing fix and verify it.
Answer. s = mean|x| ≈ 292.5. Token spacing = 30 × 292.5 / 4093 = 8775 / 4093 = 2.144 K. Your entire 3.0 K signal spans 3.0 / 2.144 = 1.4 tokens — effectively two values. The model will emit a flat line and be technically almost correct on MASE while being completely useless. Fix: subtract a constant before scaling — work in Celsius (values around 19.0, s ≈ 19, spacing 0.139 K, 21 tokens across the swing) or, better, subtract the context mean and hand over the residual, then add it back (values around ±1.5, s ≈ 0.85, spacing 0.0062 K, about 480 tokens across the swing). The lesson: for a Chronos-style tokenizer, the choice of unit and origin is a modelling decision, not a formatting one.
Chronos borrowed a language model whole. TimesFM borrowed only the shape of one — a causal decoder that predicts the next thing from all previous things — and then broke the analogy in exactly one place, which turns out to be the most interesting design decision in the paper.
The claim is a modest-sounding one for a 200M-parameter model: zero-shot performance that "comes close to the accuracy of fully-supervised forecasting models on a diverse set of time-series data." And the authors are careful to put it in context against the alternative that was popular at the time: "unlike recent work that recommends Large Language Models such as GPT-3 and LLama-2 as out-of-the-box zero-shot forecasters, foundation models trained from scratch exclusively on time-series data can obtain much better zero-shot performance at a tiny fraction of its costs."
Decision one: patch. Inherited from PatchTST, and justified in the same terms — "A patch of a time-series is a natural analogue for a token in language models" — with the added inference argument that "the number of tokens being fed into the transformer is reduced by a factor of the patch length."
Decision two: go causal. "A key difference between our architecture and PatchTST is that our model is trained in decoder-only mode. In other words, given a sequence of input patches, the model is optimized to predict the next patch as a function of all past patches. Similar to LLMs this can be done in parallel over the entire context window, and automatically enables the model to predict the future after having seen varying number of input patches."
That last clause is the whole reason. A bidirectional encoder with a forecasting head is trained for one context length and one horizon. A causal decoder over N patches produces N supervised predictions per sequence, each conditioned on a different amount of history — so it is simultaneously being trained to forecast from 1 patch, 2 patches, …, N−1 patches. Variable context length is not a feature you add; it is a side effect of the objective.
Decision three: make the output patch longer than the input patch. This is the novel one, and it deserves its own section.
Start with the tension the paper identifies. In long-horizon forecasting "it has been observed that directly predicting the full horizon yields better accuracy than multi-step auto-regressive decoding" — a direct multi-step head beats rolling a one-step model forward, because rolled-forward errors compound. But you cannot bake the full horizon into the output width when you do not know the horizon in advance, "as in the case of zero-shot forecasting which is our primary goal."
TimesFM's answer: "We propose a middle ground by allowing our output patches for prediction to be longer than the input patches." Input patch p = 32, output patch h = 128.
The paper's own training illustration, spelled out: "suppose the input patch length is 32 and output patch length is 128. During training, the model is simultaneously trained to use the first 32 time-points to forecast the next 128 time-steps, the first 64 time-points to forecast time-steps 65 to 192, the first 96 time-points to forecast time-steps 97 to 224 and so on."
And the inference payoff, also the paper's example: "During inference, suppose the model is given a new time-series of length 256 and tasked with forecasting the next 256 time-steps into the future. The model will first generate the future predictions for time-steps 257 to 384, then condition on the initial 256 length input plus the generated output to generate time-steps 385 to 512."
rollout step count — the arithmetic that makes h mattersteps = ceil(H / h) # H = requested horizon, h = output patch H = 256, h = 128 -> ceil(2.00) = 2 steps # TimesFM as shipped H = 256, h = 32 -> ceil(8.00) = 8 steps # if h were tied to p H = 512, h = 128 -> ceil(4.00) = 4 steps H = 96, h = 128 -> ceil(0.75) = 1 step # most benchmarks: ONE forward pass # each extra step feeds the model its own output, so errors compound. # 2 steps instead of 8 is a 4x reduction in compounding opportunities, # and a 4x reduction in sequential latency.
Look at the last line of that block. For the two most-reported long-horizon settings, T = 96 and T = 192, an output patch of 128 means the entire forecast comes out of one forward pass for T = 96 and two for T = 192. The model is behaving like a direct multi-step forecaster on exactly the benchmarks where direct multi-step is known to win, while remaining able to roll out arbitrarily far when asked.
Track a series of length L = 512 through the model, with the 200M configuration: p = 32, h = 128, model_dim = 1280, 20 layers, 16 heads, FFN hidden size equal to model_dim.
| Stage | Operation | Shape out | Note |
|---|---|---|---|
| Input | y1:512 plus binary padding mask m1:512 | (512,) and (512,) | mi = 1 means "ignore this input" |
| Normalise | Standardise using the mean and std of the first input patch | (512,) | The paper uses "only the standard normalization part of reversible instance normalization" |
| Patch | Contiguous, non-overlapping, size 32 | (16, 32) and (16, 32) | 512 / 32 = 16 tokens. Note: no overlap, unlike PatchTST |
| Input residual block | MLP with one hidden layer plus a skip connection, on [patch, mask] | (16, 1280) | Not a bare linear map — the mask must be fused in here |
| Position | + positional encodings | (16, 1280) | |
| Stack | 20 layers, causal multi-head self-attention (16 heads) + FFN | (16, 1280) | Token j attends to tokens 1…j only |
| Output residual block | MLP 1280 → 128 | (16, 128) | Each output token is a full 128-step forecast of what follows its own patch |
| Take the last | row 16 | (128,) | At inference only the final token's forecast is used; the other 15 exist to supervise training |
| Denormalise | ·σ + μ | (128,) | Back in the caller's units |
Two structural notes. First, attention cost: 16 tokens is 256 attention cells, against 5122 = 262,144 for a pointwise model at the same context — a factor of 1024×. Second, the mask is an input, not a preprocessing step. It goes into the residual block alongside the values, so the model learns to interpret "this part of the patch is padding" rather than being handed silently corrupted numbers.
Derive the parameter count from the four hyperparameters. It lands almost exactly on the headline number, which is a good sanity check that you have understood the architecture.
TimesFM 200M parameter count, derivedd = model_dim = 1280, layers = 20, FFN hidden = d (stated in the paper) per transformer layer: attention W_Q, W_K, W_V, W_O = 4 * d * d = 4 * 1,638,400 = 6,553,600 FFN up + down = 2 * d * d = 2 * 1,638,400 = 3,276,800 ---------- 9,830,400 x 20 layers = 196,608,000 input residual block (patch 32 + mask 32 = 64) -> d -> d ~ 1.80 M output residual block d -> d -> 128 ~ 1.80 M ---------- total ~ 200.2 M # paper: "200M parameters"
Ninety-eight percent of the model is the transformer stack. The tokenizer and the head together are under 2%. Compare Chapter 3, where PatchTST's forecasting head was six times the backbone — the decoder-only design, with its fixed-width output patch, is what moves the parameters back into the part that generalises.
Here is a subtle bug you would ship if you were not careful, and the two-line fix.
Patches are non-overlapping and aligned to the start of the sequence. So the amounts of history the model is ever asked to condition on are 32, 64, 96, 128, … — multiples of p. The paper states the risk directly: "If we use patches naively, the model might only learn to predict well for context lengths that are multiples of the input patch length." Hand it a context of 100 points at inference and it is in unfamiliar territory.
The fix: "For each time-series in the batch, we sample a random number r between 0 and p − 1. Then we set m1:r = 1 and the rest as zero, i.e. we mask out a fraction of the first input patch."
Follow the paper's worked example. Max context 512, p = 32, and suppose r = 4:
why masking r points of the FIRST patch covers every context lengthr = 4 -> the first 4 values are masked out. token o_1 sees 32 - 4 = 28 real points -> supervised at context 28 token o_2 sees 28 + 32 = 60 real points -> supervised at context 60 token o_3 sees 60 + 32 = 92 real points -> supervised at context 92 ... (always 28 mod 32) # now vary r over 0..31 across the batch and across training: r = 0 covers contexts 32, 64, 96, ... (0 mod 32) r = 1 covers contexts 31, 63, 95, ... (31 mod 32) r = 2 covers contexts 30, 62, 94, ... (30 mod 32) ... r = 31 covers contexts 1, 33, 65, ... (1 mod 32) # union over r = 0..31: EVERY integer from 1 to 512. The paper: # "the model has seen all possible context lengths till 512."
One random integer per sequence, and the model becomes context-length agnostic. That is the sort of two-line trick that separates a research prototype from something you can hand to a stranger with an arbitrary series.
The context is patched into input tokens; each token emits a forecast of the next h steps, and only the last one is used at inference. Change the horizon and the output patch and watch the rollout steps — and the shaded compounding-error bands — grow or shrink. The masking slider hides the first r points of the first patch, exactly as in training.
TimesFM's pretraining data is the part of the paper that is hardest for anyone else to reproduce, and the authors are open about the sources.
| Source | What it is | Scale reported | Why it is in there |
|---|---|---|---|
| Wiki Pageviews | Hourly views of every Wikimedia page, Jan 2012 – Nov 2023, aggregated to hourly / daily / weekly / monthly | "roughly 300B time-points" | Enormous, genuinely multi-scale, and full of real human seasonality — weekday cycles, annual cycles, event spikes |
| Google Trends | Search interest for a large query set, weekly and monthly | Tens of thousands of series per granularity | Trend, fashion, bursty attention. The paper notes this data is differentially private |
| M4 | The forecasting-competition archive, all granularities | ~100k series | A curated mix of granularities from the community's own benchmark |
| Electricity, Traffic, Weather | Standard long-horizon datasets | Hundreds to 800+ series, tens of thousands of points each | Long, dense, strongly seasonal series |
| Synthetic | Generated patterns | 20% of every batch | Coverage of shapes the real corpus underrepresents |
Total: "O(100B) timepoints", against 200M parameters. The ablation confirms the synthetic share is load-bearing — the paper compares the 200M model with and without synthetic data on both Monash and ETT.
Input patch length. Sweeping p from 8 to 128 on a 70M model, "p = 16, 32 marks the best performance, with the error increasing towards either end." Too small and you are back to nearly-pointwise tokens with a huge sequence; too large and, as the paper says, "that makes the model shift from decoder only training more towards encoder-decoder style training" — in the limit p equals the context and there is only one token, so there is nothing causal left. They chose 32 over 16 because it is "almost twice as fast to train" for equal accuracy.
Scale. Three sizes — 17M, 70M, 200M — trained to 1.5M iterations at a global batch size of 4096 on TPUv5e, with checkpoints plotted against FLOPs. "It can be clearly seen that the errors decrease monotonically with the number of FLOPS (in log scale)." A clean log-linear scaling curve, on 100 billion timepoints, with the largest model costing "16 core TPUv5e for 2 days". That is a strikingly small budget for a foundation model, and it is the strongest evidence in the paper that the recipe is sound: the gains are coming from the design, not from brute force.
Every paper in this lesson reports that its model does well. All of them are telling the truth. This chapter is about reading those claims precisely enough to know what you are buying — because the honest summary is not "foundation models beat statistical baselines", and it is also not "the baselines still win". It is more specific and more useful than either.
You cannot audit a claim in a unit you cannot compute. There are two units in this literature.
MASE — Mean Absolute Scaled Error. Take the mean absolute error of your forecast, and divide it by the mean absolute error a naive one-step model would have made in sample. The division is what makes it comparable across series with different scales.
Work one completely. Quarterly data, so the seasonal period m = 4. In-sample history and the four actuals we must forecast:
MASE, all of it, by handhistory y = [10, 20, 15, 5, 12, 22, 17, 7] # 8 points, m = 4 actual a = [11, 21, 16, 6] # what really happened # denominator: mean absolute FIRST DIFFERENCE of the history diffs = |20-10|,|15-20|,|5-15|,|12-5|,|22-12|,|17-22|,|7-17| = 10 , 5 , 10 , 7 , 10 , 5 , 10 sum = 57 , count = 7 denom = 57 / 7 = 8.142857 # now score four forecasters: seasonal naive [12,22,17,7] errs 1,1,1,1 MAE 1.000 MASE 0.1228 naive (last=7) [ 7, 7, 7,7] errs 4,14,9,1 MAE 7.000 MASE 0.8596 mean (13.5) [13.5 x4 ] errs 2.5,7.5,2.5,7.5 MAE 5.000 MASE 0.6140 over-smoothed [11.5,19,15.5,8] errs 0.5,2,0.5,2 MAE 1.250 MASE 0.1535 a good model [11.4,20.6,16.3,6.2] errs .4,.4,.3,.2 MAE 0.325 MASE 0.0399
Two lessons from that block, and they are the two that people get wrong.
MASE = 1 is not "good". It means you matched a naive one-step predictor's in-sample error. On a strongly seasonal series, seasonal naive already scores 0.1228 — eight times better than the denominator — so a model at MASE 0.9 is not "close to naive", it is seven times worse than copying last quarter.
A smooth, plausible-looking forecast can lose to a crude one. The "over-smoothed" row is what an underconfident model produces: right shape, shrunken amplitude. It scores 0.1535 against seasonal naive's 0.1228. It looks better on a chart. It is worse. Foundation models trained with an MSE-style objective are systematically prone to this, because shrinking toward the mean is the risk-minimising response to uncertainty.
WQL — Weighted Quantile Loss. Used for probabilistic forecasts, computed by Chronos "on 9 uniformly-spaced quantile levels {0.1, 0.2, …, 0.9}", with the quantiles estimated from 20 sample paths for methods that sample. The per-quantile ingredient is the pinball loss, which is asymmetric on purpose:
pinball loss — why the asymmetry is the whole ideatrue value y = 11, and we are scoring the q = 0.9 quantile forecast. y_hat = 10 (too low) -> y >= y_hat -> 0.9 * (11 - 10) = 0.90 y_hat = 13 (too high) -> y < y_hat -> 0.1 * (13 - 11) = 0.20 # at q = 0.9 the loss punishes being too LOW 9x harder than being too high, # which is exactly what forces the 0.9 quantile to sit above the data 90% # of the time. Sum over the 9 levels, divide by sum|y|, and that is WQL.
Chronos reports "aggregated relative WQL" and "aggregated relative MASE". The recipe: score every model on every task, divide each score by the Seasonal Naive score on that task, and take a geometric mean across tasks.
Three consequences you must hold in your head when reading those figures.
| Choice | Why | What it hides |
|---|---|---|
| Normalise by Seasonal Naive | Datasets have wildly different difficulty; a raw average would be dominated by whichever dataset has the biggest numbers | If Seasonal Naive is unusually good on a dataset, every model's relative score looks bad there, and vice versa |
| Geometric, not arithmetic, mean | Ratios are multiplicative; the geometric mean is the right centre for them and is not dominated by one huge ratio. The paper notes it "is also not sensitive to the choice of the baseline" | A model that is catastrophic on one dataset and fine elsewhere is treated more gently than an arithmetic mean would treat it |
| Equal weight per task | "reflecting real-world scenarios where datasets may have different numbers of time series, frequencies, history and prediction lengths" | A tiny 8-series dataset counts as much as one with 800 series |
And a rule that quietly matters: "For models that failed or could not finish evaluation within the allotted time on certain datasets, we used a relative score of 1", i.e. the baseline's score. A model that cannot run on a dataset is scored as if it had tied with Seasonal Naive there, rather than being penalised.
Chronos, Benchmark I — 15 datasets that were in its training corpus. "The bigger Chronos-T5 models (Base and Large) significantly outperform baseline models… not only… better than local models (e.g., AutoETS and AutoARIMA), but they also perform better than task-specific deep learning models trained or fine-tuned for each dataset (e.g., PatchTST and DeepAR)."
That is a strong result, and it is an in-domain result — the correct comparison for "should I use one model instead of forty thousand", not for "will this work on my new data". Note also the observation the authors chose to publish: "the Seasonal Naive baseline performs competitively against other local models on this benchmark, suggesting that the datasets in this benchmark exhibit strong seasonal patterns." Half the standard benchmark suite is nearly solved by copying last week.
Chronos, Benchmark II — 27 datasets never seen in training. This is the real test, and the paper opens with the caveat rather than the headline: "This benchmark is clearly more challenging than Benchmark I, as the best models tend to offer lower improvements relative to the baseline."
| Claim | Exact wording |
|---|---|
| Versus statistical baselines | "Chronos models significantly outperform standalone local statistical models" |
| Probabilistic ranking | "Chronos models achieve the 2nd to 4th spots, performing better than most task-specific models that have been trained on these tasks" |
| Point ranking | "Chronos-T5 (Large) places 2nd, surpassing most baselines, including the strong SCUM ensemble" |
| The summary | "it performs significantly better than local models that are commonly used in a zero-shot setting, and it performs on par with the best task-specific deep learning models" |
| With fine-tuning | Chronos-T5 (Small) fine-tuned for 1000 steps "now takes the top spot on Benchmark II overall" |
"Second to fourth, on par with the best task-specific models" is a genuinely impressive result for a model that took no gradient steps on those datasets. It is not "beats everything".
TimesFM, across three benchmark families. The pattern is different and more revealing.
| Benchmark | What it is | Result, in the paper's words |
|---|---|---|
| Monash | 18 datasets (after filtering ones with missing values), minutes to years, finance / demand / weather / traffic | "TimesFM is the top model even though we never trained on these datasets. It is slightly better but within significance of N-BEATS but outperforms deep supervised models like DeepAR, and improves on llmtime's performance by more than 25%" |
| Darts | 8 univariate datasets, one series each, with interesting seasonalities and additive/multiplicative trends | "TimesFM is within statistical significance of the best models that is llmtime and seasonal ARIMA… since there are only 8 individual time-series in this dataset group, the standard errors are not sharp" |
| ETT (Informer) | 4 electricity-transformer datasets, horizons 96 and 192, context 512 | "TimesFM performs the best and the supervised PatchTST baseline… is within significance of it" |
Assemble the pattern from the evidence above and from the tokenizer failures in Chapters 4 and 5. This table is the practical takeaway of the whole lesson.
| Situation | Zero-shot foundation model | Why |
|---|---|---|
| Thousands of series, none individually precious | Strong win | One checkpoint against thousands of fits. The operational argument dominates before accuracy is even discussed |
| Cold start — a series with 30 observations | Strong win | Nothing to fit. ARIMA cannot identify orders; the foundation model just needs a context |
| Strongly seasonal, plenty of history, one series | Draw | Seasonal ARIMA / ETS / N-BEATS are within significance, per Darts and Monash |
| Long-horizon multivariate benchmarks (ETT etc.) | Slight win | TimesFM edges supervised PatchTST, which is within significance |
| Intermittent / sparse demand | Loss, sometimes badly | Chapter 4: mean scaling makes s tiny, spikes exceed 15s and clip. Croston-family methods exist for exactly this |
| Large offset, small variance (Kelvin, index levels) | Loss unless you preprocess | Chapter 4: token spacing 30s/(B−1) swallows the signal |
| Forecast driven by covariates (price, promotion, weather) | Loss | Neither model accepts covariates. Both papers list this as an open limitation |
| Strong cross-channel structure | Loss | Channel independence discards it by construction (Chapter 1) |
| High frequency needing multi-period context | Depends on tokenizer | Patch-based models cope; a one-token-per-point model runs out of context |
| You have a decent slice of target data | Fine-tune, do not zero-shot | 1000 steps moved Chronos-Small from mid-pack to first on 27 datasets |
Pick an archetype. Three real baselines are computed in your browser — seasonal naive, last-value naive, and simple exponential smoothing — alongside a toy stand-in for a pretrained model: it searches a small "pretraining corpus" of motifs for the one best matching the recent context and copies that motif's continuation. That is a caricature of what these models do, and it has the same failure mode: when the archetype is not in the corpus, retrieval returns something confidently wrong. Bars are MASE; shorter is better.
Play with the last two archetypes. On pure noise the retrieval stand-in loses to the mean forecast, because there is no motif to find and it copies a random one anyway — the same reason a foundation model's confident wiggle on an unforecastable series is worse than a flat line. On level shift everything degrades, and the ranking becomes mostly a lottery, which is the honest answer to "how do these models handle regime change".
The zero-shot claim rests entirely on the target data being absent from pretraining, and every author in this space knows the guarantee is soft. The disclosures are worth reading in full because they set the standard for what "honest" looks like here.
Chronos, in a footnote about Benchmark II: "From a rigorous standpoint, to prevent information leakage, the start time of any dataset within this category must be after the timestamp of the last observation from the pretraining dataset and Benchmark I. Nevertheless, we consider the risk to be minimal given that the datsets bear no overlap beyond high-level conceptual categorization."
Chronos, about a competitor it is beating: "the evaluation setup may have been advantageous for Moirai-1.0-R as many datasets in Benchmark II were part of its pretraining corpus." A paper flagging that its own comparison flatters itself.
TimesFM, about the Darts benchmark: "since these datasets are used in numerous time series blog posts for illustrative purposes, data contamination for llmtime cannot be ruled out." An LLM prompted with a famous series may simply have read it.
And the most quietly admirable one — Chronos's own changelog: "We found an off-by-one error in the decoded bin indices for Chronos models which had led to artificially worse results for Chronos models in the previous version. Upon fixing this issue, the results for Chronos models improved significantly." A one-index bug in dequantization, disclosed in public, that had been understating their own numbers. Note what it also implies for you: if you implement Chapter 4's quantization yourself and are off by one bin, you will lose accuracy in a way that looks like a modelling problem and is not.
Chronos measures inference time for a single series and reports that "the inference speed of the larger Chronos models is comparable to some statistical local models", while conceding that "a potential limitation of the larger Chronos models is their inference speed compared to task-specific deep learning models."
Read that comparison carefully, because it is doing real work. A statistical local model is fitted per series — that fit is the expensive part, and it is what the comparison includes. A task-specific deep model is trained once and then evaluated cheaply per series — but that training run is not in the number. So:
| Approach | One-time cost | Per-series cost at serve time | Cost of a brand-new series |
|---|---|---|---|
| ARIMA / ETS | None | A fit plus a forecast | A fit — if there is enough history to fit |
| Task-specific deep model | A training run per dataset | One forward pass | Free if the series joins a trained panel; otherwise a retrain |
| Foundation model | Someone else's training run | One forward pass (Chronos: 20, for the sample paths) | One forward pass |
The third column is where Chronos pays for its distribution: twenty sampling passes per forecast, each autoregressive over the horizon. The paper's own list of remedies is a list of things the NLP community already built — "quantization… and faster decoding techniques, including speculative and lookahead decoding" — which is the clearest possible illustration of what you buy by making your model architecturally identical to a language model.
A forecaster consumes a context and emits a future. Somewhere in the middle it holds a fixed-size representation of that context — and if that representation is good enough to forecast from, the obvious question is what else it is good enough for.
This chapter is about pulling the vector out of the middle and using it: to classify a series, to find similar series, to score how anomalous a window is. It is also where the honest limits of "one model for everything" become visible, because the objective a model was trained on determines what its representation throws away, and forecasting throws away exactly the things classification wants.
Take MOMENT, the model in this family built explicitly for general-purpose analysis rather than forecasting. Its configuration is stated precisely: "All models take an input time series of length T = 512, breaking it into N = 64 disjoint patches of length P = 8. We mask 30% of the patches uniformly at random during pre-training."
| Stage | Shape | Note |
|---|---|---|
| Input window | (512,) | Univariate. Multivariate handled "by independently operating on each channel along the batch dimension" |
| RevIN | (512,) | "re-scaling and centering time series using reversible instance normalization enables MOMENT to model time series with significantly different temporal distributions" |
| Patch | (64, 8) | Disjoint, P = 8. 512 / 8 = 64 exactly |
| Embed | (64, D) | D = 512 / 768 / 1024 for Small / Base / Large |
| Encoder | (64, D) | 6 / 12 / 24 layers; 40M / 125M / 385M parameters, sized to match T5 encoders |
| Pool | (D,) | Average over the 64 token positions. This is the embedding of the series. |
So a 512-point window becomes a 1024-number vector in the Large model. That is a 2:1 compression in raw count — not impressive as compression — but the point was never compression. The point is that the 1024 numbers live in a space where distance means similarity of dynamics, and the original 512 do not.
Once you have vectors, similarity is a dot product. Do one by hand in four dimensions so nothing is hidden. Let a query window and three library windows have pooled embeddings:
cosine retrieval over pooled embeddings, by handq = [ 0.8, 0.5, -0.2, 0.3] |q| = sqrt(0.64+0.25+0.04+0.09) = 1.0100 v1 ECG normal = [ 0.7, 0.6, -0.1, 0.4] |v1| = 1.0100 dot = 0.8(0.7) + 0.5(0.6) + (-0.2)(-0.1) + 0.3(0.4) = 0.56 + 0.30 + 0.02 + 0.12 = 1.0000 cos = 1.0000 / (1.0100 * 1.0100) = 0.9804 # nearest v2 ECG arrhythmia= [ 0.2, -0.5, 0.8, 0.1] |v2| = 0.9695 dot = 0.16 - 0.25 - 0.16 + 0.03 = -0.2200 cos = -0.2200 / (1.0100 * 0.9695) = -0.2247 v3 motor vibration=[-0.6, 0.3, 0.5, -0.2] |v3| = 0.8602 dot = -0.48 + 0.15 - 0.10 - 0.06 = -0.4900 cos = -0.4900 / (1.0100 * 0.8602) = -0.5640 # most dissimilar
Three lines of arithmetic and you have a nearest-neighbour search over an archive of sensor windows. Index a million of them and the same dot product becomes semantic search over machine behaviour: show me every window that looks like the four hours before the last failure. There is no forecasting anywhere in that query, and it is arguably the most valuable thing the checkpoint does.
Notice how tightly the objective and the task list are coupled. Masked reconstruction gives you imputation for free, anomaly detection almost for free (reconstruction error is already the loss), and classification cheaply (pool and probe). Causal next-patch prediction gives you forecasting for free and the others awkwardly. The objective is not a detail; it is the product roadmap.
MOMENT's imputation section reports that with linear probing it "achieved the lowest reconstruction error on all ETT datasets", and then adds: "In the zero-shot setting, MOMENT consistently outperformed all statistical interpolation methods with the exception of linear interpolation."
Sit with that. A 385-million-parameter foundation model, pretrained on a corpus assembled from four public archives, loses zero-shot imputation to drawing a straight line between the two neighbouring points.
Chronos says maybe, and is careful to label it a hypothesis rather than a result: "We hypothesize that the representations learned by the encoders of Chronos-T5 models are universal and can be used for these tasks. An exploration of Chronos-T5 representations for various downstream tasks would constitute interesting future work."
You can reason about how well that will go by asking, for each task, what the forecasting objective was paid to keep.
| Property of the window | Does a forecaster need it? | Does a classifier want it? | Consequence |
|---|---|---|---|
| Recent level | Critically — the forecast starts from it | Usually not — an ECG is an ECG at any baseline | Forecaster embeddings are dominated by level; you may need to remove it |
| Phase within the cycle | Critically — the next value depends on where in the cycle you are | No — class identity is phase-invariant | Two windows of the same class at different phases may sit far apart |
| Dominant frequency | Yes | Yes | Shared — transfers well |
| Amplitude / variance structure | Yes | Yes | Shared — transfers well |
| Long-range morphology | Some | Critically | Under-represented if the training horizon was short |
The two "critically / no" rows are where forecaster embeddings will disappoint on classification, and they are also fixable: centre and phase-align before pooling, or pool over several offset windows and average, which washes out phase the way a bag-of-frames does in audio. That is a real technique, not a hedge — and it is exactly the kind of adaptation that separates using a checkpoint from understanding it.
Chronos also has a structural advantage worth naming: it is a T5, so it has a genuine encoder whose output is a bidirectional representation of the context. A pure decoder-only model like TimesFM has only causal states, so the representation at position j has never seen positions after j — you would pool the final state, or the mean of states, and accept that early tokens were encoded with less information than late ones.
The reconstruction route deserves to be spelled out, because it is the one people deploy first and the one whose failure mode is least obvious.
The procedure: slide a window of 512 points along the series with some stride; run each window through the encoder and the reconstruction head; score the window by its mean squared reconstruction error. Rare dynamics score high because the model never learned to reproduce them.
Then you need a threshold, and the honest way to set one is to calibrate on a clean split rather than to pick a number.
calibrating an anomaly threshold, by hand# 1. run every window of a KNOWN-CLEAN period through the modelrecon errors on clean windows : mean mu = 0.021 , sd = 0.006 # 2. pick a working point. three sigma is the usual first guess:threshold = mu + 3 * sd = 0.021 + 0.018 = 0.039 # 3. score a suspect windowe = 0.058 z = (0.058 - 0.021) / 0.006 = 6.17 # six sigma — flag it # 4. sanity-check the alert rate BEFORE shipping. # at 3 sigma under a normal model, roughly 1 window in 741 fires. # with a 512-point window and a stride of 64 on 1 Hz data, that is # one window every 64 seconds -> about 65 false alarms per day, per sensor. # across 500 sensors that is 32,500 pages. The threshold is not the # hard part; the alert budget is.
Every task above starts with "reduce (N, D) token representations to one (D,) vector". That reduction is a modelling choice, and different choices keep different things.
| Pooling | Vector | Preserves | Destroys | Good for |
|---|---|---|---|---|
| Mean over tokens | (D,) | Average dynamics across the window | Where in the window anything happened | Classification, retrieval — MOMENT's default |
| Last token | (D,) | The most recent state; the natural read-out for a causal model | Everything the model chose not to carry forward | Forecasting from a decoder-only checkpoint |
| Max over tokens | (D,) | The strongest activation of each feature anywhere in the window | How often it fired | Detecting whether an event occurred at all |
| Mean & std concatenated | (2D,) | Average and variability of dynamics | Order | Classes that differ in regularity — arrhythmia versus normal sinus |
| No pooling | (N, D) | Everything, including position | Nothing — but it is not a fixed-size vector | Localisation: where the anomaly is, not just whether |
The fourth row is the cheap win people miss. Concatenating the standard deviation across tokens costs one line and doubles the dimension, and it captures "how much did the dynamics change within this window" — which is precisely the discriminating feature in a great many sensor problems, and which mean pooling averages away by construction.
python — pulling embeddings out of a patched encoderimport torch # x: (B, T) univariate windows, T = 512x = revin.normalize(x) # (B, 512) patches = x.unfold(-1, 8, 8) # (B, 64, 8) P = 8, disjoint tok = patch_proj(patches) + pos # (B, 64, D) h = encoder(tok) # (B, 64, D) D = 768 for Base emb_mean = h.mean(dim=1) # (B, D) the usual embedding emb_rich = torch.cat([h.mean(1), h.std(1)], -1) # (B, 2D) dynamics + variability emb_norm = torch.nn.functional.normalize(emb_mean, dim=-1) # retrieval over an archive of M windows is now one matmulscores = emb_norm @ archive_norm.T # (B, M) cosines top = scores.topk(10, dim=-1) # nearest neighbours
Nine lines from a raw window to a semantic search over a sensor archive. The heaviest thing in that block is the encoder call, and it runs once per window, offline, exactly like indexing documents.
| You want to… | Reach for | Because |
|---|---|---|
| Forecast, point estimate, long horizon | TimesFM | Decoder-only with a 128-step output patch; one or two passes for standard horizons |
| Forecast with calibrated intervals | Chronos | The output is already a distribution; sample 20 paths and read the quantiles |
| Classify, cluster, retrieve, detect anomalies | MOMENT (or another masked model) | Bidirectional masked reconstruction; pooled embeddings are the intended interface |
| Impute short gaps | Try linear interpolation first | MOMENT's own zero-shot table says so |
| Forecast multivariate with true cross-channel structure | Moirai, or a task-specific model | Any-variate attention is the only mechanism here that models channels jointly at arbitrary M |
| Anything, with a slice of labelled target data | Fine-tune whichever of the above fits | Chapter 6: 1000 steps changed Chronos-Small's ranking on 27 datasets |
Eight chapters in, you have seen five models. It would be easy to file them as five separate inventions. They are not. They are five points in a small, enumerable design space, and once you can see the axes you can read any new paper in this area in about ten minutes — and, more to the point, you can propose the combinations nobody has shipped.
There are five axes that matter.
| Tokenization | Objective | Scaling | Attention | Channels | Output | |
|---|---|---|---|---|---|---|
| PatchTST | Patch 16, stride 8 | MSE horizon / masked patch (40%) | RevIN standardise | Bidirectional encoder | Independent | Point, fixed T |
| TimesFM | Patch 32, disjoint | MSE on the next 128 steps | Standardise on the first patch | Causal decoder, 20 layers | Independent | Point, any horizon |
| Chronos | Bin index, B = 4094 | Cross-entropy over bins | Mean scaling | T5 encoder-decoder (or GPT-2) | Independent | Sampled distribution |
| MOMENT | Patch 8, disjoint | Masked reconstruction (30%) | RevIN standardise | Bidirectional encoder | Independent | Reconstruction + task heads |
| Moirai | Patch size by frequency | Mixture-distribution NLL | Instance normalisation | Masked encoder, any-variate | Any-variate | Mixture distribution |
Read the table by columns rather than rows and the field's actual state of knowledge appears. Column five is nearly constant — four of five models simply do not model channels — which tells you where the open problem is. Column three is nearly constant too, which tells you that scaling is considered solved (Chapter 4 says it is not). Columns one and two are where all the variation lives, which is why this lesson spent five chapters there.
| Token | Sequence length for L = 512 | What the first layer is | Wins | Loses |
|---|---|---|---|---|
| Point | 512 | Rank-one linear map | No information discarded; every value addressable | Quadratic blow-up; each token nearly meaningless |
| Patch (overlap) | 64 at P = 16, S = 8 | Linear RP → RD | Shape-level tokens; smooth boundaries from overlap | Redundant compute; leaks across masks in SSL |
| Patch (disjoint) | 16 at P = 32 | Linear or residual MLP | Cheapest; clean masking | Boundary artefacts; coarse resolution inside a token |
| Quantized bin | 512 | Embedding lookup | A real vocabulary; language machinery works verbatim; distributions for free | Quantization error; overflow/precision failures; long sequences |
| Frequency-conditioned patch | Varies | One projection per patch size | Right resolution per granularity | Needs the frequency as an input; more parameters |
Now look at the fourth and third rows together. The quantized token has the property everyone wants — a genuine discrete vocabulary — and the property nobody wants, a sequence as long as the series. The patched token has the opposite pair. Nothing in these five papers has both. That empty cell is the most obvious open recombination in the space, and it has a name in every neighbouring field: quantize the patch, not the value. Learn a codebook of K prototype shapes, assign each patch to its nearest code, and you get a short sequence of genuine discrete tokens.
| Objective | Supervision per sequence | Gives you free | Makes awkward | Failure signature |
|---|---|---|---|---|
| MSE on a fixed horizon | 1 target | Direct multi-step accuracy | Variable horizon; needs a head per T | Amplitude shrinkage under uncertainty |
| Masked reconstruction | mask fraction × N | Imputation, anomaly scores, embeddings | Forecasting (needs a head and a story) | Learns interpolation if the mask is too small |
| Causal next-patch MSE | N targets | Any horizon; any context length | Distributions (needs quantile heads) | Compounding error over rollout steps |
| Cross-entropy over bins | N targets | A full predictive distribution; multimodality | Point forecasts (must aggregate samples) | Tokenizer overflow / precision, not model error |
| Mixture NLL | N targets | Continuous distributions, no quantization | Choosing the mixture family in advance | Mode collapse onto one component |
The last column is the one to memorise, because it is your debugging checklist. When a foundation model produces a bad forecast, the first question is not "is it undertrained" but which of these signatures am I looking at. A flat, shrunken forecast is an objective problem. A staircase is a tokenizer problem. A forecast that drifts increasingly wrong after step 128 is a rollout problem. Three different fixes.
Chapter 6 named intermittent demand as the clearest loss for this family. Design a model for it, on purpose, one axis at a time. Do not skip to the answer; the value is in watching each constraint propagate.
The data. Weekly demand for spare parts. A typical series is mostly zeros with occasional counts of 1–4, and the zeros are meaningful — they are not missing data. Horizon 13 weeks; what the business needs is P(demand > 0) and the size distribution, not a point estimate.
| Axis | Choice | Reason, in one line |
|---|---|---|
| Scaling | Mean scaling — but with s from the non-zero values only, or no scaling at all if counts are small | Chapter 4: s = mean|x| collapses toward zero as sparsity rises, and 15s stops covering the spikes. Scaling on non-zeros keeps the window sized to the events |
| Tokenization | Patch, disjoint, length 4 (a month) | A single zero is uninformative; "three zeros then a 2" is the unit of meaning. Patching is what moves the token to that level |
| Objective | Two heads: Bernoulli over "any demand in this patch" plus a count distribution conditional on demand | The quantity of interest is explicitly a mixture of a point mass at zero and a positive distribution. MSE cannot represent that; neither can a single categorical over a uniform grid |
| Attention | Causal decoder | Variable horizon, and N supervision targets per sequence — sparse data is scarce, so extract the most signal per sample |
| Channels | Independent, plus a static embedding for part category | Cross-part structure is real but weak; a static covariate is far cheaper than any-variate attention |
Notice what happened. Every choice was forced by a property of the data that a general-purpose model had ignored, and the result is not a small tweak — it is a different model with a different loss, a different scaler and a different output head. That is the honest scope of "foundation model for time series" today: a very good default, and a starting point for the twenty percent of problems that have structure the default was never shown.
Architecture papers get read; data sections get skimmed. In this family the data section is where most of the variance actually lives, and the five models differ on it more than they differ on anything else.
| Model | Corpus | Scale | Augmentation | The bet being made |
|---|---|---|---|---|
| TimesFM | Google Trends, Wiki pageviews, M4, Electricity, Traffic, Weather | O(100B) timepoints | 20% synthetic, granularity-balanced loader | Volume and human-behavioural seasonality generalise to everything else |
| Chronos | 28 public datasets | 10M TSMixup + 1M synthetic | Convex mixtures + Gaussian-process kernel composition | You can manufacture pattern diversity when you cannot buy volume |
| MOMENT | The Time Series Pile, from 4 public archives | Multi-task, multi-domain | None; careful disjoint splits, seed 13 | Breadth of task beats depth of any one |
| Moirai | LOTSA | > 27B observations, 9 domains | Random context and prediction lengths | An open archive is itself the contribution |
Look at Chronos versus TimesFM. Chronos has roughly three orders of magnitude less real data and closes the gap with two generators — convex mixtures of real series, and samples from randomly composed GP kernels. Both are cheap, both are auditable, and neither requires access to a search engine's logs. If you are outside a large company, that row is the one to copy.
And the contamination point from Chapter 6 is really a corpus point. "Zero-shot" is a claim about the relationship between two datasets, so it is only as strong as the corpus documentation. A model whose corpus is a proprietary log stream cannot support an auditable zero-shot claim, no matter how good its numbers are.
Cross the axes and most combinations have never been shipped. Here are the four that look most load-bearing, with what each would buy and what it would cost.
| Recombination | Would buy | Would cost | Precedent elsewhere |
|---|---|---|---|
| Patch-level vector quantization — a learned codebook over patch shapes rather than over scalar values | A genuine discrete vocabulary and a short sequence. Distributions for free, at 16 tokens instead of 512 | Codebook collapse; and time-series shapes vary far more across domains than phonemes do across speakers | VQ-VAE for images; residual vector quantization in neural audio codecs |
| Causal decoder with a mixture-distribution head — TimesFM's rollout, Moirai's output | Any-horizon rollout and calibrated intervals, with no quantization error and no sampling passes | You must choose the mixture family in advance, and mixtures can collapse onto one component | DeepAR's parametric heads; Moirai already does the head, just not causally |
| Frequency-conditioned patching in a decoder — Moirai's multi patch-size projections, TimesFM's architecture | Right resolution per granularity without giving up the rollout freedom | The frequency becomes a required input, which it often is not in practice | Moirai's own multi patch-size projection layers |
| Role-tagged tokens for covariates — every covariate patched by the same shared projection, distinguished by a learned role embedding | The single largest missing capability: promotions, prices, weather forecasts | Sequence length grows linearly in the covariate count, so attention grows quadratically | Moirai's learned variate identities; segment embeddings in BERT |
A new time-series foundation model appears roughly every few months. Six questions, in this order, will tell you almost everything before you reach the results table.
| # | Question | What the answer predicts |
|---|---|---|
| 1 | What is one token, and how many are there for a 512-point context? | The attention budget, the maximum span, and whether high-frequency data is usable at all |
| 2 | What is the loss computed on, and how many targets per sequence? | Data efficiency, and which downstream tasks are free versus bolted on |
| 3 | How is the input scaled, and what happens to a mostly-zero series? | Whether intermittent demand works. This is almost never in the abstract |
| 4 | Causal or bidirectional? | Whether the checkpoint is a generator, an embedder, or awkwardly both |
| 5 | What happens with 862 channels? | Whether cross-channel structure is modelled or discarded — usually discarded |
| 6 | What is in the corpus, and is my data's source in it? | Whether the zero-shot number means anything for you |
If you can answer all six, you can predict the failure modes without running anything — and you will know which of the ten rows in Chapter 6's win-and-lose table your problem sits in.
Design a time-series foundation model that accepts covariates — price, promotion flag, weather forecast — without abandoning cross-dataset pretraining. The hard constraint is the one from Chapter 1: the number and meaning of covariates differ per dataset, so no weight may have a shape that depends on them.
One good answer, with the reasoning. Treat every covariate as another univariate series and tokenise it with the same shared patch projection — that keeps all weights covariate-agnostic. Then you need to tell the model which tokens are the target and which are context, and that is a per-token flag, not a per-dataset weight: add a learned "role" embedding (target / past-covariate / known-future-covariate) to each token, exactly as Moirai adds a learned variate identity. Attention then runs over the flattened set of all tokens from all series, so an arbitrary number of covariates is admissible, and the forecast is read only off the target-role positions. The two costs are real: the sequence grows linearly in the number of covariates, so attention grows quadratically in it; and the model must learn what a covariate means from context alone, since "price" and "temperature" get the same role flag. The papers' own suggestions are cheaper and weaker — TimesFM proposes predicting in-context and then "linearly regress[ing] the residual on covariates", and Chronos proposes "stacking ensembles of Chronos and other light-weight models that excel at handling covariates such as LightGBM". Both are admissions that the covariate lives outside the model.
Three papers, eighteen months, one question answered three ways. What is actually different about forecasting now?
Not the accuracy, mostly. Chapter 6 was blunt about that: on a single clean seasonal series, a tuned classical model is within significance. What changed is the unit of deployment. Before, the unit was a fitted model per series. After, the unit is a checkpoint per organisation. That is the same relocation that language modelling went through, and it has the same consequence: the interesting engineering moves from "how do I fit this" to "what do I ask it".
| Symbol | Meaning | Value / shape in these papers |
|---|---|---|
| L | Look-back window (context length), in timepoints | 336 or 512 (PatchTST); 512 (TimesFM, Chronos, MOMENT) |
| T, H | Forecast horizon | 96 / 192 / 336 / 720 (long-horizon); 64 (Chronos training) |
| M | Number of channels (variates) | 1, 7, 21, 321, 862 depending on dataset |
| P, p | Patch length (input) | 16 (PatchTST), 32 (TimesFM), 8 (MOMENT), 12 (PatchTST SSL) |
| S | Stride between patches | 8 (PatchTST); equal to P for disjoint patching |
| h | Output patch length | 128 (TimesFM) — deliberately > p |
| N | Number of tokens, ⌊(L−P)/S⌋ + 2 | 42 or 64 (PatchTST); 16 (TimesFM, L = 512); 64 (MOMENT) |
| D, d | Model dimension | 128 (PatchTST); 1280 (TimesFM); 512/768/1024 (MOMENT) |
| Wp | Patch projection — the entire "tokenizer" | RD×P; 128×16 = 2,048 weights |
| Wpos | Learned additive positional encoding | RD×N; 128×42 = 5,376 weights |
| s | Chronos mean scale, (1/C)∑|xi| | Scalar per context; 11.5 in the worked example |
| B | Number of quantization bins | 4094 numeric (4096 vocabulary including PAD and EOS) |
| Δ | Bin spacing, 30/(B−1) | 0.00732959 in scaled units |
| [c1, cB] | Representable range in scaled units | [−15, +15], i.e. [−15s, +15s] in original units |
| r | TimesFM random mask length on the first patch | Sampled uniformly from {0, …, p−1} |
| m1:L | Binary padding mask, an input to the model | 1 = ignore this timepoint |
| Number | What it is |
|---|---|
| 42 and 64 | Token counts for L = 336 and L = 512 at P = 16, S = 8. The title of the PatchTST paper |
| 64× | Attention-cell reduction from patching at stride 8. And "as much as 22 time" faster training, measured |
| 21.0% / 16.7% | PatchTST/64's MSE and MAE reduction against the best Transformer baselines |
| 0.447 vs 0.518 | Long-span-subsampled versus recent-96, at equal token count — the control that motivates patching |
| 40% / 30% / 75% | Mask ratios: PatchTST patches, MOMENT patches, image MAE patches |
| 4096 / 4094 / 0.00733 | Chronos vocabulary, numeric bins, and the bin spacing 30/4093 in scaled units |
| [−15s, +15s] | The representable range. Everything outside it clips; everything finer than 30s/(B−1) is lost |
| 15/n | Maximum representable spike height for unit spikes every n steps. Clips for n ≥ 16 |
| 20M – 710M | Chronos-T5 sizes, shrunk from the original T5 sizes by the vocabulary change |
| 200M / 1280 / 20 / 16 | TimesFM parameters, model dimension, layers, heads. The stack alone is 196.6M |
| 32 → 128 | Input patch to output patch. Cuts ⌈H/h⌉ rollout steps by 4× |
| O(100B) | TimesFM's pretraining timepoints; Wiki pageviews alone contribute roughly 300B before mixing |
| 16 cores, 2 days | TPUv5e cost of the final 200M TimesFM run — strikingly small for a foundation model |
| 15 / 27 / 42 | Chronos Benchmark I (in-domain), Benchmark II (zero-shot), and the total dataset count |
| 2nd – 4th | Chronos's zero-shot ranking on Benchmark II probabilistic forecasting. Not first |
| 1000 steps | Fine-tuning that moved Chronos-T5 (Small) to first place overall on Benchmark II |
| 27B / 9 domains | Moirai's LOTSA corpus — the largest open pretraining archive in the family |
| Step | What to do | The decision that matters |
|---|---|---|
| 1. Data | Grab the Monash archive from Hugging Face, or M4. Filter series with missing values, as TimesFM did | Hold out entire datasets, not windows, or your "zero-shot" number is meaningless |
| 2. Scale | Mean scaling or RevIN, per context window, statistics stashed for the inverse | Chapter 4: does your domain have meaningful zeros? If yes, do not centre |
| 3. Patch | tensor.unfold(-1, P, S), with S copies of the last value padded on | Overlap for supervised forecasting; disjoint if you will ever mask |
| 4. Embed | One nn.Linear(P, D), plus a learned positional table | That is the entire tokenizer. Resist the urge to make it deep |
| 5. Backbone | A vanilla Transformer. BatchNorm, not LayerNorm | Causal if you want any-horizon forecasting; bidirectional if you want embeddings |
| 6. Head | Output patch h > p if causal; flatten-and-project if not | Chapter 3: if the head is bigger than the backbone, rethink the objective |
| 7. Mask | Sample r ~ U{0, p−1} and mask the first r points of the first patch | Two lines. Without it your model only works at multiples of p |
| 8. Loss | MSE for point forecasts; pinball at 9 levels for intervals; cross-entropy if you quantized | Log the objective and MASE separately — they diverge, and the gap is diagnostic |
| 9. Baselines | Seasonal naive, naive, ETS, and linear interpolation for imputation | Chapter 7: a 385M model lost to a straight line. Always run the trivial baseline |
| 10. Report | Zero-shot and fine-tuned, with the pretraining corpus listed | Chapter 6: a claim without a corpus list is not auditable |
| If you want… | Go to |
|---|---|
| The classical forecasting machinery these models are measured against | Time-series forecasting and stationary signals |
| The Transformer itself, from zero | Transformer, attention, and the original Attention Is All You Need |
| Patching as tokenization in the modality that invented it | Vision Transformer — 16×16 pixel patches, the direct ancestor of P = 16 |
| Masked reconstruction done properly | BERT, Audio-MAE, VideoMAE V2 — the same mask-span argument in three modalities |
| Quantizing a continuous signal into a vocabulary | VAE and VQ-VAE, neural audio codecs, EnCodec, and quantization noise |
| How tokenizers get designed in language | Tokenization and CS224N tokenization |
| Gaussian processes, the generator behind KernelSynth | Gaussian processes |
| Using the embeddings for search and retrieval | Vector embeddings, similarity metrics, vector databases |
| The state-estimation view of the same problem | Kalman filter and state-space models |
| Sequence models that are not Transformers | SSMs and Mamba, RNN sequences |
| Sampling multiple paths to get a distribution | Sequential Monte Carlo |
tensor.unfold. A tokenizer is one nn.Linear. A quantizer is a divide and a round. Every mechanism in this lesson fits in fifty lines, and the models that used them are downloadable. The only thing between you and a working time-series foundation model is a corpus and a weekend.Without scrolling up: (1) derive N for L = 512, P = 16, S = 8 and explain both contributions to the "+ 2"; (2) mean-scale the vector [10, 12, 8, 14, 11, 15, 9, 13] and quantize the first entry to a token id, showing every step; (3) state the two ways Chronos's tokenizer breaks and give the arithmetic for each; (4) explain why TimesFM's output patch is longer than its input patch, and what bounds it above; (5) explain why masking whole patches rather than points is the difference between a representation and an interpolator; (6) give a MASE denominator from an 8-point history and say why MASE = 0.95 is bad news on seasonal data. If any of the six stalls, its chapter is one tap away.