← all posts

Inside TiRex-2: bidirectional where it's safe, causal where it matters

TiRex-2 reads future-known covariates in both directions, yet the target never gets a glimpse of its own future. This post is an interactive tour of the two design choices that make both possible: a time mixer that only runs backward over future-known covariates, and a single asymmetric attention mask.

Three kinds of variates

Real forecasting problems rarely involve a single signal. Take a power grid operator forecasting tomorrow's load. The load itself is the target. Some related signals, like measured grid frequency or spot prices, are only observed up to now: these are past covariates. Others are known in advance: the calendar, public holidays, scheduled maintenance, or a weather forecast. These are future-known covariates.

Formally, with context length \(T\) and horizon \(O\), TiRex-2 models

$$\mathcal{P}\bigl(\,\textcolor{#b0357f}{\mathbf{X}}_{T+1:T+O} \;\bigm|\; \textcolor{#b0357f}{\mathbf{X}}_{1:T},\; \textcolor{#b07a12}{\mathbf{Y}}_{1:T},\; \textcolor{#2f8a45}{\mathbf{Z}}_{1:T+O}\bigr)$$

and represents this distribution by a set of quantiles for every future time step.

Future-known covariates are often the most valuable input, but also the trickiest. To judge what a holiday on Friday means for Thursday's load, you want to know about Friday while you are at Thursday. In other words, you want to read these covariates in both directions along time.

The target must never be read that way. That constraint comes from two places:

So the question behind the architecture is simple: how do you give future-known covariates bidirectional context without opening a back door for the target?

The big picture

Every variate, whatever its type, is padded to length \(T+O\), scaled, split into non-overlapping patches of size \(P\), and embedded by a small residual MLP shared across all variates. This gives a grid of tokens

$$\mathbf{H} \in \mathbb{R}^{F \times L \times D}, \qquad F = F_x + F_y + F_z,\quad L = \lceil (T+O)/P \rceil .$$
$$\begin{gathered}\mathbf{H} \in \mathbb{R}^{F \times L \times D}, \\ F = F_x + F_y + F_z, \\ L = \lceil (T+O)/P \rceil .\end{gathered}$$

Unobserved positions (the future of the target and of past covariates, as well as missing values) are padded. The scaler combines instance normalization with an \(\operatorname{arcsinh}\) transform, so heavy-tailed variates can't dominate the loss. Binary variates skip the transform entirely, because standardizing a sparse 0/1 signal blows its two levels far apart.

The model then stacks \(N = 12\) blocks. Each block alternates two operations:

  1. a time mixer that mixes along the patch axis \(L\), separately for each variate, and
  2. a variate mixer that mixes along the variate axis \(F\), separately for each patch.

At the end, a quantile head turns every target token into \(Q\) quantiles for each step of the next patch, trained with the pinball loss on all observed time steps.

Here's one block. Hover over a variate type (or tap the buttons on mobile) to trace its path:

Hover over a variate type, or tap one of the buttons, to trace its path through one TiRex-2 block. Solid tokens are observed. Dashed tokens are padded positions the model has to forecast.
Figure 1. A simplified view of one TiRex-2 block with six patches (four context, two horizon). The variate mixer acts on every patch; for clarity, it's drawn for a single patch.

Time mixer: one xLSTM, two directions

The time mixer is an xLSTM. It's recurrent, so it processes patches in order and carries a fixed-size state. What differs between variates is only the direction it runs in:

$$\tilde{\mathbf{h}}_{z,l} = \mathrm{Linear}\bigl(\bigl[\,\overleftarrow{\mathbf{h}}_{z,l},\ \overrightarrow{\mathbf{h}}_{z,l}\,\bigr]\bigr), \qquad \overleftarrow{\mathbf{h}}_{z,l} = \mathrm{xLSTM}\bigl(\bar{\mathbf{H}}_{z,L:l};\,\theta\bigr)$$
$$\begin{gathered}\tilde{\mathbf{h}}_{z,l} = \mathrm{Linear}\bigl(\bigl[\,\overleftarrow{\mathbf{h}}_{z,l},\ \overrightarrow{\mathbf{h}}_{z,l}\,\bigr]\bigr), \\ \overleftarrow{\mathbf{h}}_{z,l} = \mathrm{xLSTM}\bigl(\bar{\mathbf{H}}_{z,L:l};\,\theta\bigr)\end{gathered}$$

Two details matter here. First, the reverse pass is weight-tied: it uses the same parameters \(\theta\) as the forward pass, so bidirectionality costs no extra xLSTM weights. Second, only future-known covariates pay for it. Targets and past covariates, which are the streams that keep arriving at inference time, stay forward-only.

Inside, the xLSTM stack alternates mLSTM blocks (matrix memory, fully parallelizable) with sLSTM blocks (scalar memory with state tracking). The original TiRex used sLSTM only.

Variate mixer: who may listen to whom

Mixing across variates is a different problem. The number of variates changes from one dataset to the next, and there is no natural order: "temperature" isn't variate #3 in any meaningful sense. Self-attention fits naturally here. It handles any \(F\) and is permutation-equivariant within each variate type.

Two modifications make it work for TiRex-2:

Grouped attention. Several multivariate series are packed into one batch. A block-diagonal mask keeps them from attending to each other, so nothing needs to be padded to the largest \(F\) in the batch.

An asymmetric mask. Within a series, target queries may read covariate keys, but covariate queries may not read target keys:

Row = who is reading (query), column = who is being read (key).
key xkey ykey z
query x✓✓✓
query y✕✓✓
query z✕✓✓

It looks like a small detail. It is what makes the whole design work.

Why the mask matters: the two-hop leak

Suppose we drop the mask. Press "what if there were no mask?" in Figure 1 to see the path. Here is what goes wrong:

  1. In the variate mixer, the future-known token \(z_4\) attends to the target token \(x_4\). Now \(z_4\) contains information about the target at patch 4.
  2. In the next block's time mixer, the reverse xLSTM carries \(z_4\) back to \(z_3\).
  3. In that block's variate mixer, \(x_3\) attends to \(z_3\) and learns about \(x_4\), which is exactly the patch it's supposed to predict.

None of these steps is suspicious on its own. Together they form a back door. A model trained to predict the next patch at every position would be rewarded for using it, and at inference time the information it learned to rely on simply isn't there.

The asymmetric mask cuts the first hop. Information can still flow backward in time, but only along the covariate channel, and the covariate channel never contains target information. Formally, one block maps the target token at patch \(l\) to a function of

$$\mathbf{H}_{x,\,1:l},\qquad \mathbf{H}_{y,\,1:l},\qquad \mathbf{H}_{z,\,1:L},$$

and by induction over the depth, the target token at patch \(l\) never depends on any target input after \(l\), in any layer. The paper gives the full proof. To our knowledge, TiRex-2 is the first time series foundation model that uses future-known covariates bidirectionally while keeping the target strictly causal in a single forward pass.

What this buys

Streaming at constant cost

Targets and past covariates, the streams that arrive at inference time, only pass through the forward xLSTM. Each new patch is a constant-cost state update, followed by a fresh forecast. A Transformer time mixer with KV caching pays \(\mathcal{O}(L)\) per new patch instead, so its latency grows with the history. We streamed TiRex-2 over up to 32 million time steps of a synthetic process. Forecast quality stayed stable even at context lengths 4,000× beyond the 8k context used in training.

The ablations agree

Removing single components on fev-bench, averaged over up to six seeds (MASE, lower is better):

ConfigurationAll fev-benchFuture-known cov. subset
TiRex-2 (full)1.5270.990
Forward only (no reverse pass)+0.022+0.077
No group attention+0.220+0.278
No future-known covariates+0.033+0.114

The bidirectional pass matters most exactly where it should, on tasks with future-known covariates. And the model does make use of them: withholding the future-known covariates costs more than three times as much on that subset as over all tasks.

Small and efficient

In univariate mode, where the variate mixer is inactive, TiRex-2 uses 38.4M active parameters. Multivariate forecasting activates another 44.1M. For comparison, Chronos-2 uses 120M.

For reference: the full architecture

TiRex-2 architecture. Middle: inputs are patched, embedded, passed through N blocks of time mixer and variate mixer, and projected to quantile forecasts. Left: the time mixer runs a forward xLSTM on all variates and a weight-tied reverse xLSTM on future-known covariates, fused by a linear layer. Right: the variate mixer applies asymmetric group attention across variates. Time Mixer Hn = [ hnx ; hny ; hnz ] RMSNorm hz hx , hy xLSTM ← reverse xLSTM forward → (shared weights) time Linear variate RMSNorm MLP H′ x̂ Output projection RMSNorm × N Variate Mixer asymmetric group attention Time Mixer xLSTM backbone inactive for univariate Input embedding x1:T y1:T z1:T+O context horizon target x past covariates y future covariates z forecast x̂ Variate Mixer H′ ∈ ℝ(BF)×L×P Reshape H ∈ ℝ(BL)×F×P RMSNorm Asymmetric group attention RMSNorm MLP Reshape Hn+1
Figure 2. The highlighted path shows how x, y and z pass through the model; only target tokens reach the output projection. Hover over one (or tap on mobile) to pick it. Left: time mixer. Middle: overall architecture with \(N\) stacked time and variate mixers. Right: variate mixer with asymmetric group attention (inactive for univariate inputs).Simplified for small screens: the overall architecture with \(N\) stacked time and variate mixers. The labels inside show what each mixer does with the highlighted variate. The detailed mixer panels appear on a wider screen. Adapted from the paper.

TiRex-2: Generalizing TiRex to Multivariate Data and Streaming
Patrick Podest*, Marco Pichler*, Elias Bürger, Levente Zólyomi, Bernhard Voggenberger, Wilhelm Berghammer, Daniel Klotz, Sebastian Böck, Günter Klambauer, Sepp Hochreiter. NeurIPS 2026 (Oral).

arXiv · BibTeX