Quantifying the Per-layer Contribution of LLMs
Setup设置
The baseline is the MuonH Qwen3 recipe of the Marin speedrun, from 130m to 1.2B. We add a next-token loss after every layer and judge each layer by its final training loss against backbone compute 6ND, where N counts the parameters of the layers up to that one, without the embedding and the heads, and D the training tokens. Code
基线是 Marin speedrun 里的 MuonH Qwen3 配方,规模从 130m 到 1.2B。我们在每一层后面加一个预测下一个词的损失,用每层的最终训练损失来衡量;横轴是骨干算力 6ND,N 是到这一层为止各层的参数量,不算 embedding 和头,D 是训练 token 数。代码
--- baseline loss (simplified)+++ per-layer losses (simplified; the Code link has the real code) def loss_fn(model, tokens): targets = tokens[1:] x = model.embed(tokens[:-1])- for block in model.blocks:+ loss = 0.0+ for k, block in enumerate(model.blocks[:-1]): x = block(x)- return cross_entropy(model.head(model.norm(x)), targets)+ # probes: read the layer, but send no gradient into the model+ h = stop_gradient(x) if probe else x+ # every earlier layer has its own norm and output head, and predicts the next token+ logits = model.layer_heads[k](model.layer_norms[k](h))+ loss += cross_entropy(logits, targets)+ x = model.blocks[-1](x)+ # the usual loss at the last layer, at the same weight+ return loss + cross_entropy(model.head(model.norm(x)), targets)--- 基线损失(简化)+++ 逐层损失(简化;真实代码见“代码”链接) def loss_fn(model, tokens): targets = tokens[1:] x = model.embed(tokens[:-1])- for block in model.blocks:+ loss = 0.0+ for k, block in enumerate(model.blocks[:-1]): x = block(x)- return cross_entropy(model.head(model.norm(x)), targets)+ # 探针:读取这一层,但梯度不传回模型+ h = stop_gradient(x) if probe else x+ # 前面每一层都有自己的 norm 和输出头,也预测下一个词+ logits = model.layer_heads[k](model.layer_norms[k](h))+ loss += cross_entropy(logits, targets)+ x = model.blocks[-1](x)+ # 最后一层仍是原来的损失,权重相同+ return loss + cross_entropy(model.head(model.norm(x)), targets)
Experiments实验
Answered已有结论Passive and active: how much does each layer contribute?被动与主动:每一层贡献多少?
Read passively, the baseline's early layers predict far worse than ordinary models of the same depth and catch up only at the last layers. Trained actively, every layer comes close to an ordinary model of its depth, while the last layer ends a little worse than the baseline.
被动读取时,基线模型的前几层远不如同深度的普通模型,到最后几层才追上。主动监督时,每一层都接近同深度的普通模型,而最后一层比基线略差。
Every layer predicts through the model's output head, and every layer's loss trains that head.每一层都经过模型的输出头预测,每一层的损失都训练这个头。
Every layer predicts through the output head, but only the last layer's loss trains it.每一层都经过输出头预测,但只有最后一层的损失训练这个头。
Every layer predicts through a head of its own.每一层都用自己的头预测。
Every layer predicts through a head of its own, but no gradient flows back into the model: it trains exactly like the baseline.每一层都用自己的头预测,但梯度不传回模型:模型和基线训练得完全一样。
An ordinary model with fewer layers, 2 to 6, trained on its own with only its output head. Layer k is compared with the model of k layers.层数更少的普通模型,2 到 6 层,单独训练,只有自己的输出头。第 k 层和 k 层的模型比较。
Testing检验中Does a deeper network benefit from supervising its shallow layers?更深的网络能否从浅层监督中获益?
The 130m layer stacked 48 deep, every layer predicting through a head of its own.130m 的层堆到 48 层,每一层都用自己的头预测。
The same network with heads that take no gradient back: it trains as an ordinary 48-layer model.同样的网络,头的梯度不回传:它和普通的 48 层模型训练得完全一样。
Testing检验中Does the residual design change what each layer contributes?残差设计会不会改变每一层的贡献?
Normalize, transform, add back to the stream.先归一化,再变换,加回残差流。
A second normalization on the branch output before it is added: the baseline's own design.分支输出加回之前再归一化一次:基线自己的设计。
The normalized input is scaled by 1/√ℓ, more in deeper layers.归一化后的输入乘以 1/√ℓ,越深的层缩得越多。
No norm before the branch; the stream is scaled up by (2L)^¼ and normalized after the add.分支前不归一化;残差流乘以 (2L)^¼,相加后再归一化。
Norms before and after, with a residual gain equal to the number of sublayers.前后都归一化,残差增益等于子层数。
Four residual streams, mixed by learned weights, read into the branch and written back.四条残差流,由可学习的权重混合,读入分支再写回。
Hyper-connections with the stream mixing kept doubly stochastic.超连接,但流之间的混合矩阵保持双随机。
A layer's input is a learned softmax mix of every earlier output and the embedding.每层的输入是此前所有层输出和 embedding 的 softmax 加权混合。
The same mix over 8 block outputs and the running sum of the current block.同样的混合,只在 8 个块的输出和当前块的累加和上做。
Attention also reads the same token's keys and values from earlier layers.注意力还读取同一 token 在之前各层的 key 和 value。
Testing检验中Why does supervising shallow layers hurt the final performance?为什么浅层监督会损害最终性能?
Every layer loss has weight 1 and its gradient reaches every layer below it.每个逐层损失的权重是 1,梯度传到它下面的每一层。
Each layer loss is weighted 0.2, so the five sum to the final loss's weight.每个逐层损失的权重是 0.2,五个加起来等于最终损失的权重。
A layer loss trains its head and its own layer; its gradient stops before reaching the layers below.逐层损失只训练它的头和它所在的那一层;梯度不再传到下面的层。
Layer losses weighted 0.2, each training only its own layer.逐层损失权重为 0.2,并且各自只训练自己那一层。
Testing检验中Is the gap in the heads or in the features?差距在读出头,还是在特征?
Each finished 300m model keeps its backbone; only its heads train for 2,000 more steps.训练好的 300m 模型保留骨干网络,只让读出头再训练 2,000 步。
Takeaways核心结论
Acknowledgements致谢
The author is pleased to acknowledge that the work reported on in this post was substantially performed using the Princeton Research Computing resources at Princeton University. Princeton Research Computing is a consortium of groups including the Princeton Institute for Computational Science and Engineering (PICSciE) and Research Computing at Princeton University.
本文报告的工作主要使用普林斯顿大学 Princeton Research Computing 的计算资源完成。Princeton Research Computing 是由普林斯顿计算科学与工程研究所(PICSciE)和普林斯顿大学 Research Computing 等团队组成的联合体。
Experiment record实验记录
Citation
@misc{chai2026perlayer,
title = {Quantifying the Per-layer Contribution of LLMs},
author = {Chai, Wenhao},
year = {2026},
howpublished = {Blog post},
url = {https://wenhaochai.com/blogs/per-layer-contribution.html}
}