Dehghani, Djolonga, Mustafa, Padlewski, Heek, et al. (Google Research) — ICML 2023

ViT-22B: Scaling Vision Transformers to 22 Billion Parameters

The largest dense Vision Transformer of its time — 5.5× bigger than any prior ViT. To get there, the authors had to fight a training instability that only appears at scale, and they re-wired the Transformer block itself. The result: a vision backbone whose frozen features rival fine-tuned smaller models, and whose biases shift strikingly toward human perception.

Prerequisites: Transformer / self-attention + LayerNorm + matrix multiplication. We re-derive the rest.
10
Chapters
9
Simulations
2
Code Labs

Chapter 0: The Scaling Wall

You have a recipe that worked at every scale you ever tried. You took a Vision Transformer, made it bigger, fed it more images, and accuracy went up. ViT-Base, ViT-Large, ViT-Huge, then ViT-G at 2 billion parameters — each rung on the ladder paid off. So you do the obvious thing: you build a model an order of magnitude larger. You wire up 22 billion parameters across hundreds of TPU chips, you hit "go," and a few thousand steps in, the loss spikes to a wall and never comes back.

This is the situation Dehghani et al. faced. The language world had already crossed into the hundreds of billions of parameters (GPT-3, PaLM), but the largest dense vision model was stuck around 2B. Naively scaling the ViT recipe did not work. Something new breaks when a Vision Transformer gets large enough, and the paper's central engineering story is the diagnosis and cure of that break.

The symptom: training divergence. After a healthy start, the attention logits — the raw scores inside softmax(QKT) — grow without bound. The softmax collapses to a near one-hot distribution: every query attends almost entirely to a single key. The paper calls this attention entropy collapse. Once it happens, gradients through the saturated softmax vanish, the loss diverges, and the run is dead. Crucially, this does not happen at small scale with the same hyperparameters — it is a scale-triggered failure.

Why naive scaling hits a wall

Accuracy climbs smoothly with model size (teal) — until the largest model diverges in training (red marker), getting no result at all. The paper's contribution is the bridge that lets the 22B point be reached. Drag to sweep model scale.

log₁₀ params 9.0

The fixes that make 22B trainable are small in code but deep in consequence. There are three:

QK-LayerNorm
Normalize the queries and keys before the dot product. Caps the attention logits, kills entropy collapse.
Parallel layers
Run attention and the MLP from the same input and sum them, instead of stacking them. Bigger matmuls, less communication.
Asynchronous parallel linear ops
Overlap the linear-layer compute with cross-device communication so the chips never idle.

None of these change what a Transformer fundamentally is. They change how the block is composed and how the matmuls are executed across a TPU pod. That distinction — architecture vs. systems — runs through the whole paper. We will treat both as first-class.

And the payoff is not just "a bigger number." The paper reports three findings worth caring about. First, ViT-22B's frozen features — the model is never fine-tuned, just used as a fixed feature extractor with a single linear layer on top — are remarkably strong, often matching fully fine-tuned smaller models. Second, the model's shape-vs-texture bias shifts substantially toward shape, the direction humans sit in (humans classify by shape, standard CNNs by texture). Third, its errors line up more with human errors than smaller models do. Scale, it turns out, does not just buy accuracy; it buys a representation that is more human-like.

Common misconception: "ViT-22B is just ViT-G with more layers and wider matrices — nothing new." That is exactly the recipe that fails. The headline of the paper is not the parameter count; it is that the standard ViT block diverges at this scale and had to be modified (QK-LayerNorm + parallel layers) to train at all. The architecture change is the contribution, not a footnote.

What is the core problem ViT-22B had to solve before it could even finish training?

Chapter 1: ViT Recap & Where 22B Lives

To see what changed, we need the standard Vision Transformer (Dosovitskiy et al., 2021) cleanly in mind. A ViT does not look at pixels directly. It chops the image into a grid of non-overlapping square patches, flattens each patch, and treats the resulting sequence exactly like a sequence of word tokens.

Concretely, take a 224×224 RGB image and a patch size of 14×14. That yields a 16×16 grid = 256 patches. Each patch is 14·14·3 = 588 raw numbers; a learned linear patch-embedding projects each into a d-dimensional vector. Prepend a learnable [CLS] token, add positional embeddings, and you have an input tensor of shape [T, d] with T = 257.

x ∈ RH×W×3  →  patches [N, P·P·3]  →  tokens [N, d]  →  prepend CLS, +PE  →  [T, d]

Then comes a stack of L identical Transformer blocks. The standard ViT block is a sequential composition — attention first, MLP second, each wrapped with a residual connection and a pre-LayerNorm:

z' = z + Attn(LN(z))
z'' = z' + MLP(LN(z'))

Where Attn is multi-head self-attention and MLP is a two-layer feed-forward network with a GELU nonlinearity that expands d to 4d then back to d. Finally the [CLS] token's output feeds a classification head. That is all a ViT is.

Where does 22B sit on the ladder?

ViT-22B keeps the patch-token idea identical. It scales the three knobs that set a Transformer's size: the width d (hidden dimension), the depth L (number of blocks), and the MLP expansion. The configuration is roughly d = 6144, L = 48 blocks, 48 attention heads of dimension 128, and an MLP hidden size around 24576. Multiply those out across all blocks plus the patch embedding and head, and you land near 22 billion parameters.

ModelParamsWidth dDepth LHeads
ViT-Large~0.3B10242416
ViT-Huge~0.6B12803216
ViT-G (prior largest)~1.8B16644816
ViT-22B~21.7B61444848

A worked size estimate

Let us sanity-check the count from one block. A single block has two big sources of parameters. The attention projections WQ, WK, WV, WO are each [d, d] = 6144×6144 ≈ 37.7M parameters; four of them is about 151M. The MLP has two matrices [d, 4d] and [4d, d], each ≈ 6144×24576 ≈ 151M, so about 302M. One block is therefore roughly 151M + 302M ≈ 453M parameters. Across L = 48 blocks: 48 × 453M ≈ 21.7B. The patch embedding and head are a rounding error on top. The MLP, note, is two-thirds of every block — which is exactly why the parallel-layer reorganization in Chapter 4 pays off.

A model this big does not fit on one chip

22B parameters in float32 is ~88 GB of weights — plus optimizer state (~2×) and activations. A single TPU/GPU holds far less, so every weight matrix is sharded across a 2D mesh of devices. Each tile below is the slice one chip owns. Drag to change mesh size and see per-chip memory drop.

mesh side 4×4

This sharding is not a footnote — it dictates the architecture. Every time a sharded matmul finishes, devices must exchange partial results (an "all-gather" or "reduce-scatter"). That cross-device communication is slow relative to on-chip matmul. The parallel-layer and asynchronous-linear tricks of Chapters 4–5 exist precisely to make those communication steps cheaper and to hide them behind compute. The architecture of ViT-22B is, in a real sense, co-designed with the TPU pod it runs on.

Hold this picture: a ViT is a stack of z + Attn(LN(z)) then z + MLP(LN(z)) blocks over patch tokens. ViT-22B changes (a) what's inside the block to stop divergence (QK-LN), (b) how the two halves of the block are composed (parallel, not sequential), and (c) how each linear op is executed across the device mesh (asynchronously). Everything else is the original ViT.
Common misconception: "Bigger patches or higher resolution is what makes ViT-22B special." No — the patchification is unchanged from vanilla ViT. What changed is the block internals and the systems execution. Resolution and patch size are orthogonal knobs that were not the bottleneck.
In a standard ViT block, which sublayer holds most of the parameters, and why does that matter for ViT-22B?

Chapter 2: The Divergence — Attention Entropy Collapse

Before we can appreciate the cure, we have to understand the disease precisely. Recall scaled dot-product attention. For a query q and key k (each a dh-dimensional vector, dh the per-head dimension), the pre-softmax logit is:

ij = (qi · kj) / √dh

The attention weight is aij = softmaxj(ℓij). Now here is the failure mode. Nothing in the standard block bounds the magnitude of q and k. They are produced by learned linear projections WQ, WK with no constraint on their norm. During training, if those weights grow, the dot product q·k grows, the logits grow, and the softmax sharpens.

The softmax has a runaway property. Consider one query attending over keys. The gradient that updates WQ, WK tends to push the largest logit larger (it is the one that "wins" and gets credit). Larger logits mean a sharper softmax, which concentrates the gradient even more on the winning key, which pushes that logit larger still. This is a positive feedback loop. At small scale the loop is gentle and self-limiting; at large d and large L, with thousands of these loops compounding across layers, it runs away.

The entropy view

A clean way to measure how sharp a softmax is, is its Shannon entropy. For an attention row a = (a1, ..., aT):

H(a) = − ∑j aj log aj

A uniform distribution over T keys has maximum entropy log T. A one-hot distribution has entropy 0. The paper observes that just before divergence, the average attention entropy collapses toward zero — the attention becomes nearly one-hot everywhere. This is the diagnostic signature.

A worked numerical example

Take a single query attending over three keys with raw logits before any scaling. Suppose the logit gap grows over training. Let the logits be (1, 0, 0), then (4, 0, 0), then (12, 0, 0).

Logits (1, 0, 0): exp gives (e1, 1, 1) = (2.718, 1, 1), sum = 4.718, so a = (0.576, 0.212, 0.212). Entropy H = −(0.576 ln 0.576 + 2·0.212 ln 0.212) = −(0.576·(−0.552) + 0.424·(−1.551)) = 0.318 + 0.658 = 0.976 nats. Healthy — close to the maximum ln 3 = 1.099.

Logits (4, 0, 0): exp gives (54.6, 1, 1), sum = 56.6, a = (0.965, 0.0177, 0.0177). Entropy H = −(0.965·(−0.0357) + 2·0.0177·(−4.035)) = 0.0344 + 0.143 = 0.177 nats. The softmax has sharpened hard.

Logits (12, 0, 0): exp gives (162754, 1, 1), a = (0.99999, ~6e-6, ~6e-6). Entropy ≈ 0.0002 nats — effectively one-hot. The gradient through this softmax is essentially zero (the Jacobian of softmax is a·(diag − a aT), which vanishes as a goes one-hot). The layer can no longer learn. This is entropy collapse.

Watch the entropy collapse as logits grow

Three keys, logits (s, 0, 0). As you slide s up, the softmax bars sharpen toward one-hot and the entropy (the teal readout) falls to zero. Past the dashed line, the gradient through softmax is effectively dead. This is the runaway loop, frozen as a slider.

logit scale s 1.0

Why does this only appear at scale? Two compounding reasons. First, wider models have larger dh and more capacity in WQ, WK, so the achievable logit magnitudes are larger. Second, depth L matters: a small per-layer tendency to sharpen, repeated over 48 layers and millions of steps, compounds. The small-scale model never accumulates enough to tip over; the large one does. It is a classic case where a "works fine" recipe has a latent instability that only the scale exposes.

The key realization: the divergence is not a bug in the optimizer or a bad learning rate — it is a structural property of unbounded dot-product attention. Any fix must bound the logits. You can do that by clipping, by penalizing logit norm, or — the path ViT-22B takes — by normalizing q and k so their dot product can no longer run away. That is QK-LayerNorm.
Common misconception: "Entropy collapse means the model is just very confident, which is good." No — confident output predictions are fine. Collapsed attention entropy means each token ignores all but one other token, the softmax Jacobian goes to zero, and learning stops. Sharpness in the wrong place kills the gradient signal.
Why does the attention-entropy-collapse instability appear at 22B scale but not at, say, ViT-Large?

Chapter 3: QK-LayerNorm — Capping the Logits

The cure is almost embarrassingly small. Before computing the dot product, apply a LayerNorm to the queries and to the keys, per head. The standard attention logit was ℓ = (q·k)/√dh. ViT-22B replaces q and k with their layer-normalized versions:

ij = (LN(qi) · LN(kj)) / √dh

Recall what LayerNorm does to a vector v of dimension dh: it subtracts the mean, divides by the standard deviation, then applies a learned per-dimension scale γ and shift β:

LN(v) = γ ⊙ (v − μ) / √(σ² + ε) + β,   μ = mean(v),  σ² = var(v)

The decisive consequence: after LayerNorm, each of q and k has a controlled norm. Ignoring the learned γ, β for a moment, the normalized vector (v−μ)/σ has, by construction, second moment 1 per dimension, so its L2 norm is about √dh. The dot product of two such vectors is bounded by the Cauchy–Schwarz inequality: |LN(q)·LN(k)| ≤ ||LN(q)|| · ||LN(k)|| ≈ dh. Divide by √dh and the logit is bounded on the order of √dh — a constant set by head dimension, not something the weights can inflate without limit.

Why this stops the runaway loop

In the unnormalized block, the gradient could grow q·k by simply scaling up WQ, WK. With QK-LayerNorm in the path, scaling those weights up changes the mean and variance that LayerNorm immediately divides out. The norm of LN(q) is essentially invariant to the scale of q. So the positive-feedback channel — "make the weights bigger to make the winning logit bigger" — is cut. The logits cannot escape to infinity, the softmax cannot collapse, and the entropy stays healthy. Training is stable.

A worked example: LayerNorm caps a blown-up vector

Suppose mid-training the raw query for one head is q = (10, 2, −4, 0) (dh = 4) and the weights have inflated it to 10q = (100, 20, −40, 0). Without QK-LN, the key k = (1, 1, 1, 1) gives a logit (100+20−40+0) = 80 before scaling — large, sharpening softmax. With QK-LN we normalize first.

For q: mean μ = (10+2−4+0)/4 = 2. Centered: (8, 0, −6, −2). Variance σ² = (64+0+36+4)/4 = 26, σ = 5.10. Normalized (taking γ=1, β=0): (1.569, 0, −1.177, −0.392). Now scale q by 10: mean 20, centered (80, 0, −60, −20), variance 2600, σ = 50.99, normalized = (1.569, 0, −1.177, −0.392) — identical. LayerNorm is invariant to the overall scale of its input. The weights inflating by 10× changed the logit by a factor of one. That is the entire mechanism.

QK-LayerNorm caps the logit no matter how big the weights grow

Slide the weight-scale up. Without QK-LN (red) the logit blows up linearly with weight scale. With QK-LN (teal) the logit is pinned to a constant band — the runaway loop has no channel left. This is the whole stability fix in one chart.

weight scale 1.0×

Cost and placement

QK-LayerNorm adds two tiny LayerNorms per head per layer, operating on dh-dimensional vectors. Relative to the [d, d] projections and the [d, 4d] MLP, this is a negligible amount of compute and parameters — fractions of a percent. It is applied only to q and k, not to v: v carries the content to be aggregated and we do not want to normalize away its magnitude information; only the similarity computation (q·k) needs taming.

Concept + realization: QK-LayerNorm is the same LayerNorm you already know, inserted at exactly one spot — between the Q/K projections and the dot product — because that is the one spot where an unbounded quantity feeds a saturating nonlinearity (softmax). The lesson generalizes: stability bugs at scale usually trace to an unbounded value entering a saturating function. Find that junction; normalize there.
Common misconception: "QK-LayerNorm normalizes Q, K, and V." It normalizes only Q and K. Normalizing V would erase magnitude information in the values being aggregated and is not what the paper does — the instability lives entirely in the q·k similarity feeding softmax, so that is the only place to intervene.
python
import torch, torch.nn as nn

class AttnQKNorm(nn.Module):
    def __init__(self, d_model, n_heads):
        super().__init__()
        self.h = n_heads
        self.dh = d_model // n_heads
        self.qkv = nn.Linear(d_model, 3 * d_model)
        self.proj = nn.Linear(d_model, d_model)
        # the two extra LayerNorms — over the per-head dim only
        self.q_norm = nn.LayerNorm(self.dh)
        self.k_norm = nn.LayerNorm(self.dh)

    def forward(self, x):
        B, T, D = x.shape
        q, k, v = self.qkv(x).chunk(3, dim=-1)
        q = q.view(B, T, self.h, self.dh)
        k = k.view(B, T, self.h, self.dh)
        v = v.view(B, T, self.h, self.dh)
        # QK-LayerNorm: cap the logits BEFORE the dot product
        q = self.q_norm(q)
        k = self.k_norm(k)            # note: v is NOT normalized
        scores = torch.einsum('bthd,bshd->bhts', q, k) / self.dh**0.5
        a = scores.softmax(-1)
        out = torch.einsum('bhts,bshd->bthd', a, v).reshape(B, T, D)
        return self.proj(out)
Why does QK-LayerNorm prevent the attention logits from running away, and why is it applied to Q and K but not V?

Chapter 4: Parallel Layers — Attention and MLP, Side by Side

This is the architectural reorganization at the heart of the labs. Recall the standard, sequential ViT block: attention runs, its output is added back, that result is normalized and fed into the MLP, whose output is added back again. The MLP's input depends on the attention's output.

Sequential:   z' = z + Attn(LN1(z));   out = z' + MLP(LN2(z'))

ViT-22B (following GPT-J and PaLM) uses a parallel block. Attention and the MLP both read the same normalized input, run independently, and their outputs are summed into a single residual:

Parallel:   out = z + Attn(LN(z)) + MLP(LN(z))

Read those two formulas carefully — the difference is small on the page but consequential. In the sequential version, the MLP sees LN₂(z'), which includes the attention update. In the parallel version, the MLP sees LN(z), the original input, with no knowledge of what attention computed this layer. The two sublayers are now independent functions of the same input, and only meet when their outputs are added.

Why would you give up the dependency?

Three concrete wins, all about systems efficiency, with negligible quality cost at scale:

(1) One LayerNorm instead of two. The sequential block normalizes twice per block (before attention, before MLP). The parallel block shares a single LayerNorm feeding both branches. Over 48 layers that halves the LayerNorm count.

(2) Fused QKV and MLP-input matmuls. Because attention and MLP both consume the same LN(z), their first linear projections can be combined into one larger matrix multiply. Instead of a [d, 3d] QKV matmul and a separate [d, 4d] MLP-up matmul, you do a single [d, 3d+4d] = [d, 7d] matmul. Likewise the output side fuses WO [d, d] and the MLP-down [4d, d] into one combined linear. Bigger matmuls run at higher hardware utilization than many small ones — fewer kernel launches, better tiling, more arithmetic per byte moved.

(3) Fewer communication barriers. On a sharded model, each linear layer ends with a cross-device reduction. Sequential attention-then-MLP forces those reductions to happen one after another (the MLP cannot start until attention's reduction lands). Fusing them lets the two reductions be combined and overlapped, which is exactly the asynchronous-linear idea of the next chapter. The paper reports the parallel layout gives a substantial throughput improvement at 22B scale.

A worked example: same input, summed outputs

Let z be one token's representation, LN(z) = u = (1, −1) for a tiny d = 2. Say attention contributes a = Attn(u) = (0.4, 0.2) and the MLP contributes m = MLP(u) = (−0.1, 0.5), both computed from the same u. Sequential would instead feed the MLP the post-attention vector z + a then re-normalize; parallel just adds: out = z + a + m. If z = (2, 3), out = (2+0.4−0.1, 3+0.2+0.5) = (2.3, 3.7). The attention and MLP never saw each other's work this layer — they communicate only through the residual stream, one layer later.

Sequential vs Parallel block — toggle and compare

Toggle between the two block layouts. Sequential (left wiring): LN₂ feeds MLP from the post-attention vector — a dependency chain. Parallel (right wiring): one LN feeds BOTH branches from the same input; outputs are summed. Notice the parallel version has one fewer LayerNorm and lets the first matmuls fuse.

Standard ViT block

The cost: a small loss of expressivity

Is anything lost? In principle, yes: in the parallel block the MLP can no longer react to this layer's attention output — it must wait for the next layer to see it through the residual stream. Empirically, at large width and depth this barely matters: the residual stream already mixes both contributions, and the next layer's LN sees their sum. The paper, like PaLM before it, found the quality difference negligible while the speedup is real. This is a recurring theme in large-scale training: trade a sliver of theoretical expressivity for a large, concrete systems win.

Why it works: a deep residual network is a sum of many small functions of a shared stream. Whether attention and MLP at layer L are summed simultaneously (parallel) or in sequence (sequential), the network as a whole can represent very similar functions — the difference is a one-layer delay in cross-talk between the two sublayers, which deep stacks absorb easily. So you keep the modeling power and pocket the hardware efficiency.
Common misconception: "Parallel layers means the model runs attention and MLP on different data or different tokens in parallel." No — both sublayers process the SAME tokens and the SAME normalized input. "Parallel" refers to the composition: they are independent branches summed into one residual, rather than chained. The parallelism that helps is that their matmuls can be fused and their communication overlapped.
python
# Parallel block (ViT-22B / PaLM style)
class ParallelBlock(nn.Module):
    def __init__(self, d, n_heads, mlp_mult=4):
        super().__init__()
        self.norm = nn.LayerNorm(d)        # ONE shared norm
        self.attn = AttnQKNorm(d, n_heads)  # with QK-LayerNorm inside
        self.mlp  = nn.Sequential(
            nn.Linear(d, mlp_mult * d), nn.GELU(),
            nn.Linear(mlp_mult * d, d))

    def forward(self, z):
        u = self.norm(z)            # both branches read the SAME u
        # out = z + Attn(u) + MLP(u)  — summed into one residual
        return z + self.attn(u) + self.mlp(u)
What is the defining difference between a parallel and a sequential Transformer block, and what does it buy?

Chapter 5: Asynchronous Parallel Linear Operations

The parallel block sets up the third trick. On a model sharded across a device mesh, a single big linear layer y = xW is not one operation — it is a local matmul on each chip followed by a collective communication to assemble the result. The two costs are different in kind: matmul is compute-bound and lives in the fast on-chip arithmetic units; the collective is bandwidth-bound and crosses the slow inter-chip network.

If you run them strictly in order — matmul, then wait for the all-reduce, then the next matmul — the expensive arithmetic units sit idle during every communication step, and the network sits idle during every matmul. Utilization is poor on both. The idea behind asynchronous parallel linear operations is to overlap them: start the communication for one tile of the output while still computing the matmul for the next tile, so compute and communication run at the same time.

total ≈ max(Tcompute, Tcomm)  (overlapped)  vs.   Tcompute + Tcomm  (serial)

If compute and communication take roughly equal time, overlapping them nearly halves the wall-clock cost of the layer. The parallel block makes this far easier: because attention's and the MLP's first matmuls are fused and read the same input, there is a single large matmul whose output tiles can be streamed into a single overlapped collective, rather than several small matmuls each with its own barrier.

A worked example: serial vs overlapped

Say a layer's matmul takes 10 ms and its cross-device all-reduce takes 8 ms. Done serially, the layer takes 10 + 8 = 18 ms. With perfect overlap (start reducing the early output tiles while computing the late ones), the layer takes max(10, 8) = 10 ms — a 1.8× speedup. Over L = 48 layers and millions of steps, that compounds into days of training time saved and is a large fraction of why 22B was feasible on the available hardware budget.

Compute / communication overlap timeline

Top bar: serial execution — matmul finishes, THEN the all-reduce runs, then idle gaps. Bottom bar: asynchronous — the communication slides under the compute. Drag to change how communication-heavy the layer is and watch the overlapped time track max(compute, comm), not their sum.

comm / compute 0.8

Why the architecture and the systems are co-designed

This chapter is where it becomes undeniable that ViT-22B's "architecture" cannot be cleanly separated from the hardware it runs on. The parallel block was chosen partly because it makes the matmuls fusible and the collectives overlappable. QK-LayerNorm was chosen partly because it adds almost no cost to those matmuls. The model is shaped by the shape of the TPU pod. The paper is as much a distributed-systems contribution as an architecture one — it shows a concrete recipe (in JAX, with GSPMD-style sharding annotations) for training a dense 22B vision model efficiently.

The systems lesson: at scale, the bottleneck shifts from FLOPs to memory movement and communication. A faster model is often not one with fewer FLOPs but one whose FLOPs and bytes can be overlapped. ViT-22B's three tricks all serve this: QK-LN keeps it trainable, parallel layers create big fusible matmuls, async linear ops hide the communication behind them.
Common misconception: "Asynchronous linear ops change the math / the result of the layer." They do not — the computed output y = xW is bit-for-bit the same. Only the scheduling changes: communication for early output tiles overlaps with compute for later ones. It is a pure wall-clock optimization, not an approximation.
What do asynchronous parallel linear operations optimize, and why does the parallel block help?

Chapter 6: Frozen-Feature Transfer

Now the payoff. The cleanest way to ask "how good is a representation?" is to freeze the backbone — never update a single weight — and train only a tiny linear classifier on top of its features. This is the linear probe. If the frozen features are linearly separable for a downstream task, a single matrix can read them out; if not, no amount of linear readout will help. Linear-probe accuracy is therefore a direct measure of representation quality, with no fine-tuning to muddy the comparison.

freeze φViT-22B;   train only W:   ŷ = softmax(W · φ(x))

Why care about frozen transfer specifically? Because a 22B model is expensive to fine-tune — you would have to store optimizer state and gradients for all 22B parameters per downstream task. If the frozen features are already excellent, you skip all of that: extract features once, train a cheap linear head per task, and reuse the same frozen backbone for everything. ViT-22B reports exactly this — its frozen features are strong across a wide battery of classification tasks, often rivaling fully fine-tuned smaller models. Scale converts the backbone into a reusable, general feature service.

A worked example: why frozen probing is a clean test

Imagine a task with 1000 classes and a feature dimension d = 6144. A linear probe is a single [6144, 1000] matrix — about 6.1M parameters, trivially cheap to train. If ViT-22B's frozen 6144-dim CLS feature lets that linear layer reach, say, the high-80s top-1 on ImageNet, it tells you the 22B backbone has already arranged its feature space so that classes are linearly separable — the hard work is done by the representation, not the readout. Contrast a weaker backbone whose linear probe lags its fine-tuned number by many points: its features need nonlinear untangling, so fine-tuning is doing real work. The smaller the probe-vs-finetune gap, the better the frozen representation.

Linear probe vs fine-tune gap shrinks with scale

For each model size, the teal bar is frozen linear-probe accuracy and the warm outline is full fine-tune. As scale grows, the gap between them shrinks — the frozen features get close to what fine-tuning achieves. ViT-22B sits at the right, where the gap is smallest (illustrative trend, not exact paper numbers). Drag to sweep scale.

model scale ViT-H

Robustness and out-of-distribution transfer

The paper also evaluates ViT-22B features on out-of-distribution and robustness benchmarks (ImageNet variants like ImageNet-R, ImageNet-A, and others), on dense tasks like depth estimation and segmentation via frozen features, and on fairness/calibration. The recurring finding is that the large frozen backbone transfers gracefully — it does not just memorize ImageNet, it learns features that generalize to shifted distributions and to tasks it was never trained on. This is the practical argument for one very large, frozen, shared backbone over many task-specific fine-tunes.

Why frozen features get better with scale: a bigger model trained on enough data is forced to discover features that are generally useful, because no single task can absorb all its capacity. Those general features happen to be linearly separable for many downstream tasks. Fine-tuning a small model contorts its few features to one task; a huge frozen model already contains the features many tasks need, so a linear readout suffices.
Common misconception: "A linear probe is weaker than fine-tuning, so a high probe score just means the task is easy." A high linear-probe score on a hard task is strong evidence the representation is good — it means a single linear layer can read out the answer, which is only possible if the backbone already untangled the classes. The smallness of the probe is the point: it isolates representation quality from readout capacity.
What does a small gap between linear-probe and fine-tune accuracy tell you about a backbone?

Chapter 7: Shape Bias & Human-Perception Alignment

Here is the most surprising result, and it is not about accuracy at all. When you classify a "cat-shaped object painted with elephant skin texture," what is it? Humans overwhelmingly say cat — we classify by shape. Standard ImageNet-trained CNNs say elephant — they classify by texture (Geirhos et al., 2019). The fraction of such cue-conflict images a model labels by shape is its shape bias; the rest is texture bias. Humans sit around 90–96% shape; a typical ResNet sits around 20–30% shape (i.e. mostly texture).

ViT-22B's headline perceptual finding: its shape bias rises dramatically compared to smaller models and CNNs — the paper reports it reaching levels far closer to the human range than prior vision models, a substantial shift along the shape–texture axis. The largest model is, in this specific and measurable sense, the most human-like vision model reported at the time.

shape_bias = (# images classified by SHAPE) / (# classified by shape OR texture)

How shape bias is measured

The cue-conflict test set (Geirhos et al.) takes an image with one object's shape and another object's texture, restricted to the cases where the model picks one of the two conflicting labels. Among those, shape_bias is the fraction where it chose the shape label. A pure texture classifier scores 0; a pure shape classifier scores 1. Plot a model as a single point on a shape-vs-texture axis and you can place it relative to the human band.

A worked example

Suppose on 16 cue-conflict categories a model, restricted to shape-or-texture answers, picks the shape label 13 times and the texture label 3 times. Its shape bias is 13/16 = 0.81 = 81%. A ResNet on the same set might pick shape only 4 times: 4/16 = 25%. Humans pick shape ~15 of 16: ~94%. The number is a single fraction, but it encodes which cue the model trusts when forced to choose — and ViT-22B's number moved far toward the human end of that line.

The shape–texture axis: where models sit relative to humans

A single axis from pure texture (left) to pure shape (right). CNNs cluster on the texture side; the human band sits far right. As you scale the ViT up (slider), its marker slides toward the human band — ViT-22B lands closest. Illustrative placement of the qualitative trend the paper reports.

model ViT-L

Beyond shape: error consistency and calibration

Shape bias is one slice of a broader claim: ViT-22B's behavior aligns more with human perception. The paper also looks at error consistency — do the model and humans make mistakes on the same images? — and finds ViT-22B's errors are more human-consistent than smaller models'. It examines calibration (are the model's confidences well-matched to its accuracy?) and reports improvements. The thread tying these together: scaling did not merely make a better ImageNet scorer; it nudged the entire perceptual profile of the network toward the way people see.

Why might scale do this? One hypothesis the community offers: shape is a more global, relational cue than texture, and self-attention over the whole image — given enough capacity and data — can integrate global structure that small or convolutional models, biased toward local texture statistics, miss. A 22B ViT has the capacity to represent and rely on global shape, so it does. This is a representational consequence of the architecture-plus-scale combination, not something explicitly trained for.

Why this matters: a model whose biases and errors match humans is more predictable to humans — easier to anticipate, audit, and trust. Shape bias is also tied to robustness: shape-based classifiers tend to be more robust to texture-level corruptions and distribution shift, which dovetails with ViT-22B's strong OOD results from Chapter 6.
Common misconception: "High shape bias was a training objective — they trained ViT-22B to be human-like." It was not. Shape bias is an emergent property measured after training on standard image-classification data. Nothing in the loss rewards shape over texture; the bias shifted as a side effect of scale and the attention architecture's ability to use global structure.
What is "shape bias," and what did ViT-22B reveal about it?

Chapter 8: The ViT-22B Block Explorer

This is the payoff simulation — the paper's two core architectural ideas, live and interactive. The explorer runs a single attention head over a 6-token patch sequence and lets you (a) toggle QK-LayerNorm on or off and inflate the query/key weights to watch entropy collapse appear and be cured, and (b) switch the block layout between sequential and parallel to see how the residual output is assembled. Everything is computed from real arithmetic in the browser — the bars are actual softmax weights, the entropy is the actual Shannon entropy.

Drive it like an experimentalist. First, turn QK-LN off and crank the weight scale: the attention bars sharpen to one-hot and the entropy readout crashes toward zero — that is the divergence of Chapter 2, frozen as a control. Then flip QK-LN on and crank the same slider: the bars stay spread, the entropy holds up — the logits are capped (Chapter 3). Finally, toggle the block layout and watch which input the MLP branch reads (the post-attention vector in sequential, the shared normalized input in parallel) and how the residual output is summed (Chapter 4).

Interactive ViT-22B block: QK-LN + parallel layers

One head, 6 patch tokens. Top: attention weights for the selected query token, with the live entropy readout. Bottom: the block-composition diagram (sequential vs parallel). Toggle QK-LN and the layout; slide the weight scale and the query selector.

query token sat
weight scale 1.0×

What you should take away from playing with it: the two ideas are independent levers. QK-LayerNorm is about numerical stability — it governs whether the run survives. Parallel layers are about composition and systems efficiency — they govern how fast each surviving step is. ViT-22B needed both: stability to start, efficiency to finish in a reasonable budget. Remove either and 22B is out of reach — without QK-LN it diverges; without the parallel-layer / async-linear efficiency it is too slow to train on the available hardware.

The unifying picture: a Transformer block at extreme scale is a numerical object (which can diverge) and a systems object (which can stall). ViT-22B is the case study where treating it as both at once — fixing the divergence with QK-LN and the stall with parallel + async-linear execution — is what unlocked the next order of magnitude.

Chapter 9: Limitations, Connections & Cheat Sheet

ViT-22B is a milestone, not a finish line. Honest limitations:

Dense and expensive. 22B dense parameters are activated for every patch of every image. Sparse mixture-of-experts vision models can reach larger nominal parameter counts at a fraction of the per-image FLOPs — ViT-22B deliberately chose dense to keep the architecture simple and the result a clean scaling data point, but density is a cost.

Data and compute access. The model is trained on a very large proprietary image dataset on a TPU pod. The recipe is reproducible in principle, but the resources are out of reach for most labs — a recurring equity concern with frontier-scale work.

Quadratic attention remains. QK-LayerNorm fixes the stability of attention but not its O(T²) cost in the number of tokens. High-resolution images mean many patches; the attention matrix still grows quadratically. Long-context / efficient-attention work is orthogonal and still needed.

Bias is shifted, not solved. Higher shape bias and better human-error-consistency are improvements in degree, not a guarantee of human-like robustness or fairness everywhere. The paper's own fairness analysis is a starting point, not a clean bill of health.

Where this sits in the literature

The lineage is direct: the original Transformer introduced self-attention and the sequential block; ViT applied it to image patches; ViT-22B is the scaling study that re-engineered the block to push an order of magnitude further. QK-LayerNorm and the parallel block both have roots in the language-model scaling literature (PaLM, GPT-J), which ViT-22B imports into vision.

Foundation
Attention Is All You Need — the original Transformer block this paper re-engineers.
Mechanism
Vision Transformer (ViT) — patchification and the base architecture that gets scaled here.
Component
Normalization — the LayerNorm that QK-LN reuses at a new spot in the block.

Related lessons

Cheat sheet

IdeaWhat it isWhy it matters
The wallNaive ViT scaling diverges via attention entropy collapseThe standard block is latently unstable at 22B — the problem the paper solves
Entropy collapseLogits run away → softmax goes one-hot → gradient vanishesDiagnostic signature of the divergence; measured by attention entropy → 0
QK-LayerNormLayerNorm Q and K (not V) before the dot productCaps the logit (norm-invariant to weight scale); kills the runaway loop, near-zero cost
Parallel layerout = z + Attn(LN(z)) + MLP(LN(z)) — same input, summedOne shared LN, fusible big matmuls, fewer comm barriers; negligible quality cost
Async linear opsOverlap cross-device communication with on-chip matmulLayer time → max(compute, comm) not their sum; hides communication behind compute
Frozen transferFreeze backbone, train only a linear probe22B frozen features rival fine-tuned smaller models; one reusable backbone
Shape biasFraction of cue-conflict images classified by shape vs textureShifts dramatically toward humans — emergent from scale, not trained for
Co-designArchitecture chosen to fit the TPU pod's matmul + comm profileThe model is shaped by the hardware; stability and systems are inseparable at scale
The one-sentence takeaway: ViT-22B's contribution is not "22 billion parameters" — it is the demonstration that the standard Transformer block breaks at that scale and the precise, cheap surgery (QK-LayerNorm for stability, parallel layers + asynchronous linear ops for efficiency) that fixes it, yielding a frozen backbone whose representations are not only strong but measurably more human-like.