Back to blog
ResearchModels

Intelligence Ladders: One Set of Weights, Every Depth a Model

Needle 3 is trained so that any depth from 2 to 20 layers is a deployable model. This is how the subnetworks are chosen, how they are trained without training five models, and what each one scores.

HN

Henry Ndubuaku

||12 min read

Needle 3 runs on watches, Raspberry Pis and phones. Each device has a different memory budget, so each wants a different model size. Training one model per size means several training runs, several files and a separate fine-tune for each. Needle 3 is one set of weights. Every depth from 2 to 20 layers is a trained model, and all of them run on the same engine. We call this an intelligence ladder.

Blocks and the residual stream

A transformer is a stack of blocks. Needle 3 has twenty, f0,…,f19f_0, \dots, f_{19}. They share one running vector, the residual stream. Block ℓ\ell reads the stream, computes an update, and adds it:

xℓ+1=xℓ+fℓ(xℓ).x_{\ell+1} = x_\ell + f_\ell(x_\ell).

Because each block only adds to the stream, skipping a block means adding nothing, the same fact that stochastic depth and LayerDrop use during training. The stream passes through unchanged and the model is simply shallower. Two questions remain: which blocks to skip, and how to make the shallow models good.

Which blocks make a subnetwork

A subnetwork of depth dd is a set Sd⊆{0,…,19}S_d \subseteq \{0, \dots, 19\} of blocks, run in their original order. The sets must nest, S2⊂S3⊂⋯⊂S20S_2 \subset S_3 \subset \cdots \subset S_{20}, so that one set of weights serves all of them. The chosen blocks must also stay spread through the stack, so that a shallow model sees early and late computation rather than only the first few blocks.

One rule gives both. Start from the two ends, then repeatedly split the widest gap between chosen blocks at its midpoint:

S2={0, L−1},Sd+1=Sd∪{⌊a+b2⌋},(a,b)=arg⁡max⁡a<b adjacent in Sd(b−a),S_2 = \{0,\ L-1\}, \qquad S_{d+1} = S_d \cup \Big\{\Big\lfloor \tfrac{a+b}{2} \Big\rfloor\Big\}, \quad (a, b) = \arg\max_{\substack{a<b \text{ adjacent in } S_d}} (b - a),

with ties going to the leftmost gap. Each step only adds a block, so the sets nest. Each step halves the largest hole, so the coverage stays balanced.

depth 2largest gap 0..19 · midpoint ⌊(0+19)/2⌋ = 9 joins next012345678910111213141516171819order so far: 0 19ties break toward the leftmost gap · the sequence is fixed, so every depth nests inside the next
How the order is built. Start with the two endpoints, then repeatedly split the widest remaining gap at its midpoint. Twenty blocks give one fixed sequence, and the first d entries of it are subnetwork d.

Twenty blocks give one fixed sequence, 0,19,9,14,4,6,11,16,2,7,12,17,1,3,5,8,10,13,15,180, 19, 9, 14, 4, 6, 11, 16, 2, 7, 12, 17, 1, 3, 5, 8, 10, 13, 15, 18. The subnetwork of depth dd is its first dd entries.

8 of 20 blocks runskipped blocks pass the residual stream through unchanged0111329314455156671081693101711712111318144151916817121820192selection order· engram sites (kept when their block is kept)S8 = {0, 4, 6, 9, 11, 14, 16, 19}
Every subnetwork keeps block 0 and block 19 and fills in the interior by bisection, so each depth is a superset of the one below it. The number above each block is its rank in that order.

Running a subnetwork

With 1[ℓ∈Sd]\mathbb{1}[\ell \in S_d] equal to 1 when block ℓ\ell is in the set and 0 otherwise, the forward pass at depth dd is

xℓ+1=xℓ+1[ℓ∈Sd] fℓ(xℓ),ℓ=0,…,L−1,x_{\ell+1} = x_\ell + \mathbb{1}[\ell \in S_d]\, f_\ell(x_\ell), \qquad \ell = 0, \dots, L-1,

followed by the same final normalisation and the same output layer as the full model.

depth 20 · 20 of 20 blocks run · 100% of the FLOPs, cache and bytesx ← x + f(x) at a kept block · x ← x at a skipped one0+f1+f2+f3+f4+f5+f6+f7+f8+f9+f10+f11+f12+f13+f14+f15+f16+f17+f18+f19+fnext x = x + (1 if kept, else 0) · f(x) · same blocks, same final norm, same output layera skipped block reads no weights and writes no KV cache
Running a subnetwork. Depth d keeps the first d blocks of the bisection order and skips the rest, and a skipped block is the identity on the residual stream. Depth 8 is exactly an 8-layer model in compute, cache and file size.

Three details make this hold in the real architecture:

  • Needle's residual stream has four parallel lanes, and blocks read and write them in round-robin order. Inside a subnetwork the order is renumbered over the blocks that remain, so consecutive surviving blocks still alternate lanes.
  • The engram memory sites and the global-attention layers belong to specific blocks. They are kept when their block is kept and dropped when it is dropped.
  • The KV cache is per block, so a shallower model also has a proportionally smaller cache.

Training every depth at once

Adding one loss term per depth to every training step would cost L−1L - 1 forward passes per step. Instead, each step samples one path. With probability 0.80.8 it is the full model and the step is an ordinary language-modelling step. Otherwise a depth dd is drawn uniformly from {2,…,L−1}\{2, \dots, L-1\}, only the blocks in SdS_d run, and the loss is scaled by the fraction of the model that took part:

Lstep={CE(pL)with probability 0.8,d2L[CE(pd)+λ KL(sg⁡[pL] ∥ pd)],d∼U{2,…,L−1}with probability 0.2.\mathcal{L}_{\text{step}} = \begin{cases} \mathrm{CE}(p_L) & \text{with probability } 0.8,\\[4pt] \dfrac{d}{2L}\Big[\mathrm{CE}(p_d) + \lambda\, \mathrm{KL}\big(\operatorname{sg}[p_L]\,\|\,p_d\big)\Big], \quad d \sim \mathcal{U}\{2, \dots, L-1\} & \text{with probability } 0.2. \end{cases}

pdp_d is the next-token distribution at depth dd, CE\mathrm{CE} is cross-entropy against the true next token, and sg⁡\operatorname{sg} is a stop-gradient: the full model's prediction is a fixed target on that step, and no gradient flows into it.

The KL term does most of the work for the shallow depths. Cross-entropy asks a 3-layer subnetwork to predict the next token, which it can barely do, and its gradient is small. The KL term asks it to predict what the whole network predicts. The full model is the teacher, each subnetwork is a student, and because they share every weight, the teacher costs no extra forward pass. This is self-distillation, with λ=1\lambda = 1.

One path per optimizer stepfull model with probability 0.8 · otherwise one depth drawn uniformly from 2..192L10L20L71331795steps →full model, plain losssubnetwork d
A typical stretch of training. A subnetwork step runs only the blocks in S_d, weights its loss by d/L, and, on the paired steps, is pulled toward the full model's predictions by a KL term. Nothing is ever trained twice: the subnetwork shares every weight with the full model.

Each step trains one depth. Averaged over many steps, this gives the same expected loss as training every depth on every step, and it costs one forward pass instead of eighteen.

The ladder also improves the full model. We trained the same 18-layer architecture twice for 3,000 steps on the same data, once with the ladder and once without. With the ladder the full-depth validation loss was 1.958; without it, 2.037. The ladder model was ahead at every checkpoint, and its 16-layer exit alone matched the control's full 18 layers. Every prefix of the stack has to predict well on its own, so the early blocks cannot leave the work to the later ones, and no single block can become one the model depends on.

validation loss, 18 layers, 3,000 steps2.02.22.42.62.8500100015002000250030001.958 ladder2.037 controlbits per byte by depth, ladder run1.542L0.994L0.858L0.7712L0.6916L0.6618Lsame architecture, data, optimiser and steps; the only difference is the sampled-depth lossdashed line: the control's full 18 layers at 0.686 bits per byte
Left: validation loss during training for the same 18-layer network with and without the ladder. The ladder run is lower at every checkpoint and finishes 3.9% lower. Right: bits per byte of the ladder run at each depth. At 16 layers it scores 0.689, the same as the control at all 18 layers, 0.686.

The numbers behind the figure. Bits per byte is the validation text loss in a unit that does not depend on the tokenizer; lower is better.

run, 18 layers, 3,000 stepsvalidation loss (nats)bits per byte at 18Lat 16Lat 12Lat 8Lat 4Lat 2L
control, full depth only2.0370.686
ladder from step 01.9580.6600.6890.7690.8550.9911.538
ladder switched on late in training2.0590.6940.7360.8360.9080.9961.675

Two things follow. The ladder costs the full model nothing and gains it 0.079 nats, 3.9% of the loss. And the ladder has to be there from the start: switching it on late gives worse subnetworks at every depth and a slightly worse full model, 1.1% above the control, because the blocks have already specialised around a fixed depth.

What each depth of the ladder-trained model keeps and what it costs, against its own full depth. The parameters kept are the surviving blocks with the engram sites and the confidence rows that belong to them; the embeddings and the final layers are shared by every depth.

depth18L16L12L8L4L2L
parameters kept100%93%80%55%31%24%
bits per byte0.6600.6890.7690.8550.9911.538
loss change+4.4%+16.7%+29.6%+50.3%+133%

Down to 4 layers the loss grows more slowly than the parameters shrink. At 2 layers it more than doubles.

What each depth scores

Every depth from 2 to 20 layers ships in the one Needle 3 file, and needle build --layers picks any of them. We benchmarked four of them on two tool-calling suites, sliced from the same checkpoint and run through the same engine with the confidence gate on.

One set of weights, four models025507510011.721.04L29M · 30 MFLOPs/tok36.836.58L52M · 48 MFLOPs/tok80.740.016L98M · 83 MFLOPs/tok86.047.020L121M · 100 MFLOPs/tokMobile ActionsDroidCall
Exact-match accuracy of Needle 3 at the four depths we benchmarked, every one sliced from the same 20-layer weights and run through the same engine with the confidence gate on. Any depth from 2 to 20 can be built the same way. Mobile Actions has 961 rows, DroidCall 200.

The 2-layer subnetwork is absent because at 2 layers the base model's confidence head withholds almost every call, so its gated score is zero, and with calls forced it scores 20.5 on DroidCall. Two layers of a generalist is not a product. Two layers fine-tuned on one product's tools is, which is the next figure.

Every subnetwork before and after fine-tuning on the suite, both scored with forced calls, against DeepSeek V4 Flash through its cloud API. Toggle between DroidCall and Mobile Actions.

Fine-tuning lifts every depth by 18 to 36 points on DroidCall, and from 4 layers up the tuned subnetwork passes DeepSeek V4 Flash. The 2-layer model goes from unusable to 56.5. A small network trained on one narrow task reaches frontier accuracy on that task, and the ladder is what lets you choose how small.

Fine-tune once, deploy any depth

Because the subnetworks share weights, one fine-tune is a fine-tune of all of them. The LoRA adapter is trained on the frozen base at the full 20 layers, merged into the weights, then sliced:

θd=slice(θ+BA, Sd),\theta_d = \mathrm{slice}\big(\theta + BA,\ S_d\big),

where BABA is the low-rank update and slice\mathrm{slice} keeps the blocks in SdS_d, the engram tables of their sites, and the rows of the confidence head that belong to them.

A sliced model has its own block numbering, 0 to 15 for a 16-layer slice. Running the bisection rule on that numbering picks a different set of blocks from the parent's, blocks that were never trained together as a subnetwork. Of the 14 depths of a 16-layer slice, 13 differ between the two rules.

a 16-layer slice, cut again to depth 8with the parent's orderthe first 8 of 0 19 9 14 4 6 11 16 …, the blocks that were trained together012345678910111213141516171819with a fresh order on the 16 blocksa different set: blocks that never trained as a unit012345678910111213141516171819faded blocks are not in the 16-layer slice · of its 14 depths, 13 differ between the two rules
The re-slicing trap. A slice has its own block numbering; run the bisection rule on that numbering and you pick blocks that were never trained as a subnetwork. Every slice therefore carries its parent's order, so slicing a slice equals slicing the original.

So every slice carries its parent's selection order, and slicing a slice equals slicing the original. In the Python package:

needle finetune data.jsonl --epochs 10 --out adapter.safetensors
needle build --lora adapter.safetensors --layers 8 --platform linux-arm64 --out ./pi

The same ladder exists along width, where each sampled subnetwork is a depth and a channel prefix of every matrix, as in Matryoshka representations and MatFormer. The shipped Needle 3 exposes depth.

What it costs

At training time, a sampled step is cheaper than a full step, so the ladder adds no wall-clock time per step. The price is that 20% of steps update only part of the model, which the self-distillation term recovers.

At inference time there is no cost. A subnetwork of depth dd is exactly a dd-layer model in operations, in cache and in file size. The blocks are the same bytes at every depth, so file size is a straight line in dd.

One file, and what each depth of it weighssize(d) ≈ 2.75 MB of embeddings and heads + 1.3 MB per block · 2-bit weights10 MB20 MB29 MB52L84L116L138L1610L1912L2114L2416L2618L2920Ldepth 8 is a subset of depth 20, so one file serves every depth
What a depth costs on disk. Every block is the same bytes at every depth, so the size of a subnetwork is a straight line in d: about 8 MB at 4 layers, 29 MB at 20.

A device can hold the full 29 MB file and choose a depth per request, a shallow pass for a simple command and the full stack for a hard one, with no second download. That part is not shipped yet.

References

  1. He et al., Deep Residual Learning for Image Recognition, 2015.
  2. Huang et al., Deep Networks with Stochastic Depth, 2016.
  3. Fan et al., Reducing Transformer Depth on Demand with Structured Dropout, 2019.
  4. Hinton et al., Distilling the Knowledge in a Neural Network, 2015.
  5. Kusupati et al., Matryoshka Representation Learning, 2022.
  6. Devvrit et al., MatFormer: Nested Transformer for Elastic Inference, 2023.
  7. Cai et al., Once-for-All: Train One Network and Specialize it for Efficient Deployment, 2019.
  8. Hu et al., LoRA: Low-Rank Adaptation of Large Language Models, 2021.