Can Jin1* · Yan Kang2 · Yifan Gong2 · Chongjian Ge2 · Mingze Xu2 · Yuanjun Xiong2 · Dimitris N. Metaxas1 · Hongwu Peng2
1Rutgers University 2Adobe Research
*Corresponding author: can.jin@rutgers.edu. Work done during an internship at Adobe Research.
Elastic pretraining trains several nested sub-networks of different sizes inside one weight-shared supernet, so that a single run serves several inference budgets. ShellElastic makes this scalable: its hidden dimensions form a dense core followed by shells, so one full-width forward pass computes every sub-network exactly and each step costs about as much as training the widest sub-network alone. μ-Elastic, an extension of μP to ShellElastic and other elastic models, keeps all sub-networks maximally updated at once and transfers hyperparameters tuned on a small non-elastic proxy to elastic models and to larger supernets. At three scales from 119M to 1.69B parameters, one ShellElastic run produces sub-networks that outperform MatFormer and fully elastic baselines at matched parameter counts and approach separately trained models that together take five times the steps.
ShellElastic (Figure 1) partitions the residual stream into a dense core followed by ordered shells, each a multiple of a base width g, and each supported sub-network is the core plus a prefix of the shells. Every hidden matrix is block lower triangular: a shell reads the core, the earlier shells and itself, but never a later shell. Trunk normalization acts within each group, attention heads align with the group boundaries, and every supported width has its own readout. One full-width forward pass therefore contains the exact hidden states of every sub-network as prefixes (Proposition 1), and the per-step compute stays close to that of a single full-width pass however many sub-networks are trained, so every step has a fixed workload, as in non-elastic training.
μ-Elastic (Figure 2) extends maximal update parameterization (μP) (Yang et al., 2021) to elastic models with two factors: a μ-Transfer factor m = g/d0 that carries HPs from a non-elastic proxy of width d0 to base width g, and a μ-Internal factor for the different widths inside one shared model. Every group reads the same input coordinates in every sub-network that contains it, so we set its initialization, learning rate and weight decay from this fan-in, while each readout uses its own input width (Table 1). This keeps every group maximally updated in all sub-networks at once (Theorem 1), which uniform scaling across groups cannot do in general (Proposition 2). The same two factors apply to MatFormer and to fully elastic models (Appendix D). The standard parameterization (SP) sets both factors and the FFN expansion e to one in the scaling rules and fixes the readout scalars αs = 1, preserving the architecture.
Recipe.
- Tune (σ0, η0, λ0) on a non-elastic proxy of width d0.
- Choose the base width g and the supported set 𝒮.
- Compute m = g/d0 and instantiate the parameterization in Table 1.
- Train the supernet on the joint objective (Equation 8).
Table 2. Final validation loss and mean 5-shot accuracy over 13 downstream tasks at three scales, labeled by sub-network size. Entries at the 119M–285M and 375M–906M scales average three runs; those at 675M–1.69B are single runs. †Five separately trained models, together taking 5× the steps of any other row. Bold marks the best of the four methods that train all five sizes in one run.
| Method | Val. loss ↓ | 5-shot acc. (%) ↑ | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Low | Medium | High | Extra | Max | Avg. | Low | Medium | High | Extra | Max | Avg. | |
| 119M–285M | ||||||||||||
| Standalone† | 3.369 | 3.308 | 3.264 | 3.219 | 3.191 | 3.270 | 35.6 | 35.8 | 36.6 | 37.1 | 37.1 | 36.5 |
| Sampled standalone | 3.667 | 3.609 | 3.583 | 3.532 | 3.524 | 3.583 | 33.8 | 33.4 | 34.0 | 34.2 | 34.4 | 34.0 |
| MatFormer | 3.425 | 3.357 | 3.325 | 3.312 | 3.314 | 3.347 | 35.1 | 35.2 | 35.8 | 35.9 | 35.9 | 35.6 |
| Fully elastic | 3.429 | 3.354 | 3.315 | 3.295 | 3.290 | 3.336 | 34.9 | 35.5 | 35.7 | 35.9 | 36.0 | 35.6 |
| ShellElastic | 3.409 | 3.338 | 3.294 | 3.264 | 3.240 | 3.309 | 35.5 | 36.6 | 36.6 | 36.9 | 36.9 | 36.5 |
| 375M–906M | ||||||||||||
| Standalone† | 3.007 | 2.963 | 2.926 | 2.897 | 2.870 | 2.933 | 40.4 | 41.8 | 42.5 | 43.2 | 43.1 | 42.2 |
| Sampled standalone | 3.208 | 3.175 | 3.141 | 3.115 | 3.093 | 3.147 | 37.7 | 37.8 | 38.0 | 38.7 | 39.0 | 38.2 |
| MatFormer | 3.072 | 3.005 | 2.975 | 2.963 | 2.963 | 2.996 | 39.7 | 40.3 | 40.4 | 41.2 | 41.3 | 40.6 |
| Fully elastic | 3.052 | 2.995 | 2.966 | 2.952 | 2.948 | 2.983 | 40.3 | 41.0 | 41.6 | 42.0 | 42.0 | 41.4 |
| ShellElastic | 3.055 | 3.000 | 2.967 | 2.943 | 2.925 | 2.978 | 40.8 | 41.4 | 42.0 | 42.6 | 43.0 | 41.9 |
| 675M–1.69B | ||||||||||||
| Standalone† | 2.912 | 2.859 | 2.821 | 2.793 | 2.767 | 2.830 | 43.4 | 43.9 | 44.7 | 46.2 | 46.1 | 44.8 |
| Sampled standalone | 3.037 | 2.998 | 2.970 | 2.956 | 2.924 | 2.977 | 40.2 | 40.8 | 41.6 | 41.0 | 43.2 | 41.4 |
| MatFormer | 2.914 | 2.872 | 2.849 | 2.839 | 2.838 | 2.862 | 42.8 | 43.3 | 43.4 | 44.0 | 43.6 | 43.4 |
| Fully elastic | 2.940 | 2.884 | 2.854 | 2.838 | 2.833 | 2.870 | 42.1 | 43.4 | 43.9 | 44.2 | 44.6 | 43.6 |
| ShellElastic | 2.914 | 2.866 | 2.835 | 2.813 | 2.796 | 2.845 | 43.7 | 43.7 | 43.9 | 44.3 | 44.5 | 44.0 |
Among the methods that train all five sizes in one run, ShellElastic has the lowest mean validation loss (0.028, 0.005 and 0.018 nats below the best baseline) and the highest mean 5-shot accuracy at every scale, and is best or tied-best at 12 of the 15 tiers in validation loss and 14 in 5-shot accuracy. With a fifth of their optimizer steps, ShellElastic comes within 0.039, 0.045 and 0.014 nats of the standalone models in mean validation loss and within 0.8 points in mean 5-shot accuracy.
|
Scroll sideways: Figure 3, then Figures 12–16 of Appendix H (each sub-network, and weight decay).
Under μ-Elastic, the proxy’s optimum, η0 = 2 × 10−3 and σ0 = 3.3 × 10−3 (the base values of Section 4.1), transfers to all three elastic models at both levels of μ-Transfer (Figure 3, Corollary 1) and stays within 0.005 nats of the optimum of every sub-network (Figures 12–14). Under SP, the optimum departs from the proxy’s and shifts with scale, as Section 3.2 anticipates, and at the base values SP is 0.03–0.11 nats worse. Weight decay transfers as well (Figures 15 and 16): under μ-Elastic, the mean loss of ShellElastic at 119M–285M is flat over the same range as the proxy’s, from λ0 = 10−3 to 10−1 (within 0.003 nats), whereas SP is higher at every swept value.
Table 3. Effect of μ-Elastic on each elastic model at the 119M–285M and 375M–906M scales. For each model, the first row is the best of the 12 (13 at 375M–906M) SP configurations of Figure 3 at that scale (lowest mean validation loss), and the w/ μ-Elastic row is its result in Table 2, with the base values of Section 4.1 and no re-tuning. Table 28 gives the values with four decimals.
| Method | Train loss ↓ | Val. loss ↓ | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Low | Medium | High | Extra | Max | Avg. | Low | Medium | High | Extra | Max | Avg. | |
| 119M–285M | ||||||||||||
| MatFormer | 3.261 | 3.184 | 3.157 | 3.140 | 3.139 | 3.176 | 3.434 | 3.360 | 3.327 | 3.314 | 3.311 | 3.349 |
| w/ μ-Elastic | 3.254 | 3.182 | 3.156 | 3.141 | 3.144 | 3.175 | 3.425 | 3.357 | 3.325 | 3.312 | 3.314 | 3.347 |
| Fully elastic | 3.272 | 3.192 | 3.154 | 3.130 | 3.126 | 3.175 | 3.445 | 3.368 | 3.325 | 3.303 | 3.297 | 3.348 |
| w/ μ-Elastic | 3.257 | 3.178 | 3.145 | 3.123 | 3.120 | 3.165 | 3.429 | 3.354 | 3.315 | 3.295 | 3.290 | 3.336 |
| ShellElastic | 3.247 | 3.180 | 3.136 | 3.104 | 3.079 | 3.149 | 3.423 | 3.354 | 3.308 | 3.275 | 3.249 | 3.322 |
| w/ μ-Elastic | 3.230 | 3.164 | 3.123 | 3.094 | 3.071 | 3.137 | 3.409 | 3.338 | 3.294 | 3.264 | 3.240 | 3.309 |
| 375M–906M | ||||||||||||
| MatFormer | 2.914 | 2.841 | 2.815 | 2.796 | 2.793 | 2.832 | 3.089 | 3.019 | 2.988 | 2.974 | 2.970 | 3.008 |
| w/ μ-Elastic | 2.899 | 2.828 | 2.803 | 2.786 | 2.787 | 2.821 | 3.072 | 3.005 | 2.975 | 2.963 | 2.963 | 2.996 |
| Fully elastic | 2.906 | 2.842 | 2.813 | 2.790 | 2.786 | 2.827 | 3.081 | 3.020 | 2.987 | 2.969 | 2.963 | 3.004 |
| w/ μ-Elastic | 2.879 | 2.817 | 2.793 | 2.773 | 2.771 | 2.807 | 3.052 | 2.995 | 2.966 | 2.952 | 2.948 | 2.983 |
| ShellElastic | 2.888 | 2.830 | 2.796 | 2.770 | 2.748 | 2.806 | 3.070 | 3.009 | 2.973 | 2.946 | 2.924 | 2.984 |
| w/ μ-Elastic | 2.875 | 2.822 | 2.790 | 2.767 | 2.749 | 2.801 | 3.055 | 3.000 | 2.967 | 2.943 | 2.925 | 2.978 |
Without width-dependent scaling, re-tuning one global value only trades one width against another (Proposition 2). Table 3 gives SP the best of its configurations in Figure 3 and μ-Elastic only the base values; still, at the 119M–285M scale μ-Elastic gives lower training and validation losses at every tier for the fully elastic model and ShellElastic (by 0.011 and 0.013 nats in mean validation loss), as it keeps all widths maximally updated at once (Theorem 1), and at the 375M–906M scale tuned SP remains 0.006–0.021 nats worse for all three models. Under tuned SP, ShellElastic still beats both baselines by 0.026–0.027 and 0.020–0.024 nats at the two scales, so its lead is not due to μ-Elastic alone.
All ablations use the 119M–285M supernet of Section 4.1 and change one setting at a time; the default results are those of Table 2. Of the settings we ablate, sub-network selection, in-place distillation, ensembles of the sub-networks, stage-residual gradient scaling and the trunk gradient of the narrower widths can change the mean validation loss by 0.010 to 0.20 nats, whereas the loss weights, normalization, readouts, base width and head dimension, and optimization HPs change it by at most 0.007 nats (Section 4.4, Table 4; Appendix J, Tables 31 and 32).
| Resource | Where |
|---|---|
| Results and training logs | Project page: each result in the main text, followed by the runs behind it (training curves, run files with final metrics in JSON and CSV, and training logs) |
| Checkpoints | 🤗 Hugging Face |
| Datasets | 🤗 Hugging Face: the tokenized training and validation shards the runs read (Can111/ShellElastic-data, scripts/download_data.py) |
Where the paper averages several runs, the tables and plots on the project page show its averages, and the curves, data files and logs come from one of the runs it averages for that entry.
Reference implementation of ShellElastic and the μ-Elastic parameterization from the paper, together with the baselines of the paper (fully elastic model, MatFormer, standalone and sampled standalone models, StairFormer) and everything needed to rerun its experiments. Section, appendix, equation, table and figure numbers in this README and in the code refer to the paper, arXiv:2610.15124.
| Path | What it is |
|---|---|
paper/ShellElastic.pdf |
The paper |
elastic/models/shell.py |
ShellElastic (ShellElasticLM; Section 3.1): shell projections, group-local norms, per-width terminal norms and readouts, learned readout scales, optional width router, stage-residual gradient scaling; StairFormer and standalone models are configurations of it |
elastic/models/dense.py |
Fully elastic model and MatFormer (DenseElasticLM) with the split μ-Elastic parameterization (Appendix D) |
elastic/kernels/ |
GPU kernels of the shell models |
elastic/optim.py |
μ-Elastic AdamW parameter groups (Table 1; Tables 5 and 6) and the warmup-stable-decay schedule (Table 9) |
elastic/train/ |
Joint objective (Equation 8: width selection, loss weights, z-loss) with in-place distillation and ensemble teachers (Appendix J), FSDP2 trainer, checkpointing |
elastic/data/text.py |
Streaming WebDataset loader for pre-tokenized text |
elastic/eval/ |
In-context-learning evaluation of every sub-network (13 tasks, 5-shot; Appendix F) |
configs/paper/ |
Every run of the paper |
configs/eval/ |
The 13 tasks of the final evaluation (tasks.yaml) and the three probed at every validation (probe.yaml) |
scripts/ |
Pretraining-data download, evaluation-data download, sweep expansion |
tools/ |
Parameter counts, Proposition 1 check, ensemble analysis |
Python ≥ 3.10 and PyTorch ≥ 2.6 with CUDA; run all commands from the repository root.
pip install -e ".[all,dev]"The tokenized DCLM-Baseline training shards and C4 validation shards that the paper's runs read are
on Hugging Face (Can111/ShellElastic-data):
python scripts/download_data.py --scale 1 --out data # 119M–285M (20 GB)
python scripts/download_data.py --scale 2 --out data # 375M–906M (72 GB)
python scripts/download_data.py --scale 3 --out data # 675M–1.69B (141 GB), covers all three scales
python scripts/download_eval_data.py --out eval_data # the 13 evaluation taskstorchrun --nproc_per_node=8 -m elastic.train configs/paper/scale1/shellelastic.yaml
torchrun --nproc_per_node=8 -m elastic.train configs/paper/scale1/shellelastic.yaml optim.lr=1e-3 run.name=my_runAny setting can be overridden as key=value. A run writes config.yaml,
metrics.jsonl, checkpoints and the final weights (final/; final_<i>/ per model for sampled
standalone) to outputs/<run.name>/ and resumes from the latest checkpoint there, so a new run
needs a new run.name. The metrics of each sub-network are named by its width, e.g.
val_loss_width_512 (by its FFN width for MatFormer). The paper configs also evaluate during
training and need eval_data/; eval.probe=null train.final_eval=false turns this off.
The paper configs run on one node of 8 GPUs. On another number of GPUs, keep the global batch,
data.batch_size × #GPUs, at 128 (119M–285M) or 256 (the two larger scales), and likewise
data.eval_batch_size; the data order then differs from the paper's runs.
The paper configs end training with the 5-shot evaluation of every sub-network on the 13 tasks (Appendix F). To evaluate exported weights:
torchrun --nproc_per_node=8 -m elastic.eval outputs/<run.name>/final [widths=[4,8]] [out=results.json]widths selects sub-networks by their entry of 𝒮 (default: every trained one); the results are
icl/<task>_5shot_width_<n> and their mean icl/mean_width_<n>.
Configs are YAML files; inherit: builds on other files (the paper configs inherit
configs/paper/common.yaml), and key=value arguments override any setting.
| Setting | Meaning |
|---|---|
run |
|
name |
Run name; the outputs go to outputs/<name>/ |
seed |
Seed of the model initialization |
model |
|
type |
shell: ShellElastic, StairFormer, standalone and proxy models; dense: fully elastic model and MatFormer |
mode |
dense only: full (fully elastic model) or ffn (MatFormer) |
base_width |
Base width g; the model width Dmodel for MatFormer and the full width for a standalone model |
supported |
Supported set 𝒮, in units of base_width (of ffn_hidden for MatFormer; [1] for a standalone model) |
trained |
Widths of 𝒮 that are trained (default: all) |
ffn_hidden |
FFN hidden width per unit of 𝒮 (MatFormer: base FFN width h0) |
n_layers, head_dim, gated_attention |
Number of layers, head dimension dhead and gated attention |
norm, norm_eps |
rms (RMSNorm) or layer (LayerNorm), and its ε |
trunk_norm |
Trunk normalization: group (group-local), block (block-local over every g coordinates) or cumulative (cumulative prefix norm, as in StairFormer) |
terminal_norm |
Terminal norm Nsout: full (over all sg coordinates) or trunk (each group separately, as in the trunk) |
separate_terminal_norms |
One terminal-norm gain per width (false: one shared gain) |
readout |
separate (a readout Us per width) or shared (one sliced readout) |
parameterization |
mu_elastic or sp; sets only the defaults of the next four settings, which the paper configs set explicitly (their SP variants add the sp_overrides of configs/paper/sweeps.yaml) |
width_multiplier |
μ-Transfer factor m (null: base_width / proxy_width) |
ffn_expansion |
FFN expansion e in the scaling rules (null: ffn_hidden / base_width) |
internal_scaling |
μ-Internal factor: each group's initialization, learning rate and weight decay follow its own fan-in |
alpha |
Readout scalars αs: learnable or a fixed value |
init_std |
Base initialization σ0 |
proxy_width |
Width d0 of the non-elastic proxy |
stage_grad_scale |
Stage-residual gradient scale γ, ablation (9) (1: off) |
width_router |
Learned per-token router over the widths, ablation (8) |
objective |
|
selection |
Sub-networks selected per step 𝒜τ: all, random (one, uniformly at random), sandwich (Low, Max and one other) or max_random (Max and one other) |
loss_weights |
Loss weights ωs of Equation 8, one per width of 𝒮 |
z_loss |
z-loss coefficient λz |
distill, distill_weights, distill_kl |
In-place distillation, ablations (6) and (8): teacher (max, ensemble or oracle), weight per width and KL direction |
detach_trunk |
Only the selected widths train the trunk; the others train only their terminal norms and readouts, ablation (10) |
optim (AdamW) |
|
lr |
Base learning rate η0 |
weight_decay |
Base weight decay λ0, decoupled |
betas, eps |
β1, β2 and ε |
schedule |
|
warmup_steps, decay_start |
Warmup-stable-decay: linear warmup, then constant, then linear decay to 0 from decay_start to train.steps |
train |
|
steps |
Training steps |
grad_clip |
Gradient clipping by global norm |
skip_factor, skip_start |
From step skip_start on, a step is skipped if its gradient norm exceeds skip_factor × grad_clip |
shard_size |
The model is sharded within groups of this many GPUs and replicated across groups (0: sharded over all GPUs) |
activation_checkpointing |
Fraction of the blocks, evenly spaced, whose activations are recomputed in the backward pass: 0/1 (none), 1/2, 1/1 (all) |
val_every, val_steps |
Validation interval and number of validation batches |
final_eval |
Evaluate every sub-network on the 13 tasks after training |
data |
|
batch_size, eval_batch_size |
Training and validation sequences per GPU; the global batch is batch_size × #GPUs |
train_sources, val_sources |
Shard directories or URLs, e.g. [hf://datasets/Can111/ShellElastic-data/dclm-baseline] and [hf://datasets/Can111/ShellElastic-data/c4-val] to stream without a download |
seed, num_workers |
Data seed and data-loader workers per GPU; with the number of GPUs, they fix which shards are read and in what order |
eval |
|
probe |
Tasks evaluated at every validation (configs/eval/probe.yaml; null: none) |
tasks |
Tasks of the final evaluation (configs/eval/tasks.yaml) |
multi (sampled standalone) |
|
models |
The separate models, each with its own model and optim overrides |
selection |
random: one model, chosen uniformly at random, takes each step |
logging |
|
wandb, project, entity |
Mirror the metrics to Weights & Biases |
| Paper | Configs and commands |
|---|---|
| Main results (Table 2) | configs/paper/scale{1,2,3}/: shellelastic, fully_elastic, matformer, standalone_d* (one per width), sampled_standalone |
| Hyperparameter transfer (Figure 3; Figures 12–16) | python scripts/sweep.py configs/paper/sweeps.yaml prints one training command per run; the proxy is configs/paper/proxy/standalone_d128.yaml |
| Effect of μ-Elastic (Table 3) | The SP run with the lowest mean validation loss in python scripts/sweep.py configs/paper/sweeps.yaml --sp --grid lr init, against the main results |
| Ablations (Table 4; Tables 31 and 32) | configs/paper/ablations/, one directory per ablation of Appendix J |
| Ensembles (Figure 5; Tables 33 and 34) | configs/paper/ablations/ensemble/ and tools/analyze_ensemble.py |
| Architecture search (Figure 4c) | configs/paper/arch_search/ |
| StairFormer (Figures 4a and 4b) | configs/paper/stairformer/stairformer.yaml |
| Parameter counts (Table 10) | python tools/count_params.py configs/paper/scale{1,2,3}/*.yaml |
| Proposition 1 (Appendix B.3) | python tools/check_prefix_exactness.py configs/paper/scale1/shellelastic.yaml |
pytest tests@article{jin2026shellelastic,
title = {{ShellElastic}: Scalable Elastic Pretraining with Simultaneous Maximal Updates and Hyperparameter Transfer},
author = {Jin, Can and Kang, Yan and Gong, Yifan and Ge, Chongjian and Xu, Mingze and Xiong, Yuanjun and Metaxas, Dimitris N. and Peng, Hongwu},
journal = {arXiv preprint arXiv:2610.15124},
year = {2026},
url = {https://arxiv.org/abs/2610.15124}
}Apache-2.0. See LICENSE and THIRD_PARTY_NOTICES.md (xFormers, OpenLM, LLM Foundry, Composer). DCLM-Baseline is released under CC-BY-4.0, C4 under ODC-BY; the evaluation datasets keep their own licenses.








