AI Grimoire
Sheet
statusstale
difficultyintroductory
timeO(n²·d)
described2021
revised6w ago

ALiBi

No position embeddings at all. Subtract a per-head constant times the query–key distance from the attention scores, and the model extrapolates past its training length.

Standing

StaleLoad-bearing for understanding how the field arrived here, and replaced in practice by something on this list. Worth reading, not worth reaching for.

Solved the extrapolation problem first and lost to RoPE plus context extension, which extrapolates further without giving up an explicit position representation.

judged as of 2026-09 · what the labels mean

Theory

ALiBi adds nothing to the embeddings. It biases the attention logits directly with a penalty proportional to how far back the key is, using a slope mhm_h fixed per head.

softmax ⁣(qiKdkmhij)\mathrm{softmax}\!\left( \frac{q_i K^{\top}}{\sqrt{d_k}} - m_h \,|i - j| \right)
eq. 1 — bias added before the softmaxPress et al. §3

The slopes are a geometric sequence, not learned. For HH heads the ratio starts at 28/H2^{-8/H}, which spreads the heads from steeply local to nearly position-blind.

mh=28h/Hm_h = 2^{-8h/H}
eq. 2 — slope for head h, 1-indexed

Why it extrapolates

A model trained with learned or sinusoidal absolute positions has no defined behaviour past its training length: it is being asked about embeddings it never saw. ALiBi has no such embeddings. Evaluated at four times the training length its perplexity keeps falling, because the only thing the extra distance changes is a larger penalty — and a large enough penalty is simply a soft local window.

That framing is also the limitation. What extrapolates is the recency bias, not the ability to retrieve from far away: an ALiBi model handed a fact 8k tokens back has been actively discouraged from attending to it.

Implementation

python · torch ≥ 2.1
import math
import torch
from torch import Tensor


def alibi_slopes(n_heads: int) -> Tensor:
    """Geometric slopes; the paper's fallback covers non-powers of two."""
    def powers(n: int) -> list[float]:
        start = 2 ** -(2 ** -(math.log2(n) - 3))
        return [start ** (i + 1) for i in range(n)]

    if math.log2(n_heads).is_integer():
        return torch.tensor(powers(n_heads))

    closest = 2 ** math.floor(math.log2(n_heads))
    extra = powers(2 * closest)[0::2][: n_heads - closest]
    return torch.tensor(powers(closest) + extra)


def alibi_bias(n_heads: int, seq_len: int) -> Tensor:
    """[1, H, N, N], causal. Build once, reuse for every layer."""
    pos = torch.arange(seq_len)
    distance = (pos[None, :] - pos[:, None]).tril()   # <= 0 below diagonal
    return (alibi_slopes(n_heads)[:, None, None] * distance)[None]

Note the sign: distance is negative or zero on and below the diagonal, so multiplying by a positive slope already gives the penalty — no separate negation. Add the result to the scores before the causal mask, or the masked positions will pick up a finite bias and stop being masked.

Related

References

[1]Press et al. — Train Short, Test Long: Attention with Linear Biases (2021)arXiv:2108.12409
[2]Su et al. — RoFormer: Rotary Position Embedding (2021)arXiv:2104.09864
[3]Chi et al. — KERPLE: Kernelized Relative Positional Embedding (2022)arXiv:2205.09921