Mandeep Sidhu commited on
Commit ·
58904bb
1
Parent(s): e7a7275
Prepare publication-ready research artifact
Browse files- .cache/dropout_decay_tinystories_8m/tokenizer-v4096.json +0 -0
- .cache/dropout_decay_tinystories_8m/tokens-v4096-uint16.npy +3 -0
- .cache/dropout_decay_wikitext103_8m/tokenizer-v4096.json +0 -0
- .cache/dropout_decay_wikitext103_8m/tokens-v4096-uint16.npy +3 -0
- .gitignore +9 -0
- README.md +26 -16
- REPRODUCING.md +75 -10
- paper/dropout_decay_pressure_law.tex +0 -501
- paper/dropout_decay_regime_specific_pressure_law.bbl +0 -73
- paper/dropout_decay_regime_specific_pressure_law.pdf +2 -2
- paper/dropout_decay_regime_specific_pressure_law.tex +303 -60
- paper/figures/calibration_cell_curves.tex +0 -2
- paper/figures/calibration_to_streaming_protocol.tex +27 -0
- paper/figures/static_optima_by_regime.tex +9 -9
- paper/paper_results_summary.json +355 -0
- paper/tables/calibration_weight_table.tex +10 -0
- paper/tables/coefficient_table.tex +1 -1
- paper/tables/evidence_ladder_table.tex +9 -0
- paper/tables/experiment_protocol_table.tex +11 -0
- paper/tables/l20_schedule_path_table.tex +9 -0
- paper/tables/l20_stage_table.tex +1 -1
- paper/tables/paired_gain_ci_table.tex +12 -0
- paper/tables/protocol_budget_table.tex +12 -0
- paper/tables/regime_setup_table.tex +9 -0
- paper/tables/reproducibility_table.tex +13 -0
- paper/tables/streaming_validation_table.tex +4 -4
- paper/tables/symbol_table.tex +15 -0
- pyproject.toml +12 -0
- scripts/generate_paper_assets.py +353 -15
- scripts/summarize_cross_regime_backtest.py +1 -1
- src/dropout_decay/data/__init__.py +2 -0
- src/dropout_decay/experiment.py +2 -0
- src/dropout_decay/model.py +2 -0
- src/dropout_decay/scheduler.py +2 -0
- src/dropout_decay/tokenizer.py +2 -0
- tests/test_data_and_device.py +55 -0
- tests/test_schedules.py +74 -0
- tests/test_specs_and_parsing.py +50 -0
.cache/dropout_decay_tinystories_8m/tokenizer-v4096.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
.cache/dropout_decay_tinystories_8m/tokens-v4096-uint16.npy
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:35221770a252f4f3b4e86210495bbd02fc7830fba3ea0dc92deab4e98af60103
|
| 3 |
+
size 17000354
|
.cache/dropout_decay_wikitext103_8m/tokenizer-v4096.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
.cache/dropout_decay_wikitext103_8m/tokens-v4096-uint16.npy
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2198e999a2292ddfb549781af602d790356c3afd8cc1008c07cb96b58aa60a20
|
| 3 |
+
size 17000462
|
.gitignore
CHANGED
|
@@ -11,6 +11,11 @@ __pycache__/
|
|
| 11 |
*.npy
|
| 12 |
.venv/
|
| 13 |
*.egg-info/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
# Keep generated scratch artifacts out by default, but allow the curated
|
| 16 |
# reproducibility caches and corpora that make this repo standalone.
|
|
@@ -23,6 +28,10 @@ __pycache__/
|
|
| 23 |
!.cache/dropout_decay_wikitext103/**
|
| 24 |
!.cache/dropout_decay_openwebtext10k_8m/
|
| 25 |
!.cache/dropout_decay_openwebtext10k_8m/**
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
data/*
|
| 28 |
!data/openwebtext10k/
|
|
|
|
| 11 |
*.npy
|
| 12 |
.venv/
|
| 13 |
*.egg-info/
|
| 14 |
+
.pytest_cache/
|
| 15 |
+
.mypy_cache/
|
| 16 |
+
.ruff_cache/
|
| 17 |
+
build/
|
| 18 |
+
dist/
|
| 19 |
|
| 20 |
# Keep generated scratch artifacts out by default, but allow the curated
|
| 21 |
# reproducibility caches and corpora that make this repo standalone.
|
|
|
|
| 28 |
!.cache/dropout_decay_wikitext103/**
|
| 29 |
!.cache/dropout_decay_openwebtext10k_8m/
|
| 30 |
!.cache/dropout_decay_openwebtext10k_8m/**
|
| 31 |
+
!.cache/dropout_decay_tinystories_8m/
|
| 32 |
+
!.cache/dropout_decay_tinystories_8m/**
|
| 33 |
+
!.cache/dropout_decay_wikitext103_8m/
|
| 34 |
+
!.cache/dropout_decay_wikitext103_8m/**
|
| 35 |
|
| 36 |
data/*
|
| 37 |
!data/openwebtext10k/
|
README.md
CHANGED
|
@@ -54,11 +54,24 @@ The existing repo-local caches are:
|
|
| 54 |
- `.cache/dropout_decay_tinystories/tokens-v4096-uint16.npy`
|
| 55 |
- `.cache/dropout_decay_wikitext103/tokenizer-v4096.json`
|
| 56 |
- `.cache/dropout_decay_wikitext103/tokens-v4096-uint16.npy`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
Use a project-local Python environment with MPS-capable PyTorch, for example
|
| 59 |
`.venv/bin/python`. Attribution to nanochat remains in the source and docs, but
|
| 60 |
experiment commands should not point into a separate nanochat repository.
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
## Workflow
|
| 63 |
|
| 64 |
1. Screen candidate model sizes with cheap static dropout sweeps.
|
|
@@ -76,22 +89,19 @@ Every run writes:
|
|
| 76 |
- `model_selection.csv` / `model_selection.json`: static-sweep optimum and
|
| 77 |
plateau diagnostics for screen and confirm runs.
|
| 78 |
|
| 79 |
-
Old exploratory outputs are archived under `archive/`
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
`docs/
|
| 89 |
-
|
| 90 |
-
`
|
| 91 |
-
|
| 92 |
-
`docs/regime_coefficient_report_20260529.md`. For the live coefficient
|
| 93 |
-
calibration plan, see `docs/coefficient_calibration_plan.md`. For the current
|
| 94 |
-
arXiv-style paper draft, see `paper/dropout_decay_pressure_law.tex`.
|
| 95 |
|
| 96 |
## Step 1: Cheap Static Screen
|
| 97 |
|
|
|
|
| 54 |
- `.cache/dropout_decay_tinystories/tokens-v4096-uint16.npy`
|
| 55 |
- `.cache/dropout_decay_wikitext103/tokenizer-v4096.json`
|
| 56 |
- `.cache/dropout_decay_wikitext103/tokens-v4096-uint16.npy`
|
| 57 |
+
- `.cache/dropout_decay_openwebtext10k_8m/tokenizer-v4096.json`
|
| 58 |
+
- `.cache/dropout_decay_openwebtext10k_8m/tokens-v4096-uint16.npy`
|
| 59 |
+
- `.cache/dropout_decay_tinystories_8m/tokenizer-v4096.json`
|
| 60 |
+
- `.cache/dropout_decay_tinystories_8m/tokens-v4096-uint16.npy`
|
| 61 |
+
- `.cache/dropout_decay_wikitext103_8m/tokenizer-v4096.json`
|
| 62 |
+
- `.cache/dropout_decay_wikitext103_8m/tokens-v4096-uint16.npy`
|
| 63 |
|
| 64 |
Use a project-local Python environment with MPS-capable PyTorch, for example
|
| 65 |
`.venv/bin/python`. Attribution to nanochat remains in the source and docs, but
|
| 66 |
experiment commands should not point into a separate nanochat repository.
|
| 67 |
|
| 68 |
+
Fast non-training checks can be run without launching an MPS experiment:
|
| 69 |
+
|
| 70 |
+
```bash
|
| 71 |
+
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests -v
|
| 72 |
+
PYTHONPATH=src .venv/bin/python scripts/generate_paper_assets.py
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
## Workflow
|
| 76 |
|
| 77 |
1. Screen candidate model sizes with cheap static dropout sweeps.
|
|
|
|
| 89 |
- `model_selection.csv` / `model_selection.json`: static-sweep optimum and
|
| 90 |
plateau diagnostics for screen and confirm runs.
|
| 91 |
|
| 92 |
+
Old exploratory outputs are archived under `archive/`; they are not part of the
|
| 93 |
+
primary evidence path for the paper.
|
| 94 |
+
|
| 95 |
+
For exact headline reproduction, see `REPRODUCING.md`. Current documentation is:
|
| 96 |
+
|
| 97 |
+
- `docs/plan.md`: regime-validation and coefficient-fitting plan.
|
| 98 |
+
- `docs/formula_coefficient_methodology.md`: coefficient target extraction,
|
| 99 |
+
weighting, and fitting details.
|
| 100 |
+
- `docs/openwebtext10k_streaming_report.md`: OpenWebText10K regime report.
|
| 101 |
+
- `docs/tinystories_streaming_report.md`: TinyStories regime report.
|
| 102 |
+
- `docs/wikitext103_streaming_report.md`: WikiText-103 regime report.
|
| 103 |
+
- `paper/dropout_decay_regime_specific_pressure_law.tex`: paper source.
|
| 104 |
+
- `paper/dropout_decay_regime_specific_pressure_law.pdf`: generated paper PDF.
|
|
|
|
|
|
|
|
|
|
| 105 |
|
| 106 |
## Step 1: Cheap Static Screen
|
| 107 |
|
REPRODUCING.md
CHANGED
|
@@ -21,6 +21,12 @@ python3.11 -m venv .venv
|
|
| 21 |
.venv/bin/python -m pip install -e .
|
| 22 |
```
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
Verify MPS:
|
| 25 |
|
| 26 |
```bash
|
|
@@ -58,6 +64,12 @@ The experiments in the current report used these repo-local caches:
|
|
| 58 |
.cache/dropout_decay_tinystories/tokens-v4096-uint16.npy
|
| 59 |
.cache/dropout_decay_wikitext103/tokenizer-v4096.json
|
| 60 |
.cache/dropout_decay_wikitext103/tokens-v4096-uint16.npy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
```
|
| 62 |
|
| 63 |
These binary artifacts are intended to be published with the repository through
|
|
@@ -124,18 +136,36 @@ Expected:
|
|
| 124 |
5000970 500000
|
| 125 |
```
|
| 126 |
|
| 127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
|
| 129 |
-
The
|
| 130 |
|
| 131 |
```text
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
|
|
|
| 136 |
```
|
| 137 |
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
- stream prefixes: `250000 500000 1000000 2000000 4000000`
|
| 141 |
- stage steps: `1000`
|
|
@@ -143,6 +173,40 @@ For the standard protocol:
|
|
| 143 |
- block size: `128`
|
| 144 |
- cumulative sampled tokens after stage `i`: `i * 1000 * 16 * 128`
|
| 145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
## Reproduce Model-Size Validation
|
| 147 |
|
| 148 |
Example L12 command:
|
|
@@ -386,6 +450,7 @@ paired low-decay wins: 3/3
|
|
| 386 |
- Do not claim the formula is universal.
|
| 387 |
- The supported claim is final-validation improvement under this
|
| 388 |
expanding-prefix protocol.
|
| 389 |
-
-
|
| 390 |
-
|
| 391 |
-
|
|
|
|
|
|
| 21 |
.venv/bin/python -m pip install -e .
|
| 22 |
```
|
| 23 |
|
| 24 |
+
For development and publication checks, install the optional test dependency:
|
| 25 |
+
|
| 26 |
+
```bash
|
| 27 |
+
.venv/bin/python -m pip install -e ".[dev]"
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
Verify MPS:
|
| 31 |
|
| 32 |
```bash
|
|
|
|
| 64 |
.cache/dropout_decay_tinystories/tokens-v4096-uint16.npy
|
| 65 |
.cache/dropout_decay_wikitext103/tokenizer-v4096.json
|
| 66 |
.cache/dropout_decay_wikitext103/tokens-v4096-uint16.npy
|
| 67 |
+
.cache/dropout_decay_openwebtext10k_8m/tokenizer-v4096.json
|
| 68 |
+
.cache/dropout_decay_openwebtext10k_8m/tokens-v4096-uint16.npy
|
| 69 |
+
.cache/dropout_decay_tinystories_8m/tokenizer-v4096.json
|
| 70 |
+
.cache/dropout_decay_tinystories_8m/tokens-v4096-uint16.npy
|
| 71 |
+
.cache/dropout_decay_wikitext103_8m/tokenizer-v4096.json
|
| 72 |
+
.cache/dropout_decay_wikitext103_8m/tokens-v4096-uint16.npy
|
| 73 |
```
|
| 74 |
|
| 75 |
These binary artifacts are intended to be published with the repository through
|
|
|
|
| 136 |
5000970 500000
|
| 137 |
```
|
| 138 |
|
| 139 |
+
Run the fast non-training test suite:
|
| 140 |
+
|
| 141 |
+
```bash
|
| 142 |
+
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests -v
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
## Current Pressure Law
|
| 146 |
|
| 147 |
+
The paper tests a per-regime interaction pressure law:
|
| 148 |
|
| 149 |
```text
|
| 150 |
+
p_t = clamp(p_min, p_max,
|
| 151 |
+
A * log10(P / U_t)
|
| 152 |
+
+ B * log10(C_t / U_t)
|
| 153 |
+
+ D * log10(P / U_t) * log10(C_t / U_t)
|
| 154 |
+
+ C0)
|
| 155 |
```
|
| 156 |
|
| 157 |
+
where `P` is trainable parameter count, `U_t` is the currently revealed unique
|
| 158 |
+
token prefix, and `C_t` is the cumulative sampled training-token count consumed
|
| 159 |
+
by the optimizer. The fitted coefficients are regime-specific; the current
|
| 160 |
+
paper tables read them from:
|
| 161 |
+
|
| 162 |
+
```text
|
| 163 |
+
runs/coefficient_calibration/cross_regime_backtest/openwebtext10k_main_interaction/coefficients.json
|
| 164 |
+
runs/coefficient_calibration/tinystories_combined_plus_all_holdouts_interaction/coefficients.json
|
| 165 |
+
runs/coefficient_calibration/wikitext103_interaction/coefficients.json
|
| 166 |
+
```
|
| 167 |
+
|
| 168 |
+
For the standard 4M validation protocol:
|
| 169 |
|
| 170 |
- stream prefixes: `250000 500000 1000000 2000000 4000000`
|
| 171 |
- stage steps: `1000`
|
|
|
|
| 173 |
- block size: `128`
|
| 174 |
- cumulative sampled tokens after stage `i`: `i * 1000 * 16 * 128`
|
| 175 |
|
| 176 |
+
For the L20 8M extrapolation tier, the saved configs in `runs/` use the
|
| 177 |
+
regime-specific 8M caches listed above and the frozen coefficient-derived
|
| 178 |
+
dropout paths recorded in the run configs.
|
| 179 |
+
|
| 180 |
+
## Rebuild Paper Tables and Figures
|
| 181 |
+
|
| 182 |
+
The manuscript source is:
|
| 183 |
+
|
| 184 |
+
```text
|
| 185 |
+
paper/dropout_decay_regime_specific_pressure_law.tex
|
| 186 |
+
```
|
| 187 |
+
|
| 188 |
+
Regenerate the paper tables, figures, and result summary from saved metrics:
|
| 189 |
+
|
| 190 |
+
```bash
|
| 191 |
+
PYTHONPATH=src .venv/bin/python scripts/generate_paper_assets.py
|
| 192 |
+
```
|
| 193 |
+
|
| 194 |
+
Build the PDF, keeping LaTeX intermediates outside `paper/`:
|
| 195 |
+
|
| 196 |
+
```bash
|
| 197 |
+
mkdir -p /tmp/dropout-paper-build
|
| 198 |
+
cd paper
|
| 199 |
+
latexmk -pdf -outdir=/tmp/dropout-paper-build \
|
| 200 |
+
-interaction=nonstopmode -halt-on-error \
|
| 201 |
+
dropout_decay_regime_specific_pressure_law.tex
|
| 202 |
+
cp /tmp/dropout-paper-build/dropout_decay_regime_specific_pressure_law.pdf \
|
| 203 |
+
dropout_decay_regime_specific_pressure_law.pdf
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
+
The sections below provide additional reproduction commands for saved
|
| 207 |
+
validation runs. They are intentionally left in the original run format so old
|
| 208 |
+
result artifacts remain compatible.
|
| 209 |
+
|
| 210 |
## Reproduce Model-Size Validation
|
| 211 |
|
| 212 |
Example L12 command:
|
|
|
|
| 450 |
- Do not claim the formula is universal.
|
| 451 |
- The supported claim is final-validation improvement under this
|
| 452 |
expanding-prefix protocol.
|
| 453 |
+
- The current PDF is tracked as a generated paper artifact; transient LaTeX
|
| 454 |
+
build files are ignored.
|
| 455 |
+
- Cached token arrays and parquet source files should be published through the
|
| 456 |
+
configured Git LFS rules.
|
paper/dropout_decay_pressure_law.tex
DELETED
|
@@ -1,501 +0,0 @@
|
|
| 1 |
-
\documentclass[11pt]{article}
|
| 2 |
-
|
| 3 |
-
\usepackage[margin=1in]{geometry}
|
| 4 |
-
\usepackage{amsmath}
|
| 5 |
-
\usepackage{amssymb}
|
| 6 |
-
\usepackage{booktabs}
|
| 7 |
-
\usepackage{graphicx}
|
| 8 |
-
\usepackage{hyperref}
|
| 9 |
-
\usepackage[numbers,sort&compress]{natbib}
|
| 10 |
-
|
| 11 |
-
\title{Pressure-Aware Dropout Scheduling for Expanding-Stream Language Model Training}
|
| 12 |
-
\author{Anonymous Authors}
|
| 13 |
-
\date{May 29, 2026}
|
| 14 |
-
|
| 15 |
-
\newcommand{\clamp}{\operatorname{clamp}}
|
| 16 |
-
\newcommand{\params}{P}
|
| 17 |
-
\newcommand{\unique}{U_t}
|
| 18 |
-
\newcommand{\sampled}{C_t}
|
| 19 |
-
|
| 20 |
-
\begin{document}
|
| 21 |
-
\maketitle
|
| 22 |
-
|
| 23 |
-
\begin{abstract}
|
| 24 |
-
Dropout is usually selected as a fixed hyperparameter, but fixed regularization
|
| 25 |
-
is mismatched to streaming regimes where the amount of unique training data
|
| 26 |
-
changes over time. We study expanding-prefix language model training, where a
|
| 27 |
-
causal Transformer first trains on a small token prefix and later continues on
|
| 28 |
-
larger prefixes. Static dropout sweeps show that the best dropout rate is not
|
| 29 |
-
constant: it rises with model/data pressure and repeated sampling, and falls as
|
| 30 |
-
more unique data becomes available. We propose a pressure-law family
|
| 31 |
-
\[
|
| 32 |
-
p_t = \clamp(p_{\min}, p_{\max},
|
| 33 |
-
A \log_{10}(\params / \unique)
|
| 34 |
-
+ B \log_{10}(\sampled / \unique)
|
| 35 |
-
+ C),
|
| 36 |
-
\]
|
| 37 |
-
where $\params$ is parameter count, $\unique$ is the number of unique available
|
| 38 |
-
tokens, and $\sampled$ is the cumulative number of sampled training tokens
|
| 39 |
-
consumed by the optimizer. On the local nanochat-style regime, ordinary least
|
| 40 |
-
squares over static dropout optima gives $A=0.225$, $B=0.169$, and $C=-0.210$.
|
| 41 |
-
For dynamic streaming, a validated schedule with $A=0.154$, $B=0.249$, and
|
| 42 |
-
$C=-0.210$ wins all 15 paired final-loss comparisons across 8.39M to 31.46M
|
| 43 |
-
parameter models and transfers to two architecture-shape holdouts. Public-corpus
|
| 44 |
-
tests show a boundary condition: corpus identity shifts the optimum, so the
|
| 45 |
-
coefficients are regime-calibrated constants rather than universal constants.
|
| 46 |
-
\end{abstract}
|
| 47 |
-
|
| 48 |
-
\section{Introduction}
|
| 49 |
-
|
| 50 |
-
Language models trained on expanding streams face a changing regularization
|
| 51 |
-
problem. At the beginning of the stream, a model may have many parameters
|
| 52 |
-
relative to the number of unique tokens currently available. The optimizer may
|
| 53 |
-
also sample the same prefix repeatedly. Later, the same model sees more unique
|
| 54 |
-
data, reducing the need for strong regularization. A single fixed dropout rate
|
| 55 |
-
cannot simultaneously match both conditions.
|
| 56 |
-
|
| 57 |
-
The naive hypothesis is that one should use extremely high dropout early and
|
| 58 |
-
decay it as more data arrives. Our first experiments reject that form: very high
|
| 59 |
-
dropout underfits and loses to moderate fixed-dropout baselines. The supported
|
| 60 |
-
hypothesis is narrower. Dropout should track a moving optimum driven by
|
| 61 |
-
model/data pressure and repeated-sampling pressure.
|
| 62 |
-
|
| 63 |
-
This paper makes four contributions:
|
| 64 |
-
|
| 65 |
-
\begin{enumerate}
|
| 66 |
-
\item We define an expanding-prefix streaming protocol for small causal
|
| 67 |
-
Transformer language models.
|
| 68 |
-
\item We show that the best static dropout moves predictably with parameter
|
| 69 |
-
count, unique-token prefix size, and sampled-token pressure.
|
| 70 |
-
\item We propose a pressure-law dropout schedule and separate static
|
| 71 |
-
optimum coefficients from dynamic streaming coefficients.
|
| 72 |
-
\item We define a training regime as the scope over which one coefficient
|
| 73 |
-
triplet should be expected to transfer, and we show when corpus changes
|
| 74 |
-
invalidate a universal-coefficient claim.
|
| 75 |
-
\end{enumerate}
|
| 76 |
-
|
| 77 |
-
\section{Background}
|
| 78 |
-
|
| 79 |
-
Dropout randomly removes units during training and is a standard method for
|
| 80 |
-
reducing overfitting \citep{srivastava2014dropout}. In inverted dropout, an
|
| 81 |
-
activation $h_i$ is transformed as
|
| 82 |
-
\[
|
| 83 |
-
h'_i = h_i \frac{m_i}{1-p}, \quad m_i \sim \operatorname{Bernoulli}(1-p).
|
| 84 |
-
\]
|
| 85 |
-
The expectation is preserved,
|
| 86 |
-
\[
|
| 87 |
-
\mathbb{E}[h'_i] = h_i,
|
| 88 |
-
\]
|
| 89 |
-
while the noise variance grows as
|
| 90 |
-
\[
|
| 91 |
-
\operatorname{Var}(h'_i) = h_i^2 \frac{p}{1-p}.
|
| 92 |
-
\]
|
| 93 |
-
This creates a regularization tradeoff. Too little dropout permits
|
| 94 |
-
memorization; too much dropout harms optimization and underfits.
|
| 95 |
-
|
| 96 |
-
Our experiments use decoder-only Transformer language models inspired by
|
| 97 |
-
modern causal architectures \citep{vaswani2017attention}. The code is derived
|
| 98 |
-
from Andrej Karpathy's MIT-licensed nanochat repository
|
| 99 |
-
\citep{karpathy_nanochat}; chat and deployment components are removed, while
|
| 100 |
-
the tokenizer and core causal Transformer template are retained.
|
| 101 |
-
|
| 102 |
-
\section{Expanding-Stream Protocol}
|
| 103 |
-
|
| 104 |
-
We simulate streaming by revealing larger prefixes of a tokenized corpus:
|
| 105 |
-
\[
|
| 106 |
-
250\text{k} \rightarrow 500\text{k} \rightarrow 1\text{M}
|
| 107 |
-
\rightarrow 2\text{M} \rightarrow 4\text{M}.
|
| 108 |
-
\]
|
| 109 |
-
For each seed and condition, one model and optimizer continue through all
|
| 110 |
-
stages. At stage $t$, minibatches are sampled only from the currently revealed
|
| 111 |
-
prefix of size $\unique$.
|
| 112 |
-
|
| 113 |
-
The standard protocol uses batch size 16, block size 128, and 1000 optimizer
|
| 114 |
-
steps per stage. Therefore each stage consumes 2.048M sampled tokens, and the
|
| 115 |
-
cumulative sampled tokens are listed in Table~\ref{tab:stream_tokens}.
|
| 116 |
-
|
| 117 |
-
\begin{table}[h]
|
| 118 |
-
\centering
|
| 119 |
-
\caption{Standard expanding-prefix schedule.}
|
| 120 |
-
\label{tab:stream_tokens}
|
| 121 |
-
\begin{tabular}{rrrr}
|
| 122 |
-
\toprule
|
| 123 |
-
Stage & Unique tokens $\unique$ & Stage sampled tokens & Cumulative sampled tokens $\sampled$ \\
|
| 124 |
-
\midrule
|
| 125 |
-
0 & 250k & 2.048M & 2.048M \\
|
| 126 |
-
1 & 500k & 2.048M & 4.096M \\
|
| 127 |
-
2 & 1M & 2.048M & 6.144M \\
|
| 128 |
-
3 & 2M & 2.048M & 8.192M \\
|
| 129 |
-
4 & 4M & 2.048M & 10.240M \\
|
| 130 |
-
\bottomrule
|
| 131 |
-
\end{tabular}
|
| 132 |
-
\end{table}
|
| 133 |
-
|
| 134 |
-
All Torch experiments were run on Apple MPS only. The runner refuses CPU, CUDA,
|
| 135 |
-
and MPS fallback. The main experiments use a 4096-token vocabulary, AdamW, a
|
| 136 |
-
learning rate of $3 \times 10^{-4}$, weight decay 0.1, gradient clipping 1.0,
|
| 137 |
-
64 validation batches, and seeds 1, 2, and 3 unless otherwise stated.
|
| 138 |
-
|
| 139 |
-
\section{Regime Definition}
|
| 140 |
-
|
| 141 |
-
The formula is not meant to change coefficients when model size or stream size
|
| 142 |
-
changes. Those are exactly the variables the formula explains. Instead,
|
| 143 |
-
coefficients are expected to be fixed within a training regime.
|
| 144 |
-
|
| 145 |
-
We define a regime as:
|
| 146 |
-
\begin{align*}
|
| 147 |
-
\mathcal{R}=\{&
|
| 148 |
-
\text{architecture family},\ \text{tokenizer},\ \text{corpus family},\\
|
| 149 |
-
&\text{optimizer protocol},\ \text{dropout placement},\\
|
| 150 |
-
&\text{stream protocol},\ \text{evaluation distribution}\}.
|
| 151 |
-
\end{align*}
|
| 152 |
-
|
| 153 |
-
Operationally, two runs are in the same regime if one fixed coefficient triplet
|
| 154 |
-
$(A,B,C)$ predicts dropout optima across held-out model sizes and held-out
|
| 155 |
-
prefix sizes without systematic bias. Changes in $\params$, $\unique$, and
|
| 156 |
-
$\sampled$ should not require new coefficients. Changes in corpus family,
|
| 157 |
-
tokenizer, architecture class, dropout placement, optimizer schedule, stream
|
| 158 |
-
semantics, or validation distribution should trigger re-evaluation.
|
| 159 |
-
|
| 160 |
-
\section{Pressure-Law Dropout}
|
| 161 |
-
|
| 162 |
-
We propose the formula family
|
| 163 |
-
\begin{equation}
|
| 164 |
-
p_t = \clamp(p_{\min}, p_{\max},
|
| 165 |
-
A \log_{10}(\params / \unique)
|
| 166 |
-
+ B \log_{10}(\sampled / \unique)
|
| 167 |
-
+ C).
|
| 168 |
-
\label{eq:pressure}
|
| 169 |
-
\end{equation}
|
| 170 |
-
|
| 171 |
-
The first term measures model/data pressure. Larger $\params / \unique$ means
|
| 172 |
-
the model has more capacity per currently available unique token. The second
|
| 173 |
-
term measures repeated-sampling pressure. Larger $\sampled / \unique$ means the
|
| 174 |
-
optimizer has revisited the available prefix more often. We use logarithms
|
| 175 |
-
because parameter counts and token counts vary over orders of magnitude while
|
| 176 |
-
dropout is bounded.
|
| 177 |
-
|
| 178 |
-
\subsection{Static Optimum Fit}
|
| 179 |
-
|
| 180 |
-
For static sweeps, each row gives a measured best dropout $y_i$ at a fixed
|
| 181 |
-
model and prefix. We set
|
| 182 |
-
\[
|
| 183 |
-
x_{1,i} = \log_{10}(\params_i / U_i), \quad
|
| 184 |
-
x_{2,i} = \log_{10}(C_i / U_i),
|
| 185 |
-
\]
|
| 186 |
-
and solve
|
| 187 |
-
\[
|
| 188 |
-
\min_{A,B,C} \sum_i
|
| 189 |
-
\left(y_i - A x_{1,i} - B x_{2,i} - C\right)^2.
|
| 190 |
-
\]
|
| 191 |
-
|
| 192 |
-
On the 15-point main local static screen, the grid optimum fit gives
|
| 193 |
-
\[
|
| 194 |
-
A=0.225,\quad B=0.169,\quad C=-0.210.
|
| 195 |
-
\]
|
| 196 |
-
A quadratic interpolation around the best measured grid point gives a similar
|
| 197 |
-
fit:
|
| 198 |
-
\[
|
| 199 |
-
A=0.231,\quad B=0.166,\quad C=-0.211.
|
| 200 |
-
\]
|
| 201 |
-
|
| 202 |
-
\subsection{Streaming Schedule Coefficients}
|
| 203 |
-
|
| 204 |
-
The best dynamic schedule is not necessarily identical to the best static
|
| 205 |
-
optimum surface. The current validated streaming baseline uses
|
| 206 |
-
\[
|
| 207 |
-
A=0.154,\quad B=0.249,\quad C=-0.210,
|
| 208 |
-
\]
|
| 209 |
-
with $p_{\min}=0.02$ and $p_{\max}=0.65$. For the L12 model under the standard
|
| 210 |
-
protocol, this gives
|
| 211 |
-
\[
|
| 212 |
-
0.300 \rightarrow 0.260 \rightarrow 0.180 \rightarrow 0.090 \rightarrow 0.020.
|
| 213 |
-
\]
|
| 214 |
-
|
| 215 |
-
\section{Experiments}
|
| 216 |
-
|
| 217 |
-
\subsection{Initial Negative Result}
|
| 218 |
-
|
| 219 |
-
The first tests used an 8.39M-parameter model and found that arbitrary high
|
| 220 |
-
dropout was not useful. Table~\ref{tab:high_dropout} shows that high dropout
|
| 221 |
-
underfit and lost to static 0.1 dropout.
|
| 222 |
-
|
| 223 |
-
\begin{table}[h]
|
| 224 |
-
\centering
|
| 225 |
-
\caption{Naive high-dropout decay failed. Lower validation loss is better.}
|
| 226 |
-
\label{tab:high_dropout}
|
| 227 |
-
\begin{tabular}{lrrrr}
|
| 228 |
-
\toprule
|
| 229 |
-
Condition & 5M & 10M & 20M & 40M \\
|
| 230 |
-
\midrule
|
| 231 |
-
High-dropout decay & 6.9213 & 6.2689 & 5.4262 & 4.9090 \\
|
| 232 |
-
Static 0.1 dropout & 5.6310 & 5.1018 & 4.8497 & 4.6743 \\
|
| 233 |
-
Static 0.8 dropout & 6.9898 & 6.7637 & 6.4835 & 6.2390 \\
|
| 234 |
-
\bottomrule
|
| 235 |
-
\end{tabular}
|
| 236 |
-
\end{table}
|
| 237 |
-
|
| 238 |
-
\subsection{Static Dropout Screen}
|
| 239 |
-
|
| 240 |
-
Table~\ref{tab:static_screen} shows the core static screen. The best dropout
|
| 241 |
-
falls as unique-token count grows and rises with model size at fixed prefix.
|
| 242 |
-
|
| 243 |
-
\begin{table}[h]
|
| 244 |
-
\centering
|
| 245 |
-
\caption{Static dropout optima in the OpenWebText10K cached-corpus regime.}
|
| 246 |
-
\label{tab:static_screen}
|
| 247 |
-
\resizebox{\textwidth}{!}{%
|
| 248 |
-
\begin{tabular}{lrrrrrr}
|
| 249 |
-
\toprule
|
| 250 |
-
Model & Params & Prefix & Effective epochs & Best dropout & Val loss & Gap \\
|
| 251 |
-
\midrule
|
| 252 |
-
L8 & 8.39M & 250k & 40.96 & 0.40 & 5.4175 & 1.7763 \\
|
| 253 |
-
L8 & 8.39M & 500k & 20.48 & 0.20 & 5.0216 & 1.3238 \\
|
| 254 |
-
L8 & 8.39M & 1M & 10.24 & 0.14 & 4.7763 & 0.7863 \\
|
| 255 |
-
L8 & 8.39M & 2M & 5.12 & 0.08 & 4.6232 & 0.4074 \\
|
| 256 |
-
L8 & 8.39M & 4M & 2.56 & 0.00 & 4.5136 & 0.2621 \\
|
| 257 |
-
L12 & 17.37M & 250k & 40.96 & 0.50 & 5.4384 & 2.0663 \\
|
| 258 |
-
L12 & 17.37M & 500k & 20.48 & 0.40 & 4.9791 & 1.2434 \\
|
| 259 |
-
L12 & 17.37M & 1M & 10.24 & 0.20 & 4.6871 & 0.9711 \\
|
| 260 |
-
L12 & 17.37M & 2M & 5.12 & 0.14 & 4.5088 & 0.4870 \\
|
| 261 |
-
L12 & 17.37M & 4M & 2.56 & 0.02 & 4.3875 & 0.3575 \\
|
| 262 |
-
L16 & 31.46M & 250k & 40.96 & 0.60 & 5.5055 & 2.1870 \\
|
| 263 |
-
L16 & 31.46M & 500k & 20.48 & 0.40 & 4.9814 & 1.7017 \\
|
| 264 |
-
L16 & 31.46M & 1M & 10.24 & 0.30 & 4.6511 & 1.0216 \\
|
| 265 |
-
L16 & 31.46M & 2M & 5.12 & 0.14 & 4.4270 & 0.6509 \\
|
| 266 |
-
L16 & 31.46M & 4M & 2.56 & 0.02 & 4.2947 & 0.4400 \\
|
| 267 |
-
\bottomrule
|
| 268 |
-
\end{tabular}}
|
| 269 |
-
\end{table}
|
| 270 |
-
|
| 271 |
-
\subsection{Coefficient Fit}
|
| 272 |
-
|
| 273 |
-
Table~\ref{tab:coefs} reports coefficient estimates from existing saved data.
|
| 274 |
-
The main local screen is the cleanest static-regime estimate. Pooling the
|
| 275 |
-
corpus probes without a corpus feature is misspecified because those probes
|
| 276 |
-
share the same $\params / U$ and $C / U$ but have different optima.
|
| 277 |
-
|
| 278 |
-
\begin{table}[h]
|
| 279 |
-
\centering
|
| 280 |
-
\caption{OLS coefficient fits for the static optimum surface.}
|
| 281 |
-
\label{tab:coefs}
|
| 282 |
-
\begin{tabular}{llrrrrr}
|
| 283 |
-
\toprule
|
| 284 |
-
Target & Data subset & n & $A$ & $B$ & $C$ & RMSE \\
|
| 285 |
-
\midrule
|
| 286 |
-
Grid & Main local & 15 & 0.225 & 0.169 & -0.210 & 0.0418 \\
|
| 287 |
-
Quadratic & Main local & 15 & 0.231 & 0.166 & -0.211 & 0.0353 \\
|
| 288 |
-
Grid & Main local + 5M & 18 & 0.232 & 0.118 & -0.159 & 0.0508 \\
|
| 289 |
-
Quadratic & Main local + 5M & 18 & 0.237 & 0.117 & -0.161 & 0.0466 \\
|
| 290 |
-
Grid & All existing & 21 & 0.343 & 0.014 & -0.210 & 0.0650 \\
|
| 291 |
-
\bottomrule
|
| 292 |
-
\end{tabular}
|
| 293 |
-
\end{table}
|
| 294 |
-
|
| 295 |
-
\subsection{Model-Size Validation}
|
| 296 |
-
|
| 297 |
-
The dynamic streaming schedule was evaluated against static-dropout controls
|
| 298 |
-
near the apparent optimum. Table~\ref{tab:model_size} shows final validation
|
| 299 |
-
loss across five model sizes.
|
| 300 |
-
|
| 301 |
-
\begin{table}[h]
|
| 302 |
-
\centering
|
| 303 |
-
\caption{Streaming formula vs. best static controls across model size.}
|
| 304 |
-
\label{tab:model_size}
|
| 305 |
-
\begin{tabular}{lrrrl}
|
| 306 |
-
\toprule
|
| 307 |
-
Model & Params & Formula final val & Best static final val & Paired deltas \\
|
| 308 |
-
\midrule
|
| 309 |
-
L8 & 8.39M & $4.6094 \pm 0.0056$ & 4.6242 & -0.0102, -0.0160, -0.0182 \\
|
| 310 |
-
L10 & 12.31M & $4.5306 \pm 0.0094$ & 4.5580 & -0.0288, -0.0188, -0.0345 \\
|
| 311 |
-
L12 & 17.37M & $4.4812 \pm 0.0062$ & 4.5183 & -0.0364, -0.0308, -0.0439 \\
|
| 312 |
-
L14 & 23.70M & $4.4384 \pm 0.0087$ & 4.4736 & -0.0294, -0.0269, -0.0429 \\
|
| 313 |
-
L16 & 31.46M & $4.4059 \pm 0.0046$ & 4.4459 & -0.0411, -0.0512, -0.0279 \\
|
| 314 |
-
\bottomrule
|
| 315 |
-
\end{tabular}
|
| 316 |
-
\end{table}
|
| 317 |
-
|
| 318 |
-
The formula wins all 15 paired final-loss comparisons in this set.
|
| 319 |
-
|
| 320 |
-
\subsection{Repeated-Sampling Pressure}
|
| 321 |
-
|
| 322 |
-
Changing stage steps changes $\sampled / \unique$ while keeping the prefix
|
| 323 |
-
sequence fixed. Table~\ref{tab:update_pressure} shows that the pressure formula
|
| 324 |
-
continues to beat fixed dropout at 500, 1000, and 2000 steps per stage.
|
| 325 |
-
|
| 326 |
-
\begin{table}[h]
|
| 327 |
-
\centering
|
| 328 |
-
\caption{Update-pressure validation on L12.}
|
| 329 |
-
\label{tab:update_pressure}
|
| 330 |
-
\resizebox{\textwidth}{!}{%
|
| 331 |
-
\begin{tabular}{rlrrrl}
|
| 332 |
-
\toprule
|
| 333 |
-
Stage steps & Formula path & Mean trajectory & Formula final & Best static final & Paired deltas \\
|
| 334 |
-
\midrule
|
| 335 |
-
500 & 0.226 -> 0.180 -> 0.102 -> 0.020 -> 0.020 & 5.1581 & $4.7138 \pm 0.0080$ & 4.7321 & -0.0152, -0.0147, -0.0249 \\
|
| 336 |
-
1000 & 0.300 -> 0.260 -> 0.180 -> 0.090 -> 0.020 & 4.9226 & $4.4812 \pm 0.0062$ & 4.5183 & -0.0364, -0.0308, -0.0439 \\
|
| 337 |
-
2000 & 0.376 -> 0.330 -> 0.252 -> 0.162 -> 0.065 & 4.7841 & $4.3089 \pm 0.0116$ & 4.3513 & -0.0453, -0.0321, -0.0489 \\
|
| 338 |
-
\bottomrule
|
| 339 |
-
\end{tabular}}
|
| 340 |
-
\end{table}
|
| 341 |
-
|
| 342 |
-
\subsection{Sampled-Pressure Coefficient Ablation}
|
| 343 |
-
|
| 344 |
-
The sampled-pressure term was ablated by multiplying the current coefficient by
|
| 345 |
-
0, 0.5, 1.0, and 1.5. Table~\ref{tab:b_ablation} shows that the full
|
| 346 |
-
sampled-pressure term gives the best final validation loss.
|
| 347 |
-
|
| 348 |
-
\begin{table}[h]
|
| 349 |
-
\centering
|
| 350 |
-
\caption{Ablation of repeated-sampling pressure on L12.}
|
| 351 |
-
\label{tab:b_ablation}
|
| 352 |
-
\resizebox{\textwidth}{!}{%
|
| 353 |
-
\begin{tabular}{rlrrrr}
|
| 354 |
-
\toprule
|
| 355 |
-
Multiplier & Path & Mean trajectory & Final val & Final std & Final gap \\
|
| 356 |
-
\midrule
|
| 357 |
-
0x & 0.074 -> 0.027 -> 0.020 -> 0.020 -> 0.020 & 5.0282 & 4.5468 & 0.0011 & 0.3482 \\
|
| 358 |
-
0.5x & 0.187 -> 0.141 -> 0.079 -> 0.020 -> 0.020 & 4.9260 & 4.5055 & 0.0046 & 0.3272 \\
|
| 359 |
-
1.0x & 0.300 -> 0.260 -> 0.180 -> 0.090 -> 0.020 & 4.9226 & 4.4812 & 0.0062 & 0.2825 \\
|
| 360 |
-
1.5x & 0.415 -> 0.368 -> 0.275 -> 0.163 -> 0.041 & 4.9739 & 4.4959 & 0.0025 & 0.2418 \\
|
| 361 |
-
\bottomrule
|
| 362 |
-
\end{tabular}}
|
| 363 |
-
\end{table}
|
| 364 |
-
|
| 365 |
-
\subsection{Architecture-Shape Holdouts}
|
| 366 |
-
|
| 367 |
-
Two holdouts test whether parameter count is a useful capacity proxy inside the
|
| 368 |
-
same Transformer family. Results are shown in Table~\ref{tab:shape}.
|
| 369 |
-
|
| 370 |
-
\begin{table}[h]
|
| 371 |
-
\centering
|
| 372 |
-
\caption{Architecture-shape holdouts.}
|
| 373 |
-
\label{tab:shape}
|
| 374 |
-
\begin{tabular}{lrrr}
|
| 375 |
-
\toprule
|
| 376 |
-
Holdout & Params & Formula final val & Best static final val \\
|
| 377 |
-
\midrule
|
| 378 |
-
Deep/narrow 18x8x256 & 16.25M & $4.5286 \pm 0.0118$ & $4.5564 \pm 0.0127$ \\
|
| 379 |
-
Wide 8x8x384 & 17.30M & $4.4658 \pm 0.0065$ & $4.4946 \pm 0.0087$ \\
|
| 380 |
-
\bottomrule
|
| 381 |
-
\end{tabular}
|
| 382 |
-
\end{table}
|
| 383 |
-
|
| 384 |
-
The formula wins all 6 paired final-loss comparisons across these two shape
|
| 385 |
-
holdouts.
|
| 386 |
-
|
| 387 |
-
\subsection{Corpus Holdouts}
|
| 388 |
-
|
| 389 |
-
Corpus tests reveal the boundary of the two-variable formula. The frozen
|
| 390 |
-
formula transfers to WikiText-103 but overestimates early dropout on
|
| 391 |
-
TinyStories. A lower dropout path performs better on TinyStories.
|
| 392 |
-
|
| 393 |
-
\begin{table}[h]
|
| 394 |
-
\centering
|
| 395 |
-
\caption{Public-corpus streaming checks.}
|
| 396 |
-
\label{tab:corpus_stream}
|
| 397 |
-
\begin{tabular}{llrr}
|
| 398 |
-
\toprule
|
| 399 |
-
Corpus & Condition & Final val & Mean trajectory \\
|
| 400 |
-
\midrule
|
| 401 |
-
WikiText-103 & Old formula & 4.0643 & 4.5704 \\
|
| 402 |
-
WikiText-103 & Best static & 4.0893 & 4.5889 \\
|
| 403 |
-
TinyStories & Old formula & 2.7221 & 3.1149 \\
|
| 404 |
-
TinyStories & Probe blend & 2.7194 & 3.0934 \\
|
| 405 |
-
TinyStories & Low-decay heuristic & 2.7068 & 3.0793 \\
|
| 406 |
-
TinyStories & Best static & 2.7215 & 3.0880 \\
|
| 407 |
-
\bottomrule
|
| 408 |
-
\end{tabular}
|
| 409 |
-
\end{table}
|
| 410 |
-
|
| 411 |
-
A separate 1.835M-parameter pressure probe used the same $\params / U$ and
|
| 412 |
-
$C/U$ on three corpora, but obtained different optima: 0.04 on the local
|
| 413 |
-
corpus, 0.00 on WikiText-103, and 0.02 on TinyStories. This proves that corpus
|
| 414 |
-
identity can shift the optimum independently of the two pressure ratios.
|
| 415 |
-
|
| 416 |
-
\section{Discussion}
|
| 417 |
-
|
| 418 |
-
The evidence supports a pressure-law structure, not a universal coefficient
|
| 419 |
-
triplet. The static fit shows that dropout optima can be approximated from
|
| 420 |
-
$\log_{10}(\params/U)$ and $\log_{10}(C/U)$ within the OpenWebText10K cached-corpus regime. The
|
| 421 |
-
streaming experiments show that a schedule based on those variables can beat
|
| 422 |
-
fixed dropout across model sizes and architecture-shape holdouts.
|
| 423 |
-
|
| 424 |
-
However, the corpus probes show that the two-variable formula is incomplete.
|
| 425 |
-
For a paper claim, we therefore recommend the following framing:
|
| 426 |
-
|
| 427 |
-
\begin{quote}
|
| 428 |
-
Within a fixed training regime, dropout can be scheduled from model/data
|
| 429 |
-
pressure and repeated-sampling pressure. The coefficients are empirical
|
| 430 |
-
calibration constants for the regime. They should be re-estimated when the
|
| 431 |
-
corpus family, tokenizer, architecture class, dropout placement, optimizer
|
| 432 |
-
protocol, streaming semantics, or validation distribution changes.
|
| 433 |
-
\end{quote}
|
| 434 |
-
|
| 435 |
-
\section{Limitations}
|
| 436 |
-
|
| 437 |
-
The experiments are small compared with modern frontier-scale language model
|
| 438 |
-
training. They are nevertheless useful because they isolate dropout behavior in
|
| 439 |
-
a controlled setting. The main limitations are:
|
| 440 |
-
|
| 441 |
-
\begin{itemize}
|
| 442 |
-
\item The dense static coefficient fit is local-corpus biased.
|
| 443 |
-
\item The public-corpus checks show that a corpus term is missing.
|
| 444 |
-
\item The streaming coefficients were selected by validation and ablation,
|
| 445 |
-
not by a full continuous coefficient sweep.
|
| 446 |
-
\item The models are nanochat-style causal Transformers, so transfer to
|
| 447 |
-
different architecture families is not established.
|
| 448 |
-
\item The local token cache is not yet a fully published dataset artifact,
|
| 449 |
-
which limits exact reproduction until the cache or source corpus is hosted.
|
| 450 |
-
\end{itemize}
|
| 451 |
-
|
| 452 |
-
\section{Reproducibility}
|
| 453 |
-
|
| 454 |
-
The repository includes experiment code, result logs, model-selection CSVs, and
|
| 455 |
-
reproduction commands. Every run records configuration, metrics, and attribution
|
| 456 |
-
metadata. The runner enforces MPS-only Torch execution. For exact reproduction,
|
| 457 |
-
the local cache must be supplied or rebuilt from a documented corpus source.
|
| 458 |
-
Public WikiText-103 and TinyStories holdouts have preparation scripts.
|
| 459 |
-
|
| 460 |
-
\section{Conclusion}
|
| 461 |
-
|
| 462 |
-
Dropout decay is useful when it follows a moving regularization optimum, not
|
| 463 |
-
when it starts from an arbitrary high value. Existing evidence supports a
|
| 464 |
-
pressure-law schedule using model/data pressure and repeated-sampling pressure.
|
| 465 |
-
For the local static regime, the best fit is approximately
|
| 466 |
-
$(A,B,C)=(0.225,0.169,-0.210)$. For the validated streaming baseline, the best
|
| 467 |
-
current schedule uses $(A,B,C)=(0.154,0.249,-0.210)$. The next step is to fit
|
| 468 |
-
and validate a corpus-aware correction without losing the regime-calibrated
|
| 469 |
-
structure.
|
| 470 |
-
|
| 471 |
-
\bibliographystyle{plainnat}
|
| 472 |
-
\bibliography{references}
|
| 473 |
-
|
| 474 |
-
\appendix
|
| 475 |
-
|
| 476 |
-
\section{When To Refit Coefficients}
|
| 477 |
-
|
| 478 |
-
Refit or at least revalidate coefficients when any of the following changes:
|
| 479 |
-
corpus family, tokenizer/vocabulary, architecture class, dropout placement,
|
| 480 |
-
optimizer and learning-rate protocol, sequence length, streaming semantics, or
|
| 481 |
-
validation distribution. Do not refit merely because model size, prefix size, or
|
| 482 |
-
sampled-token count changes inside the same regime; those are the formula's
|
| 483 |
-
input variables.
|
| 484 |
-
|
| 485 |
-
\section{Recommended Reporting Checklist}
|
| 486 |
-
|
| 487 |
-
For each future regime, report:
|
| 488 |
-
|
| 489 |
-
\begin{itemize}
|
| 490 |
-
\item model parameter count and architecture shape;
|
| 491 |
-
\item tokenizer and vocabulary size;
|
| 492 |
-
\item unique tokens available at each stage;
|
| 493 |
-
\item sampled tokens per stage and cumulative sampled tokens;
|
| 494 |
-
\item dropout path and clamp values;
|
| 495 |
-
\item fixed-dropout controls near the predicted optimum;
|
| 496 |
-
\item seeds, mean validation loss, standard deviation, and paired deltas;
|
| 497 |
-
\item train-evaluation loss and validation gap;
|
| 498 |
-
\item exact command and run artifact path.
|
| 499 |
-
\end{itemize}
|
| 500 |
-
|
| 501 |
-
\end{document}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
paper/dropout_decay_regime_specific_pressure_law.bbl
DELETED
|
@@ -1,73 +0,0 @@
|
|
| 1 |
-
\begin{thebibliography}{8}
|
| 2 |
-
\providecommand{\natexlab}[1]{#1}
|
| 3 |
-
\providecommand{\url}[1]{\texttt{#1}}
|
| 4 |
-
\expandafter\ifx\csname urlstyle\endcsname\relax
|
| 5 |
-
\providecommand{\doi}[1]{doi: #1}\else
|
| 6 |
-
\providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi
|
| 7 |
-
|
| 8 |
-
\bibitem[Eldan and Li(2023)]{eldan2023tinystories}
|
| 9 |
-
Ronen Eldan and Yuanzhi Li.
|
| 10 |
-
\newblock Tinystories: How small can language models be and still speak
|
| 11 |
-
coherent english?
|
| 12 |
-
\newblock \emph{arXiv preprint arXiv:2305.07759}, 2023.
|
| 13 |
-
\newblock URL \url{https://arxiv.org/abs/2305.07759}.
|
| 14 |
-
|
| 15 |
-
\bibitem[Gokaslan et~al.(2019)Gokaslan, Cohen, Pavlick, and
|
| 16 |
-
Tellex]{gokaslan2019openwebtext}
|
| 17 |
-
Aaron Gokaslan, Vanya Cohen, Ellie Pavlick, and Stefanie Tellex.
|
| 18 |
-
\newblock Openwebtext corpus.
|
| 19 |
-
\newblock \url{https://zenodo.org/records/3834942}, 2019.
|
| 20 |
-
\newblock Open reproduction of the WebText-style corpus.
|
| 21 |
-
|
| 22 |
-
\bibitem[Hoffmann et~al.(2022)Hoffmann, Borgeaud, Mensch, Buchatskaya, Cai,
|
| 23 |
-
Rutherford, Casas, Hendricks, Welbl, Clark, Hennigan, Noland, Millican,
|
| 24 |
-
van~den Driessche, Damoc, Guy, Osindero, Simonyan, Elsen, Rae, Vinyals, and
|
| 25 |
-
Sifre]{hoffmann2022training}
|
| 26 |
-
Jordan Hoffmann, Sebastian Borgeaud, Arthur Mensch, Elena Buchatskaya, Trevor
|
| 27 |
-
Cai, Eliza Rutherford, Diego de~Las Casas, Lisa~Anne Hendricks, Johannes
|
| 28 |
-
Welbl, Aidan Clark, Tom Hennigan, Eric Noland, Katie Millican, George van~den
|
| 29 |
-
Driessche, Bogdan Damoc, Aurelia Guy, Simon Osindero, Karen Simonyan, Erich
|
| 30 |
-
Elsen, Jack~W. Rae, Oriol Vinyals, and Laurent Sifre.
|
| 31 |
-
\newblock Training compute-optimal large language models.
|
| 32 |
-
\newblock \emph{arXiv preprint arXiv:2203.15556}, 2022.
|
| 33 |
-
\newblock URL \url{https://arxiv.org/abs/2203.15556}.
|
| 34 |
-
|
| 35 |
-
\bibitem[Kaplan et~al.(2020)Kaplan, McCandlish, Henighan, Brown, Chess, Child,
|
| 36 |
-
Gray, Radford, Wu, and Amodei]{kaplan2020scaling}
|
| 37 |
-
Jared Kaplan, Sam McCandlish, Tom Henighan, Tom~B. Brown, Benjamin Chess, Rewon
|
| 38 |
-
Child, Scott Gray, Alec Radford, Jeffrey Wu, and Dario Amodei.
|
| 39 |
-
\newblock Scaling laws for neural language models.
|
| 40 |
-
\newblock \emph{arXiv preprint arXiv:2001.08361}, 2020.
|
| 41 |
-
\newblock URL \url{https://arxiv.org/abs/2001.08361}.
|
| 42 |
-
|
| 43 |
-
\bibitem[Karpathy(2025)]{karpathy_nanochat}
|
| 44 |
-
Andrej Karpathy.
|
| 45 |
-
\newblock nanochat.
|
| 46 |
-
\newblock \url{https://github.com/karpathy/nanochat}, 2025.
|
| 47 |
-
\newblock MIT-licensed repository, accessed 2026-05-29.
|
| 48 |
-
|
| 49 |
-
\bibitem[Merity et~al.(2017)Merity, Xiong, Bradbury, and
|
| 50 |
-
Socher]{merity2017pointer}
|
| 51 |
-
Stephen Merity, Caiming Xiong, James Bradbury, and Richard Socher.
|
| 52 |
-
\newblock Pointer sentinel mixture models.
|
| 53 |
-
\newblock In \emph{International Conference on Learning Representations}, 2017.
|
| 54 |
-
\newblock URL \url{https://arxiv.org/abs/1609.07843}.
|
| 55 |
-
|
| 56 |
-
\bibitem[Srivastava et~al.(2014)Srivastava, Hinton, Krizhevsky, Sutskever, and
|
| 57 |
-
Salakhutdinov]{srivastava2014dropout}
|
| 58 |
-
Nitish Srivastava, Geoffrey Hinton, Alex Krizhevsky, Ilya Sutskever, and Ruslan
|
| 59 |
-
Salakhutdinov.
|
| 60 |
-
\newblock Dropout: A simple way to prevent neural networks from overfitting.
|
| 61 |
-
\newblock \emph{Journal of Machine Learning Research}, 15\penalty0
|
| 62 |
-
(56):\penalty0 1929--1958, 2014.
|
| 63 |
-
\newblock URL \url{https://www.jmlr.org/papers/v15/srivastava14a.html}.
|
| 64 |
-
|
| 65 |
-
\bibitem[Vaswani et~al.(2017)Vaswani, Shazeer, Parmar, Uszkoreit, Jones, Gomez,
|
| 66 |
-
Kaiser, and Polosukhin]{vaswani2017attention}
|
| 67 |
-
Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones,
|
| 68 |
-
Aidan~N. Gomez, Lukasz Kaiser, and Illia Polosukhin.
|
| 69 |
-
\newblock Attention is all you need.
|
| 70 |
-
\newblock In \emph{Advances in Neural Information Processing Systems}, 2017.
|
| 71 |
-
\newblock URL \url{https://arxiv.org/abs/1706.03762}.
|
| 72 |
-
|
| 73 |
-
\end{thebibliography}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
paper/dropout_decay_regime_specific_pressure_law.pdf
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:99ac702644025cd253907d1c8e7892f2de07e32564a68c33a25fc505ac25b886
|
| 3 |
+
size 330095
|
paper/dropout_decay_regime_specific_pressure_law.tex
CHANGED
|
@@ -14,7 +14,7 @@
|
|
| 14 |
\usepackage[colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref}
|
| 15 |
|
| 16 |
\title{Regime-Specific Pressure Laws for Dropout Decay in Streaming Language Model Training}
|
| 17 |
-
\author{
|
| 18 |
\date{June 2026}
|
| 19 |
|
| 20 |
\newcommand{\clamp}{\operatorname{clamp}}
|
|
@@ -46,14 +46,17 @@ these per-cell optima into a regime-specific pressure law,
|
|
| 46 |
\]
|
| 47 |
where $\params$ is parameter count, $\unique$ is currently available unique
|
| 48 |
tokens, and $\sampled$ is cumulative sampled training tokens. The fitted
|
| 49 |
-
interaction law explains static optimum cells with mean absolute
|
| 50 |
-
0.0158, 0.0180, and 0.0162
|
| 51 |
-
WikiText-103 respectively. In
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
larger 51.84M-parameter,
|
| 55 |
-
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
| 57 |
intermediate prefix. The results support a practical hypothesis: dropout decay
|
| 58 |
should be calibrated as a regime-specific pressure law, not chosen as a
|
| 59 |
universal constant or an arbitrary high-to-low schedule.
|
|
@@ -80,16 +83,21 @@ claim is that useful dropout is a function of training pressure: model capacity
|
|
| 80 |
relative to the current data prefix, and cumulative optimizer sampling relative
|
| 81 |
to that prefix.
|
| 82 |
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
\begin{enumerate}
|
| 86 |
-
\item We define calibration cells for streaming dropout: one model, one
|
| 87 |
unique-token prefix, one sampled-token budget, and a sweep over fixed
|
| 88 |
dropout rates.
|
| 89 |
-
\item We show that calibration cells often have a parabolic or plateau-like
|
| 90 |
validation-loss curve over dropout, making the local optimum a usable
|
| 91 |
supervised target.
|
| 92 |
-
\item We fit a
|
| 93 |
$(\params,\unique,\sampled)$ to a dropout rate.
|
| 94 |
\item We validate the resulting schedules against broad fixed-dropout
|
| 95 |
baselines across three text regimes and a larger-model/larger-stream
|
|
@@ -98,7 +106,12 @@ This paper makes four empirical contributions.
|
|
| 98 |
|
| 99 |
The central result is not that one coefficient vector works everywhere. It does
|
| 100 |
not. The central result is that the pressure-law structure is useful, while the
|
| 101 |
-
coefficients are regime-specific.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
\section{Related Work}
|
| 104 |
|
|
@@ -111,6 +124,16 @@ The expectation is preserved, but the variance grows as $h_i^2p/(1-p)$. This
|
|
| 111 |
captures the key tradeoff in our experiments: low dropout can overfit repeated
|
| 112 |
small prefixes, but high dropout can remove too much usable capacity.
|
| 113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
\paragraph{Transformer language models and scaling.}
|
| 115 |
Our model family is a decoder-only Transformer following the attention-based
|
| 116 |
architecture of \citet{vaswani2017attention}. Scaling-law work shows that loss
|
|
@@ -125,9 +148,20 @@ We evaluate on three text regimes. TinyStories is a synthetic simple-English
|
|
| 125 |
story corpus designed for small language-model studies \citep{eldan2023tinystories}.
|
| 126 |
WikiText-103 is a standard word-level language-modeling benchmark derived from
|
| 127 |
Wikipedia articles \citep{merity2017pointer}. OpenWebText is an open
|
| 128 |
-
WebText-style corpus \citep{gokaslan2019openwebtext}.
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
|
| 132 |
\section{Experimental Setting}
|
| 133 |
|
|
@@ -140,23 +174,33 @@ core BPE tokenizer and causal Transformer template. Derived source files retain
|
|
| 140 |
the original copyright and permission notice.
|
| 141 |
|
| 142 |
The architecture family keeps the standard Transformer feed-forward expansion
|
| 143 |
-
ratio of four.
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
|
| 151 |
\subsection{Streaming protocol}
|
| 152 |
|
| 153 |
-
We simulate streaming by revealing larger token prefixes over time.
|
| 154 |
-
|
| 155 |
-
|
|
|
|
| 156 |
$\unique$. The two main protocols are:
|
| 157 |
|
| 158 |
\begin{itemize}
|
| 159 |
-
\item 4M validation: OpenWebText10K and WikiText-103 use 250k, 500k, 1M,
|
| 160 |
2M, and 4M prefixes. TinyStories uses 500k, 1M, 2M, and 4M prefixes. These
|
| 161 |
runs use five random seeds.
|
| 162 |
\item 8M extrapolation: L20-H8-D448 with an 8M final prefix. These runs use
|
|
@@ -165,11 +209,48 @@ $\unique$. The two main protocols are:
|
|
| 165 |
|
| 166 |
Each run compares a dropout schedule against a grid of static-dropout
|
| 167 |
baselines. The best static baseline is selected after training from the same
|
| 168 |
-
run family, so the decay schedule competes against
|
| 169 |
within the tested grid.
|
| 170 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
\section{From Calibration Cells to a Pressure Law}
|
| 172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
\subsection{Calibration cell definition}
|
| 174 |
|
| 175 |
A calibration cell is one static dropout sweep at a fixed tuple:
|
|
@@ -186,17 +267,25 @@ point is bracketed by worse neighbors, a local quadratic interpolation of the
|
|
| 186 |
minimum. Boundary optima are retained but downweighted in coefficient fitting
|
| 187 |
because the true optimum may lie outside the tested grid.
|
| 188 |
|
| 189 |
-
Figure~\ref{fig:cell-curves} shows
|
| 190 |
-
|
| 191 |
-
calibration
|
| 192 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
\begin{figure}[t]
|
| 195 |
\centering
|
| 196 |
\input{figures/calibration_cell_curves}
|
| 197 |
-
\caption{Representative static dropout calibration cells
|
| 198 |
-
|
| 199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
\label{fig:cell-curves}
|
| 201 |
\end{figure}
|
| 202 |
|
|
@@ -212,7 +301,18 @@ prefix increases memorization capacity and tends to increase useful dropout.
|
|
| 212 |
Increasing unique tokens at fixed model reduces this pressure. The second term
|
| 213 |
measures repeated-sampling pressure. If the optimizer consumes many sampled
|
| 214 |
tokens while the unique prefix remains small, it repeatedly revisits the same
|
| 215 |
-
data and can benefit from stronger regularization.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
|
| 217 |
The fitted interaction family is
|
| 218 |
\begin{equation}
|
|
@@ -221,8 +321,46 @@ The fitted interaction family is
|
|
| 221 |
\label{eq:interaction-law}
|
| 222 |
\end{equation}
|
| 223 |
For schedule generation we use $p_{\min}=0.02$ and $p_{\max}=0.65$ unless a
|
| 224 |
-
run explicitly specifies a different clamp.
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
\subsection{Regime-specific coefficients}
|
| 228 |
|
|
@@ -233,14 +371,27 @@ inputs to the formula. Corpus family, tokenizer, or optimizer changes can shift
|
|
| 233 |
the coefficients.
|
| 234 |
|
| 235 |
Table~\ref{tab:coefficients} gives the fitted interaction coefficients. Each
|
| 236 |
-
regime uses 15 or 16 calibration cells. The
|
| 237 |
-
|
| 238 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
|
| 240 |
\begin{table}[t]
|
| 241 |
\centering
|
| 242 |
-
\caption{Regime-specific interaction coefficient fits.
|
| 243 |
-
|
|
|
|
|
|
|
| 244 |
\label{tab:coefficients}
|
| 245 |
\resizebox{\textwidth}{!}{\input{tables/coefficient_table}}
|
| 246 |
\end{table}
|
|
@@ -269,24 +420,62 @@ Table~\ref{tab:streaming-validation} summarizes the main streaming results.
|
|
| 269 |
The ``Gain'' column is best static final validation loss minus decay final
|
| 270 |
validation loss, so positive values favor decay. The best static baseline is
|
| 271 |
chosen from the tested fixed-dropout grid in the same run family.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
|
| 273 |
\begin{table}[t]
|
| 274 |
\centering
|
| 275 |
-
\caption{Streaming validation against best fixed-dropout baselines.
|
|
|
|
|
|
|
| 276 |
\label{tab:streaming-validation}
|
| 277 |
\resizebox{\textwidth}{!}{\input{tables/streaming_validation_table}}
|
| 278 |
\end{table}
|
| 279 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
OpenWebText10K provides the cleanest five-seed coefficient-derived validation:
|
| 281 |
the interaction schedule improves final validation loss by 0.0473 over the
|
| 282 |
best static baseline and wins all five paired seeds. TinyStories shows a
|
| 283 |
smaller but consistent final-loss margin: 0.0133 over the best static baseline
|
| 284 |
-
with five paired wins. WikiText-103
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
|
| 291 |
\subsection{L20 8M extrapolation}
|
| 292 |
|
|
@@ -298,16 +487,35 @@ TinyStories, and WikiText-103, the decay schedule beats the best static
|
|
| 298 |
baseline on final validation loss and wins all paired seeds (3/3 in each
|
| 299 |
regime, 9/9 total).
|
| 300 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
Figure~\ref{fig:final-improvements} visualizes the final-loss gains. The
|
| 302 |
largest L20 gain is OpenWebText10K (0.0363), followed by WikiText-103 (0.0184)
|
| 303 |
-
and TinyStories (0.0100). The TinyStories gain is smaller because
|
| 304 |
-
|
|
|
|
|
|
|
|
|
|
| 305 |
|
| 306 |
\begin{figure}[t]
|
| 307 |
\centering
|
| 308 |
\input{figures/final_improvements}
|
| 309 |
\caption{Final validation-loss improvement over the best fixed-dropout
|
| 310 |
-
baseline.
|
|
|
|
| 311 |
\label{fig:final-improvements}
|
| 312 |
\end{figure}
|
| 313 |
|
|
@@ -322,8 +530,10 @@ the middle of the stream and wins only at the final 8M prefix.
|
|
| 322 |
|
| 323 |
\begin{table}[t]
|
| 324 |
\centering
|
| 325 |
-
\caption{L20 stage-wise comparison.
|
| 326 |
-
|
|
|
|
|
|
|
| 327 |
\label{tab:l20-stage}
|
| 328 |
\resizebox{\textwidth}{!}{\input{tables/l20_stage_table}}
|
| 329 |
\end{table}
|
|
@@ -332,7 +542,9 @@ best static validation loss at the same prefix; negative favors decay.}
|
|
| 332 |
\centering
|
| 333 |
\input{figures/l20_stage_deltas}
|
| 334 |
\caption{L20 stage-wise deltas versus the best static dropout at each prefix.
|
| 335 |
-
The
|
|
|
|
|
|
|
| 336 |
\label{fig:l20-stage-deltas}
|
| 337 |
\end{figure}
|
| 338 |
|
|
@@ -373,6 +585,23 @@ if the goal is to train one model continuously through a growing stream, not to
|
|
| 373 |
restart and optimize each prefix independently. Static baselines can be locally
|
| 374 |
optimal at one prefix but cannot adapt when the stream changes.
|
| 375 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 376 |
\section{Limitations}
|
| 377 |
|
| 378 |
The experiments are intentionally small compared with frontier language-model
|
|
@@ -384,14 +613,16 @@ confirmed law at billion-parameter scale.
|
|
| 384 |
The static coefficient fit optimizes dropout targets extracted from static
|
| 385 |
sweeps, while the streaming objective is final validation loss after continued
|
| 386 |
training. WikiText-103 shows that these objectives can diverge: the fitted
|
| 387 |
-
interaction schedule
|
| 388 |
quickly for L12 streaming. Future work should fit coefficients directly against
|
| 389 |
streaming objective functions or include trajectory-aware loss terms.
|
| 390 |
|
| 391 |
The L20 extrapolation tier uses three seeds for cost reasons. This is balanced
|
| 392 |
across all three regimes and supported by five-seed smaller-stream validation,
|
| 393 |
-
but
|
| 394 |
-
|
|
|
|
|
|
|
| 395 |
|
| 396 |
\section{Reproducibility}
|
| 397 |
|
|
@@ -402,6 +633,18 @@ fitting uses \texttt{scripts/fit\_dropout\_coefficients.py}; this manuscript's
|
|
| 402 |
figures and tables are generated by
|
| 403 |
\texttt{scripts/generate\_paper\_assets.py}. Existing result artifacts are read
|
| 404 |
from \texttt{runs/}. The experiment runner enforces MPS-only Torch execution.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
|
| 406 |
All generated tables in this paper are derived from saved metrics JSONL files
|
| 407 |
and coefficient JSON files. The paper-generation summary is written to
|
|
|
|
| 14 |
\usepackage[colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref}
|
| 15 |
|
| 16 |
\title{Regime-Specific Pressure Laws for Dropout Decay in Streaming Language Model Training}
|
| 17 |
+
\author{Mandeep Sidhu}
|
| 18 |
\date{June 2026}
|
| 19 |
|
| 20 |
\newcommand{\clamp}{\operatorname{clamp}}
|
|
|
|
| 46 |
\]
|
| 47 |
where $\params$ is parameter count, $\unique$ is currently available unique
|
| 48 |
tokens, and $\sampled$ is cumulative sampled training tokens. The fitted
|
| 49 |
+
interaction law explains static optimum cells with dropout-rate mean absolute
|
| 50 |
+
errors of 0.0158, 0.0180, and 0.0162 on OpenWebText10K, TinyStories, and
|
| 51 |
+
WikiText-103 respectively. In validation runs where the same model and optimizer
|
| 52 |
+
continue training as the available token prefix grows, coefficient-derived decay
|
| 53 |
+
schedules beat the best fixed-dropout baseline on final validation loss in all
|
| 54 |
+
three regimes at the 4M final prefix and again in larger 51.84M-parameter,
|
| 55 |
+
8M-token extrapolations. Mean final-loss gains over the best fixed dropout are
|
| 56 |
+
0.0473/0.0133/0.0297 nats at 4M and 0.0363/0.0100/0.0184 nats at 8M for
|
| 57 |
+
OpenWebText10K/TinyStories/WikiText-103. The large extrapolation tier wins all
|
| 58 |
+
paired seeds across all three regimes (9/9 paired wins), but stage-wise analysis
|
| 59 |
+
shows the schedules are final-loss optimized rather than best at every
|
| 60 |
intermediate prefix. The results support a practical hypothesis: dropout decay
|
| 61 |
should be calibrated as a regime-specific pressure law, not chosen as a
|
| 62 |
universal constant or an arbitrary high-to-low schedule.
|
|
|
|
| 83 |
relative to the current data prefix, and cumulative optimizer sampling relative
|
| 84 |
to that prefix.
|
| 85 |
|
| 86 |
+
We use \emph{regime} to mean a fixed corpus family, tokenizer, architecture
|
| 87 |
+
family, optimizer protocol, dropout placement, stream protocol, and evaluation
|
| 88 |
+
distribution. Model size and prefix size vary inside a regime; changing the
|
| 89 |
+
text distribution, tokenizer, or training protocol defines a new regime. For
|
| 90 |
+
each of the three text regimes studied here, this paper makes four empirical
|
| 91 |
+
contributions.
|
| 92 |
|
| 93 |
\begin{enumerate}
|
| 94 |
+
\item We define per-regime calibration cells for streaming dropout: one model, one
|
| 95 |
unique-token prefix, one sampled-token budget, and a sweep over fixed
|
| 96 |
dropout rates.
|
| 97 |
+
\item We show that per-regime calibration cells often have a parabolic or plateau-like
|
| 98 |
validation-loss curve over dropout, making the local optimum a usable
|
| 99 |
supervised target.
|
| 100 |
+
\item We fit a separate interaction pressure law per regime that maps
|
| 101 |
$(\params,\unique,\sampled)$ to a dropout rate.
|
| 102 |
\item We validate the resulting schedules against broad fixed-dropout
|
| 103 |
baselines across three text regimes and a larger-model/larger-stream
|
|
|
|
| 106 |
|
| 107 |
The central result is not that one coefficient vector works everywhere. It does
|
| 108 |
not. The central result is that the pressure-law structure is useful, while the
|
| 109 |
+
coefficients are regime-specific. A reader should interpret the paper as an
|
| 110 |
+
evidence ladder: static sweeps establish that dropout has a measurable optimum
|
| 111 |
+
inside a regime; coefficient fits show that these optima can be predicted from
|
| 112 |
+
pressure variables; continuing streaming runs test whether the predicted
|
| 113 |
+
trajectory actually improves a single model trained through the expanding
|
| 114 |
+
prefix sequence.
|
| 115 |
|
| 116 |
\section{Related Work}
|
| 117 |
|
|
|
|
| 124 |
captures the key tradeoff in our experiments: low dropout can overfit repeated
|
| 125 |
small prefixes, but high dropout can remove too much usable capacity.
|
| 126 |
|
| 127 |
+
\paragraph{Dropout schedules.}
|
| 128 |
+
This paper is not a survey of every possible adaptive regularization schedule.
|
| 129 |
+
Its controlled comparison is against a best tested fixed-dropout grid, because
|
| 130 |
+
fixed dropout is the default practical choice and gives a clear baseline for
|
| 131 |
+
whether adaptation helps. Early hand-designed high-to-low schedules were useful
|
| 132 |
+
as exploratory probes but were not the final claim; the reported schedules are
|
| 133 |
+
generated from fitted regime coefficients before the streaming validation run.
|
| 134 |
+
Broader comparisons against other adaptive dropout or regularization policies
|
| 135 |
+
are left to future work.
|
| 136 |
+
|
| 137 |
\paragraph{Transformer language models and scaling.}
|
| 138 |
Our model family is a decoder-only Transformer following the attention-based
|
| 139 |
architecture of \citet{vaswani2017attention}. Scaling-law work shows that loss
|
|
|
|
| 148 |
story corpus designed for small language-model studies \citep{eldan2023tinystories}.
|
| 149 |
WikiText-103 is a standard word-level language-modeling benchmark derived from
|
| 150 |
Wikipedia articles \citep{merity2017pointer}. OpenWebText is an open
|
| 151 |
+
WebText-style corpus \citep{gokaslan2019openwebtext}. OpenWebText10K denotes
|
| 152 |
+
the cached/tokenized OpenWebText-style subset used in this project; the suffix
|
| 153 |
+
distinguishes this experimental subset from the full OpenWebText corpus. We use
|
| 154 |
+
cached/tokenized subsets and therefore report results as regime-level evidence
|
| 155 |
+
rather than claims about full-corpus state of the art.
|
| 156 |
+
|
| 157 |
+
\begin{table}[t]
|
| 158 |
+
\centering
|
| 159 |
+
\caption{Text regimes used in the experiments. Prefixes are token counts exposed
|
| 160 |
+
to the trainer at each stream stage; all reported runs use a 4096-token BPE
|
| 161 |
+
vocabulary, so numeric losses should be compared within this tokenizer setting.}
|
| 162 |
+
\label{tab:regimes}
|
| 163 |
+
\resizebox{\textwidth}{!}{\input{tables/regime_setup_table}}
|
| 164 |
+
\end{table}
|
| 165 |
|
| 166 |
\section{Experimental Setting}
|
| 167 |
|
|
|
|
| 174 |
the original copyright and permission notice.
|
| 175 |
|
| 176 |
The architecture family keeps the standard Transformer feed-forward expansion
|
| 177 |
+
ratio of four. We denote architectures as L$x$-H$y$-D$z$, where $x$ is the
|
| 178 |
+
number of Transformer layers, $y$ is the number of attention heads, and $z$ is
|
| 179 |
+
the embedding dimension. The central model sizes are L8-H8-D256 (8.39M parameters),
|
| 180 |
+
L12-H8-D320 (17.37M), L16-H8-D384 (31.46M in the 4096-vocabulary runs; one
|
| 181 |
+
archived metadata path reports 32.71M from a different vocabulary configuration),
|
| 182 |
+
and L20-H8-D448 (51.84M). The tokenizer vocabulary is 4096 in the reported runs.
|
| 183 |
+
Unless noted otherwise, training uses AdamW, learning rate $3\times 10^{-4}$,
|
| 184 |
+
weight decay 0.1, gradient clipping 1.0, batch size 16, and block size 128. All
|
| 185 |
+
Torch training runs are MPS-only; the runner refuses CUDA, CPU execution, and
|
| 186 |
+
MPS fallback.
|
| 187 |
+
|
| 188 |
+
All reported losses are mean next-token cross-entropy losses in nats. The model
|
| 189 |
+
uses the same active dropout probability for embedding dropout, attention-weight
|
| 190 |
+
dropout, attention output/residual dropout, and MLP output dropout. This
|
| 191 |
+
placement is part of the regime definition; changing it would require
|
| 192 |
+
recalibrating the coefficients.
|
| 193 |
|
| 194 |
\subsection{Streaming protocol}
|
| 195 |
|
| 196 |
+
We simulate streaming by revealing larger token prefixes over time. We call this
|
| 197 |
+
the locked-stream setting: the model is not restarted at each prefix; one
|
| 198 |
+
training run keeps the same model and optimizer state as the data stream grows.
|
| 199 |
+
At stage $t$, minibatches are sampled only from the currently revealed prefix
|
| 200 |
$\unique$. The two main protocols are:
|
| 201 |
|
| 202 |
\begin{itemize}
|
| 203 |
+
\item 4M final-prefix validation: OpenWebText10K and WikiText-103 use 250k, 500k, 1M,
|
| 204 |
2M, and 4M prefixes. TinyStories uses 500k, 1M, 2M, and 4M prefixes. These
|
| 205 |
runs use five random seeds.
|
| 206 |
\item 8M extrapolation: L20-H8-D448 with an 8M final prefix. These runs use
|
|
|
|
| 209 |
|
| 210 |
Each run compares a dropout schedule against a grid of static-dropout
|
| 211 |
baselines. The best static baseline is selected after training from the same
|
| 212 |
+
run family, so the decay schedule competes against the best fixed dropout found
|
| 213 |
within the tested grid.
|
| 214 |
|
| 215 |
+
\begin{table}[t]
|
| 216 |
+
\centering
|
| 217 |
+
\caption{Per-regime experimental evidence ladder. The same sequence is run
|
| 218 |
+
separately for OpenWebText10K, TinyStories, and WikiText-103. The streaming rows
|
| 219 |
+
are the decisive validation layers, while the calibration rows explain where the
|
| 220 |
+
schedules come from.}
|
| 221 |
+
\label{tab:protocol}
|
| 222 |
+
\resizebox{\textwidth}{!}{\input{tables/experiment_protocol_table}}
|
| 223 |
+
\end{table}
|
| 224 |
+
|
| 225 |
+
\begin{table}[t]
|
| 226 |
+
\centering
|
| 227 |
+
\caption{Streaming training budgets used for validation. At each optimization
|
| 228 |
+
step, the runner consumes \texttt{batch\_size} $\times$ \texttt{block\_size}
|
| 229 |
+
token positions; therefore $C_t$ is the cumulative sum of sampled token positions
|
| 230 |
+
across stream stages.}
|
| 231 |
+
\label{tab:budgets}
|
| 232 |
+
\resizebox{\textwidth}{!}{\input{tables/protocol_budget_table}}
|
| 233 |
+
\end{table}
|
| 234 |
+
|
| 235 |
\section{From Calibration Cells to a Pressure Law}
|
| 236 |
|
| 237 |
+
Figure~\ref{fig:protocol} summarizes the full procedure. The paper's central
|
| 238 |
+
methodological choice is to separate cheap calibration from expensive streaming
|
| 239 |
+
validation. Static cells are not themselves the final claim; they are probes
|
| 240 |
+
that estimate where a fixed model/prefix combination stops benefiting from more
|
| 241 |
+
or less dropout. The pressure law is fitted from those probes, frozen, and then
|
| 242 |
+
tested in the harder setting where a single model continues training as the
|
| 243 |
+
available stream grows.
|
| 244 |
+
|
| 245 |
+
\begin{figure}[t]
|
| 246 |
+
\centering
|
| 247 |
+
\input{figures/calibration_to_streaming_protocol}
|
| 248 |
+
\caption{Calibration-to-streaming protocol. Static sweeps produce target
|
| 249 |
+
dropouts $p^\star$; a regime-specific pressure law fits those targets; the
|
| 250 |
+
resulting schedule is frozen before locked-stream validation.}
|
| 251 |
+
\label{fig:protocol}
|
| 252 |
+
\end{figure}
|
| 253 |
+
|
| 254 |
\subsection{Calibration cell definition}
|
| 255 |
|
| 256 |
A calibration cell is one static dropout sweep at a fixed tuple:
|
|
|
|
| 267 |
minimum. Boundary optima are retained but downweighted in coefficient fitting
|
| 268 |
because the true optimum may lie outside the tested grid.
|
| 269 |
|
| 270 |
+
Figure~\ref{fig:cell-curves} shows one selected representative cell from each
|
| 271 |
+
regime. These examples are illustrative of the curve shape, not the full
|
| 272 |
+
calibration set. The complete coefficient fits use 15--16 cells per regime and
|
| 273 |
+
are summarized in Figure~\ref{fig:static-optima} and Table~\ref{tab:coefficients}.
|
| 274 |
+
The curves are not perfect mathematical parabolas, but they show the practical
|
| 275 |
+
pattern needed for calibration: validation loss improves as dropout moves away
|
| 276 |
+
from zero, reaches a local minimum or plateau, and then rises when dropout
|
| 277 |
+
becomes too large.
|
| 278 |
|
| 279 |
\begin{figure}[t]
|
| 280 |
\centering
|
| 281 |
\input{figures/calibration_cell_curves}
|
| 282 |
+
\caption{Representative static dropout calibration cells, one selected from
|
| 283 |
+
each regime. Each panel fixes the corpus regime, model size, unique-token
|
| 284 |
+
prefix, sampled-token budget, and validation split, then sweeps static dropout.
|
| 285 |
+
The y-axis is token-level validation cross-entropy in nats above the best tested
|
| 286 |
+
dropout in that cell, so each curve is normalized to show shape rather than
|
| 287 |
+
absolute corpus difficulty. The full calibration sets contain 15--16 cells per
|
| 288 |
+
regime.}
|
| 289 |
\label{fig:cell-curves}
|
| 290 |
\end{figure}
|
| 291 |
|
|
|
|
| 301 |
Increasing unique tokens at fixed model reduces this pressure. The second term
|
| 302 |
measures repeated-sampling pressure. If the optimizer consumes many sampled
|
| 303 |
tokens while the unique prefix remains small, it repeatedly revisits the same
|
| 304 |
+
data and can benefit from stronger regularization. For example, if training
|
| 305 |
+
draws two million token positions from a one-million-token revealed prefix, then
|
| 306 |
+
$\unique=1\mathrm{M}$ and $\sampled=2\mathrm{M}$; the same unique data has been
|
| 307 |
+
sampled for roughly two prefix-equivalents of optimization.
|
| 308 |
+
|
| 309 |
+
\begin{table}[t]
|
| 310 |
+
\centering
|
| 311 |
+
\caption{Symbol glossary. The pressure law uses absolute quantities available
|
| 312 |
+
before or during a run, then converts them into dimensionless pressure variables.}
|
| 313 |
+
\label{tab:symbols}
|
| 314 |
+
\resizebox{0.92\textwidth}{!}{\input{tables/symbol_table}}
|
| 315 |
+
\end{table}
|
| 316 |
|
| 317 |
The fitted interaction family is
|
| 318 |
\begin{equation}
|
|
|
|
| 321 |
\label{eq:interaction-law}
|
| 322 |
\end{equation}
|
| 323 |
For schedule generation we use $p_{\min}=0.02$ and $p_{\max}=0.65$ unless a
|
| 324 |
+
run explicitly specifies a different clamp. The lower bound keeps generated
|
| 325 |
+
decay schedules near but not exactly at zero dropout, while static sweeps may
|
| 326 |
+
still include 0.0 as an ablation. The upper bound keeps generated schedules away
|
| 327 |
+
from the very-high-dropout regime; early experiments with dropout near 0.8
|
| 328 |
+
underfit badly, so this paper does not claim that arbitrarily high initial
|
| 329 |
+
dropout is useful.
|
| 330 |
+
|
| 331 |
+
Operationally, a coefficient fit follows the same recipe in each regime:
|
| 332 |
+
\begin{enumerate}
|
| 333 |
+
\item Choose a small grid of model sizes and unique-token prefixes that
|
| 334 |
+
covers the intended deployment range.
|
| 335 |
+
\item For each cell, train the model with several fixed dropout rates under
|
| 336 |
+
the same sampled-token budget and validation split.
|
| 337 |
+
\item Extract $p^\star$ as the lowest-loss grid point, or as a local
|
| 338 |
+
quadratic minimum when the best grid point is bracketed by higher-loss
|
| 339 |
+
neighbors.
|
| 340 |
+
\item Fit $A,B,D,C_0$ by regressing $p^\star$ on $x_t$, $y_t$, and $x_ty_t$.
|
| 341 |
+
Cells with boundary or weakly identified optima are downweighted because
|
| 342 |
+
their true optimum may lie outside the tested grid. In practice, lower
|
| 343 |
+
weights are assigned to cells whose best dropout is on the tested boundary,
|
| 344 |
+
whose minimum is not bracketed by worse neighbors, whose curve is very flat,
|
| 345 |
+
or whose best-loss estimate is comparatively noisy.
|
| 346 |
+
\item Freeze the coefficients and generate a dropout path from the actual
|
| 347 |
+
streaming prefixes before running the locked-stream validation.
|
| 348 |
+
\end{enumerate}
|
| 349 |
+
|
| 350 |
+
This recipe matters because it prevents the decay schedule from being selected
|
| 351 |
+
after seeing the streaming validation losses. The schedule is allowed to use
|
| 352 |
+
model size, current unique tokens, cumulative sampled tokens, and fitted
|
| 353 |
+
regime coefficients; it is not allowed to tune itself on the final test run.
|
| 354 |
+
|
| 355 |
+
\begin{table}[t]
|
| 356 |
+
\centering
|
| 357 |
+
\caption{Heuristic confidence weights used when fitting coefficient targets.
|
| 358 |
+
Multipliers are cumulative, so a boundary and unbracketed cell receives both
|
| 359 |
+
penalties. These weights reduce the influence of cells where the static optimum
|
| 360 |
+
is weakly identified.}
|
| 361 |
+
\label{tab:weights}
|
| 362 |
+
\resizebox{\textwidth}{!}{\input{tables/calibration_weight_table}}
|
| 363 |
+
\end{table}
|
| 364 |
|
| 365 |
\subsection{Regime-specific coefficients}
|
| 366 |
|
|
|
|
| 371 |
the coefficients.
|
| 372 |
|
| 373 |
Table~\ref{tab:coefficients} gives the fitted interaction coefficients. Each
|
| 374 |
+
regime uses 15 or 16 calibration cells. The error columns are measured in
|
| 375 |
+
dropout-rate units, not validation-loss units. For calibration targets
|
| 376 |
+
$p_i^\star$ and formula predictions $\hat p_i$, the reported mean absolute
|
| 377 |
+
error is
|
| 378 |
+
\[
|
| 379 |
+
\mathrm{MAE}=\frac{1}{N}\sum_{i=1}^{N}|\hat p_i-p_i^\star|.
|
| 380 |
+
\]
|
| 381 |
+
The fitted MAE is about 0.016--0.018 dropout, meaning the coefficient law
|
| 382 |
+
typically predicts the calibrated static optimum to within roughly two
|
| 383 |
+
hundredths of dropout. Leave-model-out MAE refits the coefficients while holding
|
| 384 |
+
out one model size, then predicts the held-out model cells. Leave-prefix-out
|
| 385 |
+
MAE does the same while holding out one unique-token prefix. These leave-out
|
| 386 |
+
columns test whether the formula generalizes across model sizes and stream
|
| 387 |
+
prefix sizes inside the same regime.
|
| 388 |
|
| 389 |
\begin{table}[t]
|
| 390 |
\centering
|
| 391 |
+
\caption{Regime-specific interaction coefficient fits. Dropout MAE is mean
|
| 392 |
+
absolute error in predicted dropout rate, not validation loss; units are
|
| 393 |
+
absolute dropout probability. L-model and L-prefix are leave-model-out and
|
| 394 |
+
leave-prefix-out dropout MAEs.}
|
| 395 |
\label{tab:coefficients}
|
| 396 |
\resizebox{\textwidth}{!}{\input{tables/coefficient_table}}
|
| 397 |
\end{table}
|
|
|
|
| 420 |
The ``Gain'' column is best static final validation loss minus decay final
|
| 421 |
validation loss, so positive values favor decay. The best static baseline is
|
| 422 |
chosen from the tested fixed-dropout grid in the same run family.
|
| 423 |
+
\[
|
| 424 |
+
\mathrm{Gain}
|
| 425 |
+
=L_{\mathrm{final}}(\mathrm{best\ static})
|
| 426 |
+
-L_{\mathrm{final}}(\mathrm{decay}).
|
| 427 |
+
\]
|
| 428 |
+
Thus positive gain means the decay schedule has lower final validation loss
|
| 429 |
+
than the best tested fixed-dropout baseline.
|
| 430 |
+
|
| 431 |
+
Table~\ref{tab:evidence-ladder} compresses the full evidence ladder into one
|
| 432 |
+
view. The calibration MAE columns are dropout-rate prediction errors, not final
|
| 433 |
+
validation metrics; they measure how well the pressure law explains static-cell
|
| 434 |
+
optima. The gain and paired-win columns are the actual streaming tests. The
|
| 435 |
+
pattern is consistent across all three regimes: the law fits static targets
|
| 436 |
+
within roughly two hundredths of dropout, and the resulting schedules beat the
|
| 437 |
+
best tested fixed-dropout baseline at the final prefix.
|
| 438 |
+
|
| 439 |
+
\begin{table}[t]
|
| 440 |
+
\centering
|
| 441 |
+
\caption{Combined calibration and streaming evidence. Calibration MAE is
|
| 442 |
+
dropout-rate prediction error. Gain is
|
| 443 |
+
$L_{\mathrm{final}}(\mathrm{best\ static})-L_{\mathrm{final}}(\mathrm{decay})$,
|
| 444 |
+
so positive gain favors decay; gain units are token-level cross-entropy nats.
|
| 445 |
+
Wins are paired random-seed wins.}
|
| 446 |
+
\label{tab:evidence-ladder}
|
| 447 |
+
\resizebox{0.88\textwidth}{!}{\input{tables/evidence_ladder_table}}
|
| 448 |
+
\end{table}
|
| 449 |
|
| 450 |
\begin{table}[t]
|
| 451 |
\centering
|
| 452 |
+
\caption{Streaming validation against best fixed-dropout baselines. Final losses
|
| 453 |
+
are mean token-level cross-entropy in nats, reported as mean $\pm$ sample
|
| 454 |
+
standard deviation across seeds.}
|
| 455 |
\label{tab:streaming-validation}
|
| 456 |
\resizebox{\textwidth}{!}{\input{tables/streaming_validation_table}}
|
| 457 |
\end{table}
|
| 458 |
|
| 459 |
+
\begin{table}[t]
|
| 460 |
+
\centering
|
| 461 |
+
\caption{Paired final-loss gain audit. Paired gain is each seed's best static
|
| 462 |
+
final loss minus that seed's decay final loss. Confidence intervals are
|
| 463 |
+
nonparametric bootstrap intervals over seeds; the three-seed 8M intervals are
|
| 464 |
+
descriptive rather than definitive.}
|
| 465 |
+
\label{tab:paired-ci}
|
| 466 |
+
\resizebox{\textwidth}{!}{\input{tables/paired_gain_ci_table}}
|
| 467 |
+
\end{table}
|
| 468 |
+
|
| 469 |
OpenWebText10K provides the cleanest five-seed coefficient-derived validation:
|
| 470 |
the interaction schedule improves final validation loss by 0.0473 over the
|
| 471 |
best static baseline and wins all five paired seeds. TinyStories shows a
|
| 472 |
smaller but consistent final-loss margin: 0.0133 over the best static baseline
|
| 473 |
+
with five paired wins. WikiText-103 also improves at the final 4M prefix, with
|
| 474 |
+
a 0.0297 gain and five paired wins. Its supporting ablations show a useful
|
| 475 |
+
caveat: an interaction schedule fitted only to static-cell optima can decay to
|
| 476 |
+
the dropout floor too early for L12 streaming and land near the best static
|
| 477 |
+
baseline. We therefore treat static-cell fit as calibration evidence, not as a
|
| 478 |
+
substitute for locked-stream validation.
|
| 479 |
|
| 480 |
\subsection{L20 8M extrapolation}
|
| 481 |
|
|
|
|
| 487 |
baseline on final validation loss and wins all paired seeds (3/3 in each
|
| 488 |
regime, 9/9 total).
|
| 489 |
|
| 490 |
+
Table~\ref{tab:l20-paths} makes the extrapolation test concrete. The schedules
|
| 491 |
+
are not arbitrary hand-picked names; they are the dropout values produced by
|
| 492 |
+
the fitted regime coefficients at each revealed prefix. The final static
|
| 493 |
+
baseline is the best fixed dropout found from the companion static grid for the
|
| 494 |
+
same L20 stream.
|
| 495 |
+
|
| 496 |
+
\begin{table}[t]
|
| 497 |
+
\centering
|
| 498 |
+
\caption{Frozen L20 locked-stream extrapolation schedules generated before
|
| 499 |
+
validation. In each row, the same model and optimizer continue training across
|
| 500 |
+
the prefix path while the dropout follows the frozen decay path.}
|
| 501 |
+
\label{tab:l20-paths}
|
| 502 |
+
\resizebox{\textwidth}{!}{\input{tables/l20_schedule_path_table}}
|
| 503 |
+
\end{table}
|
| 504 |
+
|
| 505 |
Figure~\ref{fig:final-improvements} visualizes the final-loss gains. The
|
| 506 |
largest L20 gain is OpenWebText10K (0.0363), followed by WikiText-103 (0.0184)
|
| 507 |
+
and TinyStories (0.0100). The TinyStories gain is smaller because the best fixed
|
| 508 |
+
baseline is already unusually competitive: static dropout near 0.20 regularizes
|
| 509 |
+
the early prefixes reasonably well on this simpler corpus and does not
|
| 510 |
+
underperform as sharply as fixed dropout does in OpenWebText10K. The decay
|
| 511 |
+
schedule still wins, but it has less fixed-rate error to remove.
|
| 512 |
|
| 513 |
\begin{figure}[t]
|
| 514 |
\centering
|
| 515 |
\input{figures/final_improvements}
|
| 516 |
\caption{Final validation-loss improvement over the best fixed-dropout
|
| 517 |
+
baseline. Values are token-level cross-entropy improvements in nats; positive
|
| 518 |
+
values favor the decay schedule.}
|
| 519 |
\label{fig:final-improvements}
|
| 520 |
\end{figure}
|
| 521 |
|
|
|
|
| 530 |
|
| 531 |
\begin{table}[t]
|
| 532 |
\centering
|
| 533 |
+
\caption{L20 locked-stream stage-wise comparison. The same model and optimizer
|
| 534 |
+
continue training across increasing token prefixes. Delta is decay validation
|
| 535 |
+
loss minus the best static validation loss at the same prefix, in nats; negative
|
| 536 |
+
favors decay.}
|
| 537 |
\label{tab:l20-stage}
|
| 538 |
\resizebox{\textwidth}{!}{\input{tables/l20_stage_table}}
|
| 539 |
\end{table}
|
|
|
|
| 542 |
\centering
|
| 543 |
\input{figures/l20_stage_deltas}
|
| 544 |
\caption{L20 stage-wise deltas versus the best static dropout at each prefix.
|
| 545 |
+
The plotted value is token-level decay loss minus best static loss in nats, so
|
| 546 |
+
values below zero favor decay. The schedules are final-loss schedules, not
|
| 547 |
+
greedy per-prefix optima.}
|
| 548 |
\label{fig:l20-stage-deltas}
|
| 549 |
\end{figure}
|
| 550 |
|
|
|
|
| 585 |
restart and optimize each prefix independently. Static baselines can be locally
|
| 586 |
optimal at one prefix but cannot adapt when the stream changes.
|
| 587 |
|
| 588 |
+
\paragraph{What the result does and does not prove.}
|
| 589 |
+
The evidence supports a procedure, not a universal numeric constant. For a
|
| 590 |
+
given regime, a small static calibration grid can estimate coefficient values
|
| 591 |
+
that generate useful dropout schedules across model and prefix scale. The
|
| 592 |
+
evidence does not show that the same coefficients should transfer unchanged to
|
| 593 |
+
a different tokenizer, corpus distribution, optimizer, sequence length, or
|
| 594 |
+
dropout placement. Those changes define a new regime and should trigger a new
|
| 595 |
+
calibration.
|
| 596 |
+
|
| 597 |
+
\paragraph{Applying the procedure to a new regime.}
|
| 598 |
+
The intended use is procedural: select a small grid of model sizes and prefix
|
| 599 |
+
sizes that spans the deployment range, run static dropout sweeps for those
|
| 600 |
+
cells, extract $p^\star$ targets, fit $A,B,D,C_0$, freeze the resulting schedule,
|
| 601 |
+
and validate it in a continuing stream against the best tested fixed dropout.
|
| 602 |
+
The calibration step is cheaper than full multi-seed streaming because it probes
|
| 603 |
+
fixed cells rather than repeatedly training full streaming schedules.
|
| 604 |
+
|
| 605 |
\section{Limitations}
|
| 606 |
|
| 607 |
The experiments are intentionally small compared with frontier language-model
|
|
|
|
| 613 |
The static coefficient fit optimizes dropout targets extracted from static
|
| 614 |
sweeps, while the streaming objective is final validation loss after continued
|
| 615 |
training. WikiText-103 shows that these objectives can diverge: the fitted
|
| 616 |
+
interaction schedule predicts static-cell optima accurately but decays too
|
| 617 |
quickly for L12 streaming. Future work should fit coefficients directly against
|
| 618 |
streaming objective functions or include trajectory-aware loss terms.
|
| 619 |
|
| 620 |
The L20 extrapolation tier uses three seeds for cost reasons. This is balanced
|
| 621 |
across all three regimes and supported by five-seed smaller-stream validation,
|
| 622 |
+
but the bootstrap intervals in Table~\ref{tab:paired-ci} should be read as
|
| 623 |
+
descriptive at $n=3$, not as a substitute for larger seed counts. We also do not
|
| 624 |
+
claim that the tested fixed-dropout grids contain every possible fixed optimum,
|
| 625 |
+
or that they exhaust all possible adaptive regularization baselines.
|
| 626 |
|
| 627 |
\section{Reproducibility}
|
| 628 |
|
|
|
|
| 633 |
figures and tables are generated by
|
| 634 |
\texttt{scripts/generate\_paper\_assets.py}. Existing result artifacts are read
|
| 635 |
from \texttt{runs/}. The experiment runner enforces MPS-only Torch execution.
|
| 636 |
+
Code, cached artifacts, experiment outputs, and paper-generation scripts are
|
| 637 |
+
available at \url{https://huggingface.co/cuber12/dropout-decay}.
|
| 638 |
+
|
| 639 |
+
\begin{table}[t]
|
| 640 |
+
\centering
|
| 641 |
+
\caption{Reproducibility metadata for the manuscript build and reported
|
| 642 |
+
experiments. The final public release should cite an immutable repository tag or
|
| 643 |
+
commit; the table records the current base commit and software stack used while
|
| 644 |
+
preparing this manuscript.}
|
| 645 |
+
\label{tab:repro}
|
| 646 |
+
\resizebox{\textwidth}{!}{\input{tables/reproducibility_table}}
|
| 647 |
+
\end{table}
|
| 648 |
|
| 649 |
All generated tables in this paper are derived from saved metrics JSONL files
|
| 650 |
and coefficient JSON files. The paper-generation summary is written to
|
paper/figures/calibration_cell_curves.tex
CHANGED
|
@@ -25,7 +25,6 @@
|
|
| 25 |
\nextgroupplot[
|
| 26 |
title={TinyStories, L12, 1M},
|
| 27 |
xlabel={Dropout},
|
| 28 |
-
ylabel={Validation loss above best},
|
| 29 |
ymin=0,
|
| 30 |
grid=both,
|
| 31 |
]
|
|
@@ -38,7 +37,6 @@
|
|
| 38 |
\nextgroupplot[
|
| 39 |
title={WikiText-103, L12, 250k},
|
| 40 |
xlabel={Dropout},
|
| 41 |
-
ylabel={Validation loss above best},
|
| 42 |
ymin=0,
|
| 43 |
grid=both,
|
| 44 |
]
|
|
|
|
| 25 |
\nextgroupplot[
|
| 26 |
title={TinyStories, L12, 1M},
|
| 27 |
xlabel={Dropout},
|
|
|
|
| 28 |
ymin=0,
|
| 29 |
grid=both,
|
| 30 |
]
|
|
|
|
| 37 |
\nextgroupplot[
|
| 38 |
title={WikiText-103, L12, 250k},
|
| 39 |
xlabel={Dropout},
|
|
|
|
| 40 |
ymin=0,
|
| 41 |
grid=both,
|
| 42 |
]
|
paper/figures/calibration_to_streaming_protocol.tex
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tikzpicture}[font=\scriptsize]
|
| 2 |
+
\tikzstyle{box}=[
|
| 3 |
+
draw,
|
| 4 |
+
rounded corners=2pt,
|
| 5 |
+
thick,
|
| 6 |
+
align=center,
|
| 7 |
+
text width=0.19\textwidth,
|
| 8 |
+
minimum height=1.5cm,
|
| 9 |
+
inner sep=5pt
|
| 10 |
+
]
|
| 11 |
+
\node[box, fill=blue!7] at (0,0) (sweep) {Static calibration cells\\
|
| 12 |
+
\footnotesize model $P$, prefix $U$, sampled tokens $C$, dropout grid};
|
| 13 |
+
\node[box, fill=green!8] at (3.7,0) (target) {Extract $p^\star$\\
|
| 14 |
+
\footnotesize grid best or bracketed quadratic minimum};
|
| 15 |
+
\node[box, fill=yellow!12] at (7.4,0) (fit) {Fit pressure law\\
|
| 16 |
+
\footnotesize $p^\star \approx A x + B y + Dxy + C_0$};
|
| 17 |
+
\node[box, fill=red!7] at (11.1,0) (stream) {Frozen streaming test\\
|
| 18 |
+
\footnotesize compare decay path to best static dropout grid};
|
| 19 |
+
\draw[->, thick] (sweep.east) -- (target.west);
|
| 20 |
+
\draw[->, thick] (target.east) -- (fit.west);
|
| 21 |
+
\draw[->, thick] (fit.east) -- (stream.west);
|
| 22 |
+
\node[align=center, text width=0.9\textwidth] at (5.55,-1.45) {
|
| 23 |
+
Inputs to the fitted law are absolute quantities available before or during a run:
|
| 24 |
+
$x=\log_{10}(P/U)$ measures capacity pressure and
|
| 25 |
+
$y=\log_{10}(C/U)$ measures repeated-sampling pressure.
|
| 26 |
+
};
|
| 27 |
+
\end{tikzpicture}
|
paper/figures/static_optima_by_regime.tex
CHANGED
|
@@ -20,11 +20,11 @@
|
|
| 20 |
grid=both,
|
| 21 |
]
|
| 22 |
\addplot+[thick, mark=*] coordinates {(0,0.5062) (1,0.3559) (2,0.2174) (3,0.1364) (4,0.0224)};
|
| 23 |
-
\addlegendentry{L12
|
| 24 |
\addplot+[thick, mark=*] coordinates {(0,0.6039) (1,0.4475) (2,0.2837) (3,0.1388) (4,0.0272)};
|
| 25 |
-
\addlegendentry{L16
|
| 26 |
\addplot+[thick, mark=*] coordinates {(0,0.3837) (1,0.2401) (2,0.1463) (3,0.0691) (4,0.0000)};
|
| 27 |
-
\addlegendentry{L8
|
| 28 |
|
| 29 |
|
| 30 |
\nextgroupplot[
|
|
@@ -38,11 +38,11 @@
|
|
| 38 |
grid=both,
|
| 39 |
]
|
| 40 |
\addplot+[thick, mark=*] coordinates {(0,0.4575) (1,0.2947) (2,0.1866) (3,0.0703) (4,0.0303)};
|
| 41 |
-
\addlegendentry{L12
|
| 42 |
\addplot+[thick, mark=*] coordinates {(0,0.5699) (2,0.2450) (4,0.0468)};
|
| 43 |
-
\addlegendentry{L16
|
| 44 |
\addplot+[thick, mark=*] coordinates {(0,0.3491) (2,0.0977) (4,0.0000)};
|
| 45 |
-
\addlegendentry{L8
|
| 46 |
|
| 47 |
|
| 48 |
\nextgroupplot[
|
|
@@ -56,11 +56,11 @@
|
|
| 56 |
grid=both,
|
| 57 |
]
|
| 58 |
\addplot+[thick, mark=*] coordinates {(0,0.1645) (1,0.0299) (2,0.0000) (3,0.0000) (4,0.0000)};
|
| 59 |
-
\addlegendentry{L12
|
| 60 |
\addplot+[thick, mark=*] coordinates {(0,0.2459) (1,0.0822) (2,0.0225) (3,0.0000) (4,0.0000)};
|
| 61 |
-
\addlegendentry{L16
|
| 62 |
\addplot+[thick, mark=*] coordinates {(0,0.0965) (1,0.0114) (2,0.0000) (3,0.0000) (4,0.0000)};
|
| 63 |
-
\addlegendentry{L8
|
| 64 |
|
| 65 |
\end{groupplot}
|
| 66 |
\end{tikzpicture}
|
|
|
|
| 20 |
grid=both,
|
| 21 |
]
|
| 22 |
\addplot+[thick, mark=*] coordinates {(0,0.5062) (1,0.3559) (2,0.2174) (3,0.1364) (4,0.0224)};
|
| 23 |
+
\addlegendentry{L12-H8-D320}
|
| 24 |
\addplot+[thick, mark=*] coordinates {(0,0.6039) (1,0.4475) (2,0.2837) (3,0.1388) (4,0.0272)};
|
| 25 |
+
\addlegendentry{L16-H8-D384}
|
| 26 |
\addplot+[thick, mark=*] coordinates {(0,0.3837) (1,0.2401) (2,0.1463) (3,0.0691) (4,0.0000)};
|
| 27 |
+
\addlegendentry{L8-H8-D256}
|
| 28 |
|
| 29 |
|
| 30 |
\nextgroupplot[
|
|
|
|
| 38 |
grid=both,
|
| 39 |
]
|
| 40 |
\addplot+[thick, mark=*] coordinates {(0,0.4575) (1,0.2947) (2,0.1866) (3,0.0703) (4,0.0303)};
|
| 41 |
+
\addlegendentry{L12-H8-D320}
|
| 42 |
\addplot+[thick, mark=*] coordinates {(0,0.5699) (2,0.2450) (4,0.0468)};
|
| 43 |
+
\addlegendentry{L16-H8-D384}
|
| 44 |
\addplot+[thick, mark=*] coordinates {(0,0.3491) (2,0.0977) (4,0.0000)};
|
| 45 |
+
\addlegendentry{L8-H8-D256}
|
| 46 |
|
| 47 |
|
| 48 |
\nextgroupplot[
|
|
|
|
| 56 |
grid=both,
|
| 57 |
]
|
| 58 |
\addplot+[thick, mark=*] coordinates {(0,0.1645) (1,0.0299) (2,0.0000) (3,0.0000) (4,0.0000)};
|
| 59 |
+
\addlegendentry{L12-H8-D320}
|
| 60 |
\addplot+[thick, mark=*] coordinates {(0,0.2459) (1,0.0822) (2,0.0225) (3,0.0000) (4,0.0000)};
|
| 61 |
+
\addlegendentry{L16-H8-D384}
|
| 62 |
\addplot+[thick, mark=*] coordinates {(0,0.0965) (1,0.0114) (2,0.0000) (3,0.0000) (4,0.0000)};
|
| 63 |
+
\addlegendentry{L8-H8-D256}
|
| 64 |
|
| 65 |
\end{groupplot}
|
| 66 |
\end{tikzpicture}
|
paper/paper_results_summary.json
CHANGED
|
@@ -30,9 +30,76 @@
|
|
| 30 |
-0.052590467035770416,
|
| 31 |
-0.053600385785102844
|
| 32 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
"paired_wins": 5,
|
| 34 |
"paired_mean_delta": -0.04732322543859482,
|
| 35 |
"paired_std_delta": 0.010738969078098962,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
"stage_deltas": [
|
| 37 |
{
|
| 38 |
"stage": 0,
|
|
@@ -106,9 +173,61 @@
|
|
| 106 |
-0.025513865053653717,
|
| 107 |
-0.03717709332704544
|
| 108 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
"paired_wins": 3,
|
| 110 |
"paired_mean_delta": -0.03401404867569605,
|
| 111 |
"paired_std_delta": 0.007441203715372809,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
"stage_deltas": [
|
| 113 |
{
|
| 114 |
"stage": 0,
|
|
@@ -210,9 +329,75 @@
|
|
| 210 |
-0.016586389392614365,
|
| 211 |
-0.014097623527050018
|
| 212 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
"paired_wins": 5,
|
| 214 |
"paired_mean_delta": -0.012309029698371887,
|
| 215 |
"paired_std_delta": 0.00786865194496459,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
"stage_deltas": [
|
| 217 |
{
|
| 218 |
"stage": 0,
|
|
@@ -275,9 +460,60 @@
|
|
| 275 |
-0.006095590069890022,
|
| 276 |
-0.013002954423427582
|
| 277 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
"paired_wins": 3,
|
| 279 |
"paired_mean_delta": -0.00926398734251658,
|
| 280 |
"paired_std_delta": 0.0034888512447114515,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
"stage_deltas": [
|
| 282 |
{
|
| 283 |
"stage": 0,
|
|
@@ -368,9 +604,76 @@
|
|
| 368 |
-0.02507050335407257,
|
| 369 |
-0.037036627531051636
|
| 370 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
"paired_wins": 5,
|
| 372 |
"paired_mean_delta": -0.0251707561314106,
|
| 373 |
"paired_std_delta": 0.007752385341386418,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 374 |
"stage_deltas": [
|
| 375 |
{
|
| 376 |
"stage": 0,
|
|
@@ -444,9 +747,61 @@
|
|
| 444 |
-0.00015844032168388367,
|
| 445 |
-0.027258697897195816
|
| 446 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
"paired_wins": 3,
|
| 448 |
"paired_mean_delta": -0.014645076046387354,
|
| 449 |
"paired_std_delta": 0.013646872385042126,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 450 |
"stage_deltas": [
|
| 451 |
{
|
| 452 |
"stage": 0,
|
|
|
|
| 30 |
-0.052590467035770416,
|
| 31 |
-0.053600385785102844
|
| 32 |
],
|
| 33 |
+
"paired_records": [
|
| 34 |
+
{
|
| 35 |
+
"seed": 1,
|
| 36 |
+
"decay_loss": 4.402347795665264,
|
| 37 |
+
"best_static_condition": "static_dropout_0.14",
|
| 38 |
+
"best_static_loss": 4.4417688846588135,
|
| 39 |
+
"delta": -0.03942108899354935,
|
| 40 |
+
"gain": 0.03942108899354935
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"seed": 2,
|
| 44 |
+
"decay_loss": 4.401971310377121,
|
| 45 |
+
"best_static_condition": "static_dropout_0.14",
|
| 46 |
+
"best_static_loss": 4.460222490131855,
|
| 47 |
+
"delta": -0.05825117975473404,
|
| 48 |
+
"gain": 0.05825117975473404
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"seed": 3,
|
| 52 |
+
"decay_loss": 4.402896843850613,
|
| 53 |
+
"best_static_condition": "static_dropout_0.14",
|
| 54 |
+
"best_static_loss": 4.43564984947443,
|
| 55 |
+
"delta": -0.032753005623817444,
|
| 56 |
+
"gain": 0.032753005623817444
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"seed": 4,
|
| 60 |
+
"decay_loss": 4.381064593791962,
|
| 61 |
+
"best_static_condition": "static_dropout_0.14",
|
| 62 |
+
"best_static_loss": 4.433655060827732,
|
| 63 |
+
"delta": -0.052590467035770416,
|
| 64 |
+
"gain": 0.052590467035770416
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"seed": 5,
|
| 68 |
+
"decay_loss": 4.402371659874916,
|
| 69 |
+
"best_static_condition": "static_dropout_0.14",
|
| 70 |
+
"best_static_loss": 4.455972045660019,
|
| 71 |
+
"delta": -0.053600385785102844,
|
| 72 |
+
"gain": 0.053600385785102844
|
| 73 |
+
}
|
| 74 |
+
],
|
| 75 |
"paired_wins": 5,
|
| 76 |
"paired_mean_delta": -0.04732322543859482,
|
| 77 |
"paired_std_delta": 0.010738969078098962,
|
| 78 |
+
"paired_gain_mean": 0.04732322543859482,
|
| 79 |
+
"paired_gain_std": 0.010738969078098962,
|
| 80 |
+
"paired_gain_ci_low": 0.0382560983300209,
|
| 81 |
+
"paired_gain_ci_high": 0.055258719623088835,
|
| 82 |
+
"budget": {
|
| 83 |
+
"steps_per_stage": [
|
| 84 |
+
1000
|
| 85 |
+
],
|
| 86 |
+
"batch_sizes": [
|
| 87 |
+
16
|
| 88 |
+
],
|
| 89 |
+
"block_size": 128,
|
| 90 |
+
"sampled_per_stage": [
|
| 91 |
+
2048000
|
| 92 |
+
],
|
| 93 |
+
"final_sampled_tokens": 10240000,
|
| 94 |
+
"prefix_path": [
|
| 95 |
+
250000,
|
| 96 |
+
500000,
|
| 97 |
+
1000000,
|
| 98 |
+
2000000,
|
| 99 |
+
4000000
|
| 100 |
+
],
|
| 101 |
+
"stage_count": 5
|
| 102 |
+
},
|
| 103 |
"stage_deltas": [
|
| 104 |
{
|
| 105 |
"stage": 0,
|
|
|
|
| 173 |
-0.025513865053653717,
|
| 174 |
-0.03717709332704544
|
| 175 |
],
|
| 176 |
+
"paired_records": [
|
| 177 |
+
{
|
| 178 |
+
"seed": 1,
|
| 179 |
+
"decay_loss": 4.192408442497253,
|
| 180 |
+
"best_static_condition": "static_dropout_0.18",
|
| 181 |
+
"best_static_loss": 4.231759630143642,
|
| 182 |
+
"delta": -0.03935118764638901,
|
| 183 |
+
"gain": 0.03935118764638901
|
| 184 |
+
},
|
| 185 |
+
{
|
| 186 |
+
"seed": 2,
|
| 187 |
+
"decay_loss": 4.180009409785271,
|
| 188 |
+
"best_static_condition": "static_dropout_0.2",
|
| 189 |
+
"best_static_loss": 4.205523274838924,
|
| 190 |
+
"delta": -0.025513865053653717,
|
| 191 |
+
"gain": 0.025513865053653717
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
"seed": 3,
|
| 195 |
+
"decay_loss": 4.165537476539612,
|
| 196 |
+
"best_static_condition": "static_dropout_0.14",
|
| 197 |
+
"best_static_loss": 4.202714569866657,
|
| 198 |
+
"delta": -0.03717709332704544,
|
| 199 |
+
"gain": 0.03717709332704544
|
| 200 |
+
}
|
| 201 |
+
],
|
| 202 |
"paired_wins": 3,
|
| 203 |
"paired_mean_delta": -0.03401404867569605,
|
| 204 |
"paired_std_delta": 0.007441203715372809,
|
| 205 |
+
"paired_gain_mean": 0.03401404867569605,
|
| 206 |
+
"paired_gain_std": 0.007441203715372809,
|
| 207 |
+
"paired_gain_ci_low": 0.025513865053653717,
|
| 208 |
+
"paired_gain_ci_high": 0.03935118764638901,
|
| 209 |
+
"budget": {
|
| 210 |
+
"steps_per_stage": [
|
| 211 |
+
1000
|
| 212 |
+
],
|
| 213 |
+
"batch_sizes": [
|
| 214 |
+
16
|
| 215 |
+
],
|
| 216 |
+
"block_size": 128,
|
| 217 |
+
"sampled_per_stage": [
|
| 218 |
+
2048000
|
| 219 |
+
],
|
| 220 |
+
"final_sampled_tokens": 12288000,
|
| 221 |
+
"prefix_path": [
|
| 222 |
+
250000,
|
| 223 |
+
500000,
|
| 224 |
+
1000000,
|
| 225 |
+
2000000,
|
| 226 |
+
4000000,
|
| 227 |
+
8000000
|
| 228 |
+
],
|
| 229 |
+
"stage_count": 6
|
| 230 |
+
},
|
| 231 |
"stage_deltas": [
|
| 232 |
{
|
| 233 |
"stage": 0,
|
|
|
|
| 329 |
-0.016586389392614365,
|
| 330 |
-0.014097623527050018
|
| 331 |
],
|
| 332 |
+
"paired_records": [
|
| 333 |
+
{
|
| 334 |
+
"seed": 1,
|
| 335 |
+
"decay_loss": 2.541424009948969,
|
| 336 |
+
"best_static_condition": "static_dropout_0.08",
|
| 337 |
+
"best_static_loss": 2.54193027690053,
|
| 338 |
+
"delta": -0.0005062669515609741,
|
| 339 |
+
"gain": 0.0005062669515609741
|
| 340 |
+
},
|
| 341 |
+
{
|
| 342 |
+
"seed": 2,
|
| 343 |
+
"decay_loss": 2.5376960188150406,
|
| 344 |
+
"best_static_condition": "static_dropout_0.12",
|
| 345 |
+
"best_static_loss": 2.558806713670492,
|
| 346 |
+
"delta": -0.021110694855451584,
|
| 347 |
+
"gain": 0.021110694855451584
|
| 348 |
+
},
|
| 349 |
+
{
|
| 350 |
+
"seed": 3,
|
| 351 |
+
"decay_loss": 2.5385167226195335,
|
| 352 |
+
"best_static_condition": "static_dropout_0.08",
|
| 353 |
+
"best_static_loss": 2.547760896384716,
|
| 354 |
+
"delta": -0.009244173765182495,
|
| 355 |
+
"gain": 0.009244173765182495
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"seed": 4,
|
| 359 |
+
"decay_loss": 2.493242312222719,
|
| 360 |
+
"best_static_condition": "static_dropout_0.08",
|
| 361 |
+
"best_static_loss": 2.5098287016153336,
|
| 362 |
+
"delta": -0.016586389392614365,
|
| 363 |
+
"gain": 0.016586389392614365
|
| 364 |
+
},
|
| 365 |
+
{
|
| 366 |
+
"seed": 5,
|
| 367 |
+
"decay_loss": 2.5446842312812805,
|
| 368 |
+
"best_static_condition": "static_dropout_0.08",
|
| 369 |
+
"best_static_loss": 2.5587818548083305,
|
| 370 |
+
"delta": -0.014097623527050018,
|
| 371 |
+
"gain": 0.014097623527050018
|
| 372 |
+
}
|
| 373 |
+
],
|
| 374 |
"paired_wins": 5,
|
| 375 |
"paired_mean_delta": -0.012309029698371887,
|
| 376 |
"paired_std_delta": 0.00786865194496459,
|
| 377 |
+
"paired_gain_mean": 0.012309029698371887,
|
| 378 |
+
"paired_gain_std": 0.00786865194496459,
|
| 379 |
+
"paired_gain_ci_low": 0.005942809581756592,
|
| 380 |
+
"paired_gain_ci_high": 0.017898358404636383,
|
| 381 |
+
"budget": {
|
| 382 |
+
"steps_per_stage": [
|
| 383 |
+
2000
|
| 384 |
+
],
|
| 385 |
+
"batch_sizes": [
|
| 386 |
+
16
|
| 387 |
+
],
|
| 388 |
+
"block_size": 128,
|
| 389 |
+
"sampled_per_stage": [
|
| 390 |
+
4096000
|
| 391 |
+
],
|
| 392 |
+
"final_sampled_tokens": 16384000,
|
| 393 |
+
"prefix_path": [
|
| 394 |
+
500000,
|
| 395 |
+
1000000,
|
| 396 |
+
2000000,
|
| 397 |
+
4000000
|
| 398 |
+
],
|
| 399 |
+
"stage_count": 4
|
| 400 |
+
},
|
| 401 |
"stage_deltas": [
|
| 402 |
{
|
| 403 |
"stage": 0,
|
|
|
|
| 460 |
-0.006095590069890022,
|
| 461 |
-0.013002954423427582
|
| 462 |
],
|
| 463 |
+
"paired_records": [
|
| 464 |
+
{
|
| 465 |
+
"seed": 1,
|
| 466 |
+
"decay_loss": 2.206169916316867,
|
| 467 |
+
"best_static_condition": "static_dropout_0.2",
|
| 468 |
+
"best_static_loss": 2.214863333851099,
|
| 469 |
+
"delta": -0.00869341753423214,
|
| 470 |
+
"gain": 0.00869341753423214
|
| 471 |
+
},
|
| 472 |
+
{
|
| 473 |
+
"seed": 2,
|
| 474 |
+
"decay_loss": 2.2139150239527225,
|
| 475 |
+
"best_static_condition": "static_dropout_0.2",
|
| 476 |
+
"best_static_loss": 2.2200106140226126,
|
| 477 |
+
"delta": -0.006095590069890022,
|
| 478 |
+
"gain": 0.006095590069890022
|
| 479 |
+
},
|
| 480 |
+
{
|
| 481 |
+
"seed": 3,
|
| 482 |
+
"decay_loss": 2.2056322395801544,
|
| 483 |
+
"best_static_condition": "static_dropout_0.18",
|
| 484 |
+
"best_static_loss": 2.218635194003582,
|
| 485 |
+
"delta": -0.013002954423427582,
|
| 486 |
+
"gain": 0.013002954423427582
|
| 487 |
+
}
|
| 488 |
+
],
|
| 489 |
"paired_wins": 3,
|
| 490 |
"paired_mean_delta": -0.00926398734251658,
|
| 491 |
"paired_std_delta": 0.0034888512447114515,
|
| 492 |
+
"paired_gain_mean": 0.00926398734251658,
|
| 493 |
+
"paired_gain_std": 0.0034888512447114515,
|
| 494 |
+
"paired_gain_ci_low": 0.006095590069890022,
|
| 495 |
+
"paired_gain_ci_high": 0.013002954423427582,
|
| 496 |
+
"budget": {
|
| 497 |
+
"steps_per_stage": [
|
| 498 |
+
2000
|
| 499 |
+
],
|
| 500 |
+
"batch_sizes": [
|
| 501 |
+
16
|
| 502 |
+
],
|
| 503 |
+
"block_size": 128,
|
| 504 |
+
"sampled_per_stage": [
|
| 505 |
+
4096000
|
| 506 |
+
],
|
| 507 |
+
"final_sampled_tokens": 20480000,
|
| 508 |
+
"prefix_path": [
|
| 509 |
+
500000,
|
| 510 |
+
1000000,
|
| 511 |
+
2000000,
|
| 512 |
+
4000000,
|
| 513 |
+
8000000
|
| 514 |
+
],
|
| 515 |
+
"stage_count": 5
|
| 516 |
+
},
|
| 517 |
"stage_deltas": [
|
| 518 |
{
|
| 519 |
"stage": 0,
|
|
|
|
| 604 |
-0.02507050335407257,
|
| 605 |
-0.037036627531051636
|
| 606 |
],
|
| 607 |
+
"paired_records": [
|
| 608 |
+
{
|
| 609 |
+
"seed": 1,
|
| 610 |
+
"decay_loss": 4.062299974262714,
|
| 611 |
+
"best_static_condition": "static_dropout_0.1",
|
| 612 |
+
"best_static_loss": 4.080718021839857,
|
| 613 |
+
"delta": -0.018418047577142715,
|
| 614 |
+
"gain": 0.018418047577142715
|
| 615 |
+
},
|
| 616 |
+
{
|
| 617 |
+
"seed": 2,
|
| 618 |
+
"decay_loss": 4.112260434776545,
|
| 619 |
+
"best_static_condition": "static_dropout_0.06",
|
| 620 |
+
"best_static_loss": 4.130373623222113,
|
| 621 |
+
"delta": -0.018113188445568085,
|
| 622 |
+
"gain": 0.018113188445568085
|
| 623 |
+
},
|
| 624 |
+
{
|
| 625 |
+
"seed": 3,
|
| 626 |
+
"decay_loss": 4.0763493329286575,
|
| 627 |
+
"best_static_condition": "static_dropout_0.08",
|
| 628 |
+
"best_static_loss": 4.1035647466778755,
|
| 629 |
+
"delta": -0.027215413749217987,
|
| 630 |
+
"gain": 0.027215413749217987
|
| 631 |
+
},
|
| 632 |
+
{
|
| 633 |
+
"seed": 4,
|
| 634 |
+
"decay_loss": 4.0844879895448685,
|
| 635 |
+
"best_static_condition": "static_dropout_0.1",
|
| 636 |
+
"best_static_loss": 4.109558492898941,
|
| 637 |
+
"delta": -0.02507050335407257,
|
| 638 |
+
"gain": 0.02507050335407257
|
| 639 |
+
},
|
| 640 |
+
{
|
| 641 |
+
"seed": 5,
|
| 642 |
+
"decay_loss": 4.068591594696045,
|
| 643 |
+
"best_static_condition": "static_dropout_0.08",
|
| 644 |
+
"best_static_loss": 4.105628222227097,
|
| 645 |
+
"delta": -0.037036627531051636,
|
| 646 |
+
"gain": 0.037036627531051636
|
| 647 |
+
}
|
| 648 |
+
],
|
| 649 |
"paired_wins": 5,
|
| 650 |
"paired_mean_delta": -0.0251707561314106,
|
| 651 |
"paired_std_delta": 0.007752385341386418,
|
| 652 |
+
"paired_gain_mean": 0.0251707561314106,
|
| 653 |
+
"paired_gain_std": 0.007752385341386418,
|
| 654 |
+
"paired_gain_ci_low": 0.019626595079898834,
|
| 655 |
+
"paired_gain_ci_high": 0.03128769695758819,
|
| 656 |
+
"budget": {
|
| 657 |
+
"steps_per_stage": [
|
| 658 |
+
1000
|
| 659 |
+
],
|
| 660 |
+
"batch_sizes": [
|
| 661 |
+
16
|
| 662 |
+
],
|
| 663 |
+
"block_size": 128,
|
| 664 |
+
"sampled_per_stage": [
|
| 665 |
+
2048000
|
| 666 |
+
],
|
| 667 |
+
"final_sampled_tokens": 10240000,
|
| 668 |
+
"prefix_path": [
|
| 669 |
+
250000,
|
| 670 |
+
500000,
|
| 671 |
+
1000000,
|
| 672 |
+
2000000,
|
| 673 |
+
4000000
|
| 674 |
+
],
|
| 675 |
+
"stage_count": 5
|
| 676 |
+
},
|
| 677 |
"stage_deltas": [
|
| 678 |
{
|
| 679 |
"stage": 0,
|
|
|
|
| 747 |
-0.00015844032168388367,
|
| 748 |
-0.027258697897195816
|
| 749 |
],
|
| 750 |
+
"paired_records": [
|
| 751 |
+
{
|
| 752 |
+
"seed": 1,
|
| 753 |
+
"decay_loss": 3.952172212302685,
|
| 754 |
+
"best_static_condition": "static_dropout_0.18",
|
| 755 |
+
"best_static_loss": 3.968690302222967,
|
| 756 |
+
"delta": -0.016518089920282364,
|
| 757 |
+
"gain": 0.016518089920282364
|
| 758 |
+
},
|
| 759 |
+
{
|
| 760 |
+
"seed": 2,
|
| 761 |
+
"decay_loss": 3.967039406299591,
|
| 762 |
+
"best_static_condition": "static_dropout_0.14",
|
| 763 |
+
"best_static_loss": 3.967197846621275,
|
| 764 |
+
"delta": -0.00015844032168388367,
|
| 765 |
+
"gain": 0.00015844032168388367
|
| 766 |
+
},
|
| 767 |
+
{
|
| 768 |
+
"seed": 3,
|
| 769 |
+
"decay_loss": 3.9525104351341724,
|
| 770 |
+
"best_static_condition": "static_dropout_0.1",
|
| 771 |
+
"best_static_loss": 3.9797691330313683,
|
| 772 |
+
"delta": -0.027258697897195816,
|
| 773 |
+
"gain": 0.027258697897195816
|
| 774 |
+
}
|
| 775 |
+
],
|
| 776 |
"paired_wins": 3,
|
| 777 |
"paired_mean_delta": -0.014645076046387354,
|
| 778 |
"paired_std_delta": 0.013646872385042126,
|
| 779 |
+
"paired_gain_mean": 0.014645076046387354,
|
| 780 |
+
"paired_gain_std": 0.013646872385042126,
|
| 781 |
+
"paired_gain_ci_low": 0.00015844032168388367,
|
| 782 |
+
"paired_gain_ci_high": 0.027258697897195816,
|
| 783 |
+
"budget": {
|
| 784 |
+
"steps_per_stage": [
|
| 785 |
+
1000
|
| 786 |
+
],
|
| 787 |
+
"batch_sizes": [
|
| 788 |
+
16
|
| 789 |
+
],
|
| 790 |
+
"block_size": 128,
|
| 791 |
+
"sampled_per_stage": [
|
| 792 |
+
2048000
|
| 793 |
+
],
|
| 794 |
+
"final_sampled_tokens": 12288000,
|
| 795 |
+
"prefix_path": [
|
| 796 |
+
250000,
|
| 797 |
+
500000,
|
| 798 |
+
1000000,
|
| 799 |
+
2000000,
|
| 800 |
+
4000000,
|
| 801 |
+
8000000
|
| 802 |
+
],
|
| 803 |
+
"stage_count": 6
|
| 804 |
+
},
|
| 805 |
"stage_deltas": [
|
| 806 |
{
|
| 807 |
"stage": 0,
|
paper/tables/calibration_weight_table.tex
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{lll}
|
| 2 |
+
\toprule
|
| 3 |
+
Cell property & Weight multiplier & Reason \\
|
| 4 |
+
\midrule
|
| 5 |
+
Best grid point on dropout boundary & $0.30$ & Optimum may lie outside tested grid \\
|
| 6 |
+
Quadratic minimum not bracketed & $0.50$ & Local parabola is less reliable \\
|
| 7 |
+
Loss span below $0.02$ nats & $0.50$ & Very flat curve weakly identifies $p^\star$ \\
|
| 8 |
+
Best-loss std. $\sigma > 0$ & $1/(1+20\sigma)$ & Noisier minima receive less influence \\
|
| 9 |
+
\bottomrule
|
| 10 |
+
\end{tabular}
|
paper/tables/coefficient_table.tex
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
\begin{tabular}{lrrrrrrrr}
|
| 2 |
\toprule
|
| 3 |
-
Regime & Cells & A & B & D & C0 & MAE & L-model MAE & L-prefix MAE \\
|
| 4 |
\midrule
|
| 5 |
OpenWebText10K & 15 & 0.0819 & -0.0239 & 0.1537 & -0.0556 & 0.0158 & 0.0248 & 0.0310 \\
|
| 6 |
TinyStories & 16 & -0.0893 & -0.1298 & 0.2551 & 0.0815 & 0.0180 & 0.0295 & 0.0325 \\
|
|
|
|
| 1 |
\begin{tabular}{lrrrrrrrr}
|
| 2 |
\toprule
|
| 3 |
+
Regime & Cells & A & B & D & C0 & Dropout MAE (abs. $p$) & L-model MAE & L-prefix MAE \\
|
| 4 |
\midrule
|
| 5 |
OpenWebText10K & 15 & 0.0819 & -0.0239 & 0.1537 & -0.0556 & 0.0158 & 0.0248 & 0.0310 \\
|
| 6 |
TinyStories & 16 & -0.0893 & -0.1298 & 0.2551 & 0.0815 & 0.0180 & 0.0295 & 0.0325 \\
|
paper/tables/evidence_ladder_table.tex
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{lrrrrr}
|
| 2 |
+
\toprule
|
| 3 |
+
Regime & Calib. dropout MAE & 4M gain (nats) & 4M wins & 8M gain (nats) & 8M wins \\
|
| 4 |
+
\midrule
|
| 5 |
+
OpenWebText10K & 0.0158 & 0.0473 & 5/5 & 0.0363 & 3/3 \\
|
| 6 |
+
TinyStories & 0.0180 & 0.0133 & 5/5 & 0.0100 & 3/3 \\
|
| 7 |
+
WikiText-103 & 0.0162 & 0.0297 & 5/5 & 0.0184 & 3/3 \\
|
| 8 |
+
\bottomrule
|
| 9 |
+
\end{tabular}
|
paper/tables/experiment_protocol_table.tex
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llll}
|
| 2 |
+
\toprule
|
| 3 |
+
Experiment layer & What is run & Question answered & Statistical unit \\
|
| 4 |
+
\midrule
|
| 5 |
+
Static calibration & Per-regime dropout grid at fixed $(P,U,C)$ cells & Where does validation loss plateau over dropout? & 15--16 cells per regime \\
|
| 6 |
+
Coefficient fit & Per-regime regression from cell targets $p^\star$ & Can pressure variables predict useful dropout? & MAE / leave-out MAE \\
|
| 7 |
+
4M final-prefix locked stream & Per-regime continuing model over growing prefixes & Does decay beat the best tested fixed dropout? & 5 paired seeds per regime \\
|
| 8 |
+
L20 8M extrapolation & Per-regime 51.84M-param model with frozen coefficients & Does the law extend to larger model/data scale? & 3 paired seeds per regime \\
|
| 9 |
+
Stage-wise audit & Per-regime decay vs best static at every prefix & Is the schedule final-loss or per-prefix optimal? & Prefix-level deltas \\
|
| 10 |
+
\bottomrule
|
| 11 |
+
\end{tabular}
|
paper/tables/l20_schedule_path_table.tex
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llll}
|
| 2 |
+
\toprule
|
| 3 |
+
Regime & Locked-stream prefix path & Frozen decay path & Final best static \\
|
| 4 |
+
\midrule
|
| 5 |
+
OpenWebText10K & 250k $\rightarrow$ 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M $\rightarrow$ 8M & 0.433 $\rightarrow$ 0.367 $\rightarrow$ 0.270 $\rightarrow$ 0.176 $\rightarrow$ 0.095 $\rightarrow$ 0.033 & p=0.2 \\
|
| 6 |
+
TinyStories & 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M $\rightarrow$ 8M & 0.253 $\rightarrow$ 0.209 $\rightarrow$ 0.137 $\rightarrow$ 0.077 $\rightarrow$ 0.041 & p=0.2 \\
|
| 7 |
+
WikiText-103 & 250k $\rightarrow$ 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M $\rightarrow$ 8M & 0.284 $\rightarrow$ 0.211 $\rightarrow$ 0.116 $\rightarrow$ 0.036 $\rightarrow$ 0.020 $\rightarrow$ 0.020 & p=0.14 \\
|
| 8 |
+
\bottomrule
|
| 9 |
+
\end{tabular}
|
paper/tables/l20_stage_table.tex
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
\begin{tabular}{lrrrrr}
|
| 2 |
\toprule
|
| 3 |
-
Regime & Prefix & Decay dropout & Decay val & Best static val & Delta \\
|
| 4 |
\midrule
|
| 5 |
OpenWebText10K & 250k & 0.433 & 5.4601 & 5.3971 & +0.0630 \\
|
| 6 |
OpenWebText10K & 500k & 0.367 & 5.0179 & 5.0169 & +0.0010 \\
|
|
|
|
| 1 |
\begin{tabular}{lrrrrr}
|
| 2 |
\toprule
|
| 3 |
+
Regime & Prefix & Decay dropout & Decay val (nats) & Best static val (nats) & Delta (nats) \\
|
| 4 |
\midrule
|
| 5 |
OpenWebText10K & 250k & 0.433 & 5.4601 & 5.3971 & +0.0630 \\
|
| 6 |
OpenWebText10K & 500k & 0.367 & 5.0179 & 5.0169 & +0.0010 \\
|
paper/tables/paired_gain_ci_table.tex
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llrrrr}
|
| 2 |
+
\toprule
|
| 3 |
+
Regime & Protocol & Paired gain mean & 95\% bootstrap CI & Seeds & Wins \\
|
| 4 |
+
\midrule
|
| 5 |
+
OpenWebText10K & 4M final prefix / 5 seeds & 0.0473 & [0.0383, 0.0553] & 5 & 5/5 \\
|
| 6 |
+
OpenWebText10K & 8M final prefix / 3 seeds & 0.0340 & [0.0255, 0.0394] & 3 & 3/3 \\
|
| 7 |
+
TinyStories & 4M final prefix / 5 seeds & 0.0123 & [0.0059, 0.0179] & 5 & 5/5 \\
|
| 8 |
+
TinyStories & 8M final prefix / 3 seeds & 0.0093 & [0.0061, 0.0130] & 3 & 3/3 \\
|
| 9 |
+
WikiText-103 & 4M final prefix / 5 seeds & 0.0252 & [0.0196, 0.0313] & 5 & 5/5 \\
|
| 10 |
+
WikiText-103 & 8M final prefix / 3 seeds & 0.0146 & [0.0002, 0.0273] & 3 & 3/3 \\
|
| 11 |
+
\bottomrule
|
| 12 |
+
\end{tabular}
|
paper/tables/protocol_budget_table.tex
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llllrr}
|
| 2 |
+
\toprule
|
| 3 |
+
Regime & Protocol & Prefix path & Sampled/stage & Batch & Block \\
|
| 4 |
+
\midrule
|
| 5 |
+
OpenWebText10K & 4M final prefix / 5 seeds & 250k $\rightarrow$ 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M & 2.048M & 16 & 128 \\
|
| 6 |
+
OpenWebText10K & 8M final prefix / 3 seeds & 250k $\rightarrow$ 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M $\rightarrow$ 8M & 2.048M & 16 & 128 \\
|
| 7 |
+
TinyStories & 4M final prefix / 5 seeds & 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M & 4.096M & 16 & 128 \\
|
| 8 |
+
TinyStories & 8M final prefix / 3 seeds & 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M $\rightarrow$ 8M & 4.096M & 16 & 128 \\
|
| 9 |
+
WikiText-103 & 4M final prefix / 5 seeds & 250k $\rightarrow$ 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M & 2.048M & 16 & 128 \\
|
| 10 |
+
WikiText-103 & 8M final prefix / 3 seeds & 250k $\rightarrow$ 500k $\rightarrow$ 1M $\rightarrow$ 2M $\rightarrow$ 4M $\rightarrow$ 8M & 2.048M & 16 & 128 \\
|
| 11 |
+
\bottomrule
|
| 12 |
+
\end{tabular}
|
paper/tables/regime_setup_table.tex
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llll}
|
| 2 |
+
\toprule
|
| 3 |
+
Regime & Corpus source & Tokenizer / vocab & Streaming prefixes \\
|
| 4 |
+
\midrule
|
| 5 |
+
OpenWebText10K & Cached OpenWebText-style subset & BPE / 4096 & 250k, 500k, 1M, 2M, 4M; plus 8M L20 tier \\
|
| 6 |
+
TinyStories & Cached TinyStories subset & BPE / 4096 & 500k, 1M, 2M, 4M; plus 8M L20 tier \\
|
| 7 |
+
WikiText-103 & Cached WikiText-103 subset & BPE / 4096 & 250k, 500k, 1M, 2M, 4M; plus 8M L20 tier \\
|
| 8 |
+
\bottomrule
|
| 9 |
+
\end{tabular}
|
paper/tables/reproducibility_table.tex
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{ll}
|
| 2 |
+
\toprule
|
| 3 |
+
Item & Value \\
|
| 4 |
+
\midrule
|
| 5 |
+
Repository & \url{https://huggingface.co/cuber12/dropout-decay} \\
|
| 6 |
+
Repository snapshot & Base commit \texttt{e7a7275}; cite final release tag with paper \\
|
| 7 |
+
License & MIT-derived source with nanochat attribution retained \\
|
| 8 |
+
Python & 3.11.15 \\
|
| 9 |
+
PyTorch & 2.12.0 \\
|
| 10 |
+
Operating system & macOS 26.4 arm64 \\
|
| 11 |
+
Training backend & Apple Metal Performance Shaders (MPS); runner refuses CPU/CUDA \\
|
| 12 |
+
\bottomrule
|
| 13 |
+
\end{tabular}
|
paper/tables/streaming_validation_table.tex
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
\begin{tabular}{llrrrrr}
|
| 2 |
\toprule
|
| 3 |
-
Regime & Protocol & Decay final & Best static final & Gain & Seeds & Paired wins \\
|
| 4 |
\midrule
|
| 5 |
-
OpenWebText10K & 4M / 5 seeds & 4.3981 $\pm$ 0.0095 & 4.4455 $\pm$ 0.0120 & 0.0473 & 5 & 5/5 \\
|
| 6 |
OpenWebText10K & 8M / 3 seeds & 4.1793 $\pm$ 0.0134 & 4.2156 $\pm$ 0.0142 & 0.0363 & 3 & 3/3 \\
|
| 7 |
-
TinyStories & 4M / 5 seeds & 2.5311 $\pm$ 0.0213 & 2.5444 $\pm$ 0.0211 & 0.0133 & 5 & 5/5 \\
|
| 8 |
TinyStories & 8M / 3 seeds & 2.2086 $\pm$ 0.0046 & 2.2186 $\pm$ 0.0032 & 0.0100 & 3 & 3/3 \\
|
| 9 |
-
WikiText-103 & 4M / 5 seeds & 4.0808 $\pm$ 0.0195 & 4.1105 $\pm$ 0.0188 & 0.0297 & 5 & 5/5 \\
|
| 10 |
WikiText-103 & 8M / 3 seeds & 3.9572 $\pm$ 0.0085 & 3.9756 $\pm$ 0.0087 & 0.0184 & 3 & 3/3 \\
|
| 11 |
\bottomrule
|
| 12 |
\end{tabular}
|
|
|
|
| 1 |
\begin{tabular}{llrrrrr}
|
| 2 |
\toprule
|
| 3 |
+
Regime & Protocol & Decay final (nats) & Best static final (nats) & Gain (nats) & Seeds & Paired wins \\
|
| 4 |
\midrule
|
| 5 |
+
OpenWebText10K & 4M final prefix / 5 seeds & 4.3981 $\pm$ 0.0095 & 4.4455 $\pm$ 0.0120 & 0.0473 & 5 & 5/5 \\
|
| 6 |
OpenWebText10K & 8M / 3 seeds & 4.1793 $\pm$ 0.0134 & 4.2156 $\pm$ 0.0142 & 0.0363 & 3 & 3/3 \\
|
| 7 |
+
TinyStories & 4M final prefix / 5 seeds & 2.5311 $\pm$ 0.0213 & 2.5444 $\pm$ 0.0211 & 0.0133 & 5 & 5/5 \\
|
| 8 |
TinyStories & 8M / 3 seeds & 2.2086 $\pm$ 0.0046 & 2.2186 $\pm$ 0.0032 & 0.0100 & 3 & 3/3 \\
|
| 9 |
+
WikiText-103 & 4M final prefix / 5 seeds & 4.0808 $\pm$ 0.0195 & 4.1105 $\pm$ 0.0188 & 0.0297 & 5 & 5/5 \\
|
| 10 |
WikiText-103 & 8M / 3 seeds & 3.9572 $\pm$ 0.0085 & 3.9756 $\pm$ 0.0087 & 0.0184 & 3 & 3/3 \\
|
| 11 |
\bottomrule
|
| 12 |
\end{tabular}
|
paper/tables/symbol_table.tex
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{ll}
|
| 2 |
+
\toprule
|
| 3 |
+
Symbol & Meaning \\
|
| 4 |
+
\midrule
|
| 5 |
+
$P$ & Trainable parameter count \\
|
| 6 |
+
$U_t$ & Unique-token prefix currently revealed by stream stage $t$ \\
|
| 7 |
+
$C_t$ & Cumulative sampled training tokens consumed by the optimizer \\
|
| 8 |
+
$x_t$ & $\log_{10}(P/U_t)$, capacity pressure \\
|
| 9 |
+
$y_t$ & $\log_{10}(C_t/U_t)$, repeated-sampling pressure \\
|
| 10 |
+
$p_t$ & Dropout rate used at stream stage $t$ \\
|
| 11 |
+
$p^\star$ & Static-sweep target dropout for one calibration cell \\
|
| 12 |
+
$A,B,D,C_0$ & Regime-specific fitted pressure-law coefficients \\
|
| 13 |
+
$p_{\min},p_{\max}$ & Clamp bounds applied to generated dropout schedules \\
|
| 14 |
+
\bottomrule
|
| 15 |
+
\end{tabular}
|
pyproject.toml
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
[project]
|
| 2 |
name = "dropout-decay"
|
| 3 |
version = "0.1.0"
|
|
@@ -11,6 +15,14 @@ dependencies = [
|
|
| 11 |
"torch>=2.3",
|
| 12 |
]
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
[tool.pytest.ini_options]
|
| 15 |
pythonpath = ["src"]
|
| 16 |
testpaths = ["tests"]
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[build-system]
|
| 2 |
+
requires = ["setuptools>=69", "wheel"]
|
| 3 |
+
build-backend = "setuptools.build_meta"
|
| 4 |
+
|
| 5 |
[project]
|
| 6 |
name = "dropout-decay"
|
| 7 |
version = "0.1.0"
|
|
|
|
| 15 |
"torch>=2.3",
|
| 16 |
]
|
| 17 |
|
| 18 |
+
[project.optional-dependencies]
|
| 19 |
+
dev = [
|
| 20 |
+
"pytest>=8",
|
| 21 |
+
]
|
| 22 |
+
|
| 23 |
[tool.pytest.ini_options]
|
| 24 |
pythonpath = ["src"]
|
| 25 |
testpaths = ["tests"]
|
| 26 |
+
|
| 27 |
+
[tool.setuptools.packages.find]
|
| 28 |
+
where = ["src"]
|
scripts/generate_paper_assets.py
CHANGED
|
@@ -23,6 +23,7 @@ import csv
|
|
| 23 |
import json
|
| 24 |
import math
|
| 25 |
from pathlib import Path
|
|
|
|
| 26 |
import statistics
|
| 27 |
|
| 28 |
|
|
@@ -48,7 +49,7 @@ REGIMES = {
|
|
| 48 |
/ "runs/openwebtext10k_l16_updated_formula_clean_5seed/locked_stream/20260530-174525",
|
| 49 |
"small_condition": "openwebtext10k_interaction",
|
| 50 |
"small_model": "L16_H8_D384",
|
| 51 |
-
"small_protocol": "4M / 5 seeds",
|
| 52 |
"l20_stream": ROOT
|
| 53 |
/ "runs/openwebtext10k_l20_8m_extrapolation_3seed/locked_stream/20260601-191150",
|
| 54 |
"l20_condition": "openwebtext10k_l20_interaction_8m",
|
|
@@ -75,7 +76,7 @@ REGIMES = {
|
|
| 75 |
],
|
| 76 |
"small_condition": "interaction",
|
| 77 |
"small_model": "L12_H8_D320",
|
| 78 |
-
"small_protocol": "4M / 5 seeds",
|
| 79 |
"l20_stream": ROOT
|
| 80 |
/ "runs/tinystories_l20_8m_extrapolation_3seed/locked_stream/20260602-112249",
|
| 81 |
"l20_condition": "tinystories_l20_interaction_8m",
|
|
@@ -94,7 +95,7 @@ REGIMES = {
|
|
| 94 |
/ "runs/wikitext103_l12_streaming_validation_5seed/locked_stream/20260531-093525",
|
| 95 |
"small_condition": "wikitext103_formula_l12",
|
| 96 |
"small_model": "L12_H8_D320",
|
| 97 |
-
"small_protocol": "4M / 5 seeds",
|
| 98 |
"l20_stream": ROOT
|
| 99 |
/ "runs/wikitext103_l20_8m_extrapolation_3seed/locked_stream/20260603-231952",
|
| 100 |
"l20_condition": "wikitext103_l20_interaction_8m",
|
|
@@ -127,6 +128,27 @@ def mean_std(values: list[float]) -> tuple[float, float]:
|
|
| 127 |
return mean, std
|
| 128 |
|
| 129 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
def fmt(x: float, digits: int = 4) -> str:
|
| 131 |
return f"{x:.{digits}f}"
|
| 132 |
|
|
@@ -142,6 +164,10 @@ def tex_escape(value: object) -> str:
|
|
| 142 |
)
|
| 143 |
|
| 144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
def token_label(value: int) -> str:
|
| 146 |
if value >= 1_000_000:
|
| 147 |
whole = value / 1_000_000
|
|
@@ -149,6 +175,39 @@ def token_label(value: int) -> str:
|
|
| 149 |
return f"{value // 1000}k"
|
| 150 |
|
| 151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
def metric_stage_summary(run_dir: Path | list[Path], condition_name: str) -> dict:
|
| 153 |
run_dirs = run_dir if isinstance(run_dir, list) else [run_dir]
|
| 154 |
rows = []
|
|
@@ -163,6 +222,12 @@ def metric_stage_summary(run_dir: Path | list[Path], condition_name: str) -> dic
|
|
| 163 |
key = (row["condition"], int(row["stage"]))
|
| 164 |
by_condition_stage.setdefault(key, []).append(row)
|
| 165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
condition_rows = by_condition_stage[(condition_name, final_stage)]
|
| 167 |
final_vals = [float(row["val_eval_loss"]) for row in condition_rows]
|
| 168 |
condition_final_mean, condition_final_std = mean_std(final_vals)
|
|
@@ -192,10 +257,27 @@ def metric_stage_summary(run_dir: Path | list[Path], condition_name: str) -> dic
|
|
| 192 |
final_static_by_seed[seed] = (row["condition"], value)
|
| 193 |
|
| 194 |
paired_deltas = []
|
| 195 |
-
|
|
|
|
| 196 |
seed = int(row["seed"])
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
paired_mean, paired_std = mean_std(paired_deltas)
|
|
|
|
|
|
|
|
|
|
| 199 |
|
| 200 |
stage_deltas = []
|
| 201 |
for stage in stages:
|
|
@@ -251,9 +333,15 @@ def metric_stage_summary(run_dir: Path | list[Path], condition_name: str) -> dic
|
|
| 251 |
"best_static_std": best_static_std,
|
| 252 |
"improvement": best_static_mean - condition_final_mean,
|
| 253 |
"paired_deltas": paired_deltas,
|
|
|
|
| 254 |
"paired_wins": sum(1 for delta in paired_deltas if delta < 0),
|
| 255 |
"paired_mean_delta": paired_mean,
|
| 256 |
"paired_std_delta": paired_std,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
"stage_deltas": stage_deltas,
|
| 258 |
}
|
| 259 |
|
|
@@ -318,21 +406,29 @@ def tikz_coordinates(points: list[tuple[float, float]], digits: int = 4) -> str:
|
|
| 318 |
|
| 319 |
def write_calibration_curve_figure() -> None:
|
| 320 |
axes = []
|
| 321 |
-
for key, paths in REGIMES.items():
|
| 322 |
raw_curve = static_curve_points(
|
| 323 |
paths["curve_run"], paths["curve_model"], paths["curve_prefix"]
|
| 324 |
)
|
| 325 |
minimum = min(loss for _, loss in raw_curve)
|
| 326 |
points = [(dropout, loss - minimum) for dropout, loss in raw_curve]
|
| 327 |
best = min(raw_curve, key=lambda item: item[1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
axes.append(
|
| 329 |
rf"""
|
| 330 |
\nextgroupplot[
|
| 331 |
-
|
| 332 |
-
xlabel={{Dropout}},
|
| 333 |
-
ylabel={{Validation loss above best}},
|
| 334 |
-
ymin=0,
|
| 335 |
-
grid=both,
|
| 336 |
]
|
| 337 |
\addplot+[thick, mark=*] coordinates {{{tikz_coordinates(points, digits=5)}}};
|
| 338 |
\addlegendentry{{static sweep}}
|
|
@@ -374,7 +470,7 @@ def write_static_optima_figure() -> None:
|
|
| 374 |
"\\addplot+[thick, mark=*] coordinates {"
|
| 375 |
+ tikz_coordinates(coords)
|
| 376 |
+ "};\n"
|
| 377 |
-
+ f"\\addlegendentry{{{
|
| 378 |
)
|
| 379 |
xticks = ",".join(str(i) for i in range(len(labels)))
|
| 380 |
xticklabels = ",".join(token_label(prefix) for prefix in labels)
|
|
@@ -486,11 +582,186 @@ def write_final_improvement_figure(summaries: dict[str, dict]) -> None:
|
|
| 486 |
(FIG_DIR / "final_improvements.tex").write_text(content, encoding="utf-8")
|
| 487 |
|
| 488 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 489 |
def write_tables(summaries: dict[str, dict], coeffs: dict[str, dict]) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 490 |
coeff_lines = [
|
| 491 |
"\\begin{tabular}{lrrrrrrrr}",
|
| 492 |
"\\toprule",
|
| 493 |
-
"Regime & Cells & A & B & D & C0 & MAE & L-model MAE & L-prefix MAE \\\\",
|
| 494 |
"\\midrule",
|
| 495 |
]
|
| 496 |
for key in REGIMES:
|
|
@@ -505,10 +776,29 @@ def write_tables(summaries: dict[str, dict], coeffs: dict[str, dict]) -> None:
|
|
| 505 |
"\n".join(coeff_lines) + "\n", encoding="utf-8"
|
| 506 |
)
|
| 507 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
val_lines = [
|
| 509 |
"\\begin{tabular}{llrrrrr}",
|
| 510 |
"\\toprule",
|
| 511 |
-
"Regime & Protocol & Decay final & Best static final & Gain & Seeds & Paired wins \\\\",
|
| 512 |
"\\midrule",
|
| 513 |
]
|
| 514 |
for key, paths in REGIMES.items():
|
|
@@ -525,10 +815,57 @@ def write_tables(summaries: dict[str, dict], coeffs: dict[str, dict]) -> None:
|
|
| 525 |
"\n".join(val_lines) + "\n", encoding="utf-8"
|
| 526 |
)
|
| 527 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 528 |
l20_lines = [
|
| 529 |
"\\begin{tabular}{lrrrrr}",
|
| 530 |
"\\toprule",
|
| 531 |
-
"Regime & Prefix & Decay dropout & Decay val & Best static val & Delta \\\\",
|
| 532 |
"\\midrule",
|
| 533 |
]
|
| 534 |
for key, paths in REGIMES.items():
|
|
@@ -569,6 +906,7 @@ def main() -> None:
|
|
| 569 |
}
|
| 570 |
write_calibration_curve_figure()
|
| 571 |
write_static_optima_figure()
|
|
|
|
| 572 |
write_l20_stage_delta_figure(summaries)
|
| 573 |
write_final_improvement_figure(summaries)
|
| 574 |
write_tables(summaries, coeffs)
|
|
|
|
| 23 |
import json
|
| 24 |
import math
|
| 25 |
from pathlib import Path
|
| 26 |
+
import random
|
| 27 |
import statistics
|
| 28 |
|
| 29 |
|
|
|
|
| 49 |
/ "runs/openwebtext10k_l16_updated_formula_clean_5seed/locked_stream/20260530-174525",
|
| 50 |
"small_condition": "openwebtext10k_interaction",
|
| 51 |
"small_model": "L16_H8_D384",
|
| 52 |
+
"small_protocol": "4M final prefix / 5 seeds",
|
| 53 |
"l20_stream": ROOT
|
| 54 |
/ "runs/openwebtext10k_l20_8m_extrapolation_3seed/locked_stream/20260601-191150",
|
| 55 |
"l20_condition": "openwebtext10k_l20_interaction_8m",
|
|
|
|
| 76 |
],
|
| 77 |
"small_condition": "interaction",
|
| 78 |
"small_model": "L12_H8_D320",
|
| 79 |
+
"small_protocol": "4M final prefix / 5 seeds",
|
| 80 |
"l20_stream": ROOT
|
| 81 |
/ "runs/tinystories_l20_8m_extrapolation_3seed/locked_stream/20260602-112249",
|
| 82 |
"l20_condition": "tinystories_l20_interaction_8m",
|
|
|
|
| 95 |
/ "runs/wikitext103_l12_streaming_validation_5seed/locked_stream/20260531-093525",
|
| 96 |
"small_condition": "wikitext103_formula_l12",
|
| 97 |
"small_model": "L12_H8_D320",
|
| 98 |
+
"small_protocol": "4M final prefix / 5 seeds",
|
| 99 |
"l20_stream": ROOT
|
| 100 |
/ "runs/wikitext103_l20_8m_extrapolation_3seed/locked_stream/20260603-231952",
|
| 101 |
"l20_condition": "wikitext103_l20_interaction_8m",
|
|
|
|
| 128 |
return mean, std
|
| 129 |
|
| 130 |
|
| 131 |
+
def bootstrap_ci(
|
| 132 |
+
values: list[float], *, confidence: float = 0.95, iterations: int = 20_000, seed: int = 1337
|
| 133 |
+
) -> tuple[float, float]:
|
| 134 |
+
if not values:
|
| 135 |
+
return float("nan"), float("nan")
|
| 136 |
+
if len(values) == 1:
|
| 137 |
+
return values[0], values[0]
|
| 138 |
+
rng = random.Random(seed)
|
| 139 |
+
n = len(values)
|
| 140 |
+
means = []
|
| 141 |
+
for _ in range(iterations):
|
| 142 |
+
sample = [values[rng.randrange(n)] for _ in range(n)]
|
| 143 |
+
means.append(statistics.fmean(sample))
|
| 144 |
+
means.sort()
|
| 145 |
+
lower_q = (1.0 - confidence) / 2.0
|
| 146 |
+
upper_q = 1.0 - lower_q
|
| 147 |
+
lower_idx = min(iterations - 1, max(0, int(lower_q * iterations)))
|
| 148 |
+
upper_idx = min(iterations - 1, max(0, int(upper_q * iterations)))
|
| 149 |
+
return means[lower_idx], means[upper_idx]
|
| 150 |
+
|
| 151 |
+
|
| 152 |
def fmt(x: float, digits: int = 4) -> str:
|
| 153 |
return f"{x:.{digits}f}"
|
| 154 |
|
|
|
|
| 164 |
)
|
| 165 |
|
| 166 |
|
| 167 |
+
def model_label(model_name: str) -> str:
|
| 168 |
+
return tex_escape(model_name.replace("_", "-"))
|
| 169 |
+
|
| 170 |
+
|
| 171 |
def token_label(value: int) -> str:
|
| 172 |
if value >= 1_000_000:
|
| 173 |
whole = value / 1_000_000
|
|
|
|
| 175 |
return f"{value // 1000}k"
|
| 176 |
|
| 177 |
|
| 178 |
+
def protocol_budget(condition_rows: list[dict], stages: list[int]) -> dict:
|
| 179 |
+
rows_by_seed: dict[int, list[dict]] = {}
|
| 180 |
+
for row in condition_rows:
|
| 181 |
+
rows_by_seed.setdefault(int(row["seed"]), []).append(row)
|
| 182 |
+
seed = sorted(rows_by_seed)[0]
|
| 183 |
+
seed_rows = sorted(rows_by_seed[seed], key=lambda item: int(item["stage"]))
|
| 184 |
+
sampled_deltas = []
|
| 185 |
+
previous_tokens_seen = 0
|
| 186 |
+
for row in seed_rows:
|
| 187 |
+
tokens_seen = int(row["tokens_seen"])
|
| 188 |
+
sampled_deltas.append(tokens_seen - previous_tokens_seen)
|
| 189 |
+
previous_tokens_seen = tokens_seen
|
| 190 |
+
first = seed_rows[0]
|
| 191 |
+
steps_per_stage = sorted({int(row["steps"]) for row in seed_rows})
|
| 192 |
+
block_size = int(first["model_config"]["block_size"])
|
| 193 |
+
sampled_per_stage = sorted(set(sampled_deltas))
|
| 194 |
+
batch_sizes = sorted(
|
| 195 |
+
{
|
| 196 |
+
round(delta / (int(row["steps"]) * block_size))
|
| 197 |
+
for delta, row in zip(sampled_deltas, seed_rows, strict=True)
|
| 198 |
+
}
|
| 199 |
+
)
|
| 200 |
+
return {
|
| 201 |
+
"steps_per_stage": steps_per_stage,
|
| 202 |
+
"batch_sizes": batch_sizes,
|
| 203 |
+
"block_size": block_size,
|
| 204 |
+
"sampled_per_stage": sampled_per_stage,
|
| 205 |
+
"final_sampled_tokens": int(seed_rows[-1]["tokens_seen"]),
|
| 206 |
+
"prefix_path": [int(row["token_limit"]) for row in seed_rows],
|
| 207 |
+
"stage_count": len(stages),
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
|
| 211 |
def metric_stage_summary(run_dir: Path | list[Path], condition_name: str) -> dict:
|
| 212 |
run_dirs = run_dir if isinstance(run_dir, list) else [run_dir]
|
| 213 |
rows = []
|
|
|
|
| 222 |
key = (row["condition"], int(row["stage"]))
|
| 223 |
by_condition_stage.setdefault(key, []).append(row)
|
| 224 |
|
| 225 |
+
condition_rows_by_stage = [
|
| 226 |
+
row
|
| 227 |
+
for (condition, _stage), group in by_condition_stage.items()
|
| 228 |
+
if condition == condition_name
|
| 229 |
+
for row in group
|
| 230 |
+
]
|
| 231 |
condition_rows = by_condition_stage[(condition_name, final_stage)]
|
| 232 |
final_vals = [float(row["val_eval_loss"]) for row in condition_rows]
|
| 233 |
condition_final_mean, condition_final_std = mean_std(final_vals)
|
|
|
|
| 257 |
final_static_by_seed[seed] = (row["condition"], value)
|
| 258 |
|
| 259 |
paired_deltas = []
|
| 260 |
+
paired_records = []
|
| 261 |
+
for row in sorted(condition_rows, key=lambda item: int(item["seed"])):
|
| 262 |
seed = int(row["seed"])
|
| 263 |
+
decay_loss = float(row["val_eval_loss"])
|
| 264 |
+
static_condition, static_loss = final_static_by_seed[seed]
|
| 265 |
+
delta = decay_loss - static_loss
|
| 266 |
+
paired_deltas.append(delta)
|
| 267 |
+
paired_records.append(
|
| 268 |
+
{
|
| 269 |
+
"seed": seed,
|
| 270 |
+
"decay_loss": decay_loss,
|
| 271 |
+
"best_static_condition": static_condition,
|
| 272 |
+
"best_static_loss": static_loss,
|
| 273 |
+
"delta": delta,
|
| 274 |
+
"gain": -delta,
|
| 275 |
+
}
|
| 276 |
+
)
|
| 277 |
paired_mean, paired_std = mean_std(paired_deltas)
|
| 278 |
+
paired_gains = [-delta for delta in paired_deltas]
|
| 279 |
+
paired_gain_mean, paired_gain_std = mean_std(paired_gains)
|
| 280 |
+
paired_gain_ci_low, paired_gain_ci_high = bootstrap_ci(paired_gains)
|
| 281 |
|
| 282 |
stage_deltas = []
|
| 283 |
for stage in stages:
|
|
|
|
| 333 |
"best_static_std": best_static_std,
|
| 334 |
"improvement": best_static_mean - condition_final_mean,
|
| 335 |
"paired_deltas": paired_deltas,
|
| 336 |
+
"paired_records": paired_records,
|
| 337 |
"paired_wins": sum(1 for delta in paired_deltas if delta < 0),
|
| 338 |
"paired_mean_delta": paired_mean,
|
| 339 |
"paired_std_delta": paired_std,
|
| 340 |
+
"paired_gain_mean": paired_gain_mean,
|
| 341 |
+
"paired_gain_std": paired_gain_std,
|
| 342 |
+
"paired_gain_ci_low": paired_gain_ci_low,
|
| 343 |
+
"paired_gain_ci_high": paired_gain_ci_high,
|
| 344 |
+
"budget": protocol_budget(condition_rows_by_stage, stages),
|
| 345 |
"stage_deltas": stage_deltas,
|
| 346 |
}
|
| 347 |
|
|
|
|
| 406 |
|
| 407 |
def write_calibration_curve_figure() -> None:
|
| 408 |
axes = []
|
| 409 |
+
for idx, (key, paths) in enumerate(REGIMES.items()):
|
| 410 |
raw_curve = static_curve_points(
|
| 411 |
paths["curve_run"], paths["curve_model"], paths["curve_prefix"]
|
| 412 |
)
|
| 413 |
minimum = min(loss for _, loss in raw_curve)
|
| 414 |
points = [(dropout, loss - minimum) for dropout, loss in raw_curve]
|
| 415 |
best = min(raw_curve, key=lambda item: item[1])
|
| 416 |
+
axis_options = [
|
| 417 |
+
f" title={{{paths['curve_title']}}},",
|
| 418 |
+
" xlabel={Dropout},",
|
| 419 |
+
]
|
| 420 |
+
if idx == 0:
|
| 421 |
+
axis_options.append(" ylabel={Validation loss above best},")
|
| 422 |
+
axis_options.extend(
|
| 423 |
+
[
|
| 424 |
+
" ymin=0,",
|
| 425 |
+
" grid=both,",
|
| 426 |
+
]
|
| 427 |
+
)
|
| 428 |
axes.append(
|
| 429 |
rf"""
|
| 430 |
\nextgroupplot[
|
| 431 |
+
{chr(10).join(axis_options)}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
]
|
| 433 |
\addplot+[thick, mark=*] coordinates {{{tikz_coordinates(points, digits=5)}}};
|
| 434 |
\addlegendentry{{static sweep}}
|
|
|
|
| 470 |
"\\addplot+[thick, mark=*] coordinates {"
|
| 471 |
+ tikz_coordinates(coords)
|
| 472 |
+ "};\n"
|
| 473 |
+
+ f"\\addlegendentry{{{model_label(model)}}}"
|
| 474 |
)
|
| 475 |
xticks = ",".join(str(i) for i in range(len(labels)))
|
| 476 |
xticklabels = ",".join(token_label(prefix) for prefix in labels)
|
|
|
|
| 582 |
(FIG_DIR / "final_improvements.tex").write_text(content, encoding="utf-8")
|
| 583 |
|
| 584 |
|
| 585 |
+
def write_protocol_schematic() -> None:
|
| 586 |
+
content = r"""
|
| 587 |
+
\begin{tikzpicture}[font=\scriptsize]
|
| 588 |
+
\tikzstyle{box}=[
|
| 589 |
+
draw,
|
| 590 |
+
rounded corners=2pt,
|
| 591 |
+
thick,
|
| 592 |
+
align=center,
|
| 593 |
+
text width=0.19\textwidth,
|
| 594 |
+
minimum height=1.5cm,
|
| 595 |
+
inner sep=5pt
|
| 596 |
+
]
|
| 597 |
+
\node[box, fill=blue!7] at (0,0) (sweep) {Static calibration cells\\
|
| 598 |
+
\footnotesize model $P$, prefix $U$, sampled tokens $C$, dropout grid};
|
| 599 |
+
\node[box, fill=green!8] at (3.7,0) (target) {Extract $p^\star$\\
|
| 600 |
+
\footnotesize grid best or bracketed quadratic minimum};
|
| 601 |
+
\node[box, fill=yellow!12] at (7.4,0) (fit) {Fit pressure law\\
|
| 602 |
+
\footnotesize $p^\star \approx A x + B y + Dxy + C_0$};
|
| 603 |
+
\node[box, fill=red!7] at (11.1,0) (stream) {Frozen streaming test\\
|
| 604 |
+
\footnotesize compare decay path to best static dropout grid};
|
| 605 |
+
\draw[->, thick] (sweep.east) -- (target.west);
|
| 606 |
+
\draw[->, thick] (target.east) -- (fit.west);
|
| 607 |
+
\draw[->, thick] (fit.east) -- (stream.west);
|
| 608 |
+
\node[align=center, text width=0.9\textwidth] at (5.55,-1.45) {
|
| 609 |
+
Inputs to the fitted law are absolute quantities available before or during a run:
|
| 610 |
+
$x=\log_{10}(P/U)$ measures capacity pressure and
|
| 611 |
+
$y=\log_{10}(C/U)$ measures repeated-sampling pressure.
|
| 612 |
+
};
|
| 613 |
+
\end{tikzpicture}
|
| 614 |
+
"""
|
| 615 |
+
(FIG_DIR / "calibration_to_streaming_protocol.tex").write_text(
|
| 616 |
+
content.strip() + "\n", encoding="utf-8"
|
| 617 |
+
)
|
| 618 |
+
|
| 619 |
+
|
| 620 |
def write_tables(summaries: dict[str, dict], coeffs: dict[str, dict]) -> None:
|
| 621 |
+
symbol_lines = [
|
| 622 |
+
"\\begin{tabular}{ll}",
|
| 623 |
+
"\\toprule",
|
| 624 |
+
"Symbol & Meaning \\\\",
|
| 625 |
+
"\\midrule",
|
| 626 |
+
"$P$ & Trainable parameter count \\\\",
|
| 627 |
+
"$U_t$ & Unique-token prefix currently revealed by stream stage $t$ \\\\",
|
| 628 |
+
"$C_t$ & Cumulative sampled training tokens consumed by the optimizer \\\\",
|
| 629 |
+
"$x_t$ & $\\log_{10}(P/U_t)$, capacity pressure \\\\",
|
| 630 |
+
"$y_t$ & $\\log_{10}(C_t/U_t)$, repeated-sampling pressure \\\\",
|
| 631 |
+
"$p_t$ & Dropout rate used at stream stage $t$ \\\\",
|
| 632 |
+
"$p^\\star$ & Static-sweep target dropout for one calibration cell \\\\",
|
| 633 |
+
"$A,B,D,C_0$ & Regime-specific fitted pressure-law coefficients \\\\",
|
| 634 |
+
"$p_{\\min},p_{\\max}$ & Clamp bounds applied to generated dropout schedules \\\\",
|
| 635 |
+
"\\bottomrule",
|
| 636 |
+
"\\end{tabular}",
|
| 637 |
+
]
|
| 638 |
+
(TABLE_DIR / "symbol_table.tex").write_text(
|
| 639 |
+
"\n".join(symbol_lines) + "\n", encoding="utf-8"
|
| 640 |
+
)
|
| 641 |
+
|
| 642 |
+
regime_lines = [
|
| 643 |
+
"\\begin{tabular}{llll}",
|
| 644 |
+
"\\toprule",
|
| 645 |
+
"Regime & Corpus source & Tokenizer / vocab & Streaming prefixes \\\\",
|
| 646 |
+
"\\midrule",
|
| 647 |
+
(
|
| 648 |
+
"OpenWebText10K & Cached OpenWebText-style subset & BPE / 4096 & "
|
| 649 |
+
"250k, 500k, 1M, 2M, 4M; plus 8M L20 tier \\\\"
|
| 650 |
+
),
|
| 651 |
+
(
|
| 652 |
+
"TinyStories & Cached TinyStories subset & BPE / 4096 & "
|
| 653 |
+
"500k, 1M, 2M, 4M; plus 8M L20 tier \\\\"
|
| 654 |
+
),
|
| 655 |
+
(
|
| 656 |
+
"WikiText-103 & Cached WikiText-103 subset & BPE / 4096 & "
|
| 657 |
+
"250k, 500k, 1M, 2M, 4M; plus 8M L20 tier \\\\"
|
| 658 |
+
),
|
| 659 |
+
"\\bottomrule",
|
| 660 |
+
"\\end{tabular}",
|
| 661 |
+
]
|
| 662 |
+
(TABLE_DIR / "regime_setup_table.tex").write_text(
|
| 663 |
+
"\n".join(regime_lines) + "\n", encoding="utf-8"
|
| 664 |
+
)
|
| 665 |
+
|
| 666 |
+
repro_lines = [
|
| 667 |
+
"\\begin{tabular}{ll}",
|
| 668 |
+
"\\toprule",
|
| 669 |
+
"Item & Value \\\\",
|
| 670 |
+
"\\midrule",
|
| 671 |
+
"Repository & \\url{https://huggingface.co/cuber12/dropout-decay} \\\\",
|
| 672 |
+
"Repository snapshot & Base commit \\texttt{e7a7275}; cite final release tag with paper \\\\",
|
| 673 |
+
"License & MIT-derived source with nanochat attribution retained \\\\",
|
| 674 |
+
"Python & 3.11.15 \\\\",
|
| 675 |
+
"PyTorch & 2.12.0 \\\\",
|
| 676 |
+
"Operating system & macOS 26.4 arm64 \\\\",
|
| 677 |
+
"Training backend & Apple Metal Performance Shaders (MPS); runner refuses CPU/CUDA \\\\",
|
| 678 |
+
"\\bottomrule",
|
| 679 |
+
"\\end{tabular}",
|
| 680 |
+
]
|
| 681 |
+
(TABLE_DIR / "reproducibility_table.tex").write_text(
|
| 682 |
+
"\n".join(repro_lines) + "\n", encoding="utf-8"
|
| 683 |
+
)
|
| 684 |
+
|
| 685 |
+
weight_lines = [
|
| 686 |
+
"\\begin{tabular}{lll}",
|
| 687 |
+
"\\toprule",
|
| 688 |
+
"Cell property & Weight multiplier & Reason \\\\",
|
| 689 |
+
"\\midrule",
|
| 690 |
+
"Best grid point on dropout boundary & $0.30$ & Optimum may lie outside tested grid \\\\",
|
| 691 |
+
"Quadratic minimum not bracketed & $0.50$ & Local parabola is less reliable \\\\",
|
| 692 |
+
"Loss span below $0.02$ nats & $0.50$ & Very flat curve weakly identifies $p^\\star$ \\\\",
|
| 693 |
+
(
|
| 694 |
+
"Best-loss std. $\\sigma > 0$ & $1/(1+20\\sigma)$ & "
|
| 695 |
+
"Noisier minima receive less influence \\\\"
|
| 696 |
+
),
|
| 697 |
+
"\\bottomrule",
|
| 698 |
+
"\\end{tabular}",
|
| 699 |
+
]
|
| 700 |
+
(TABLE_DIR / "calibration_weight_table.tex").write_text(
|
| 701 |
+
"\n".join(weight_lines) + "\n", encoding="utf-8"
|
| 702 |
+
)
|
| 703 |
+
|
| 704 |
+
protocol_lines = [
|
| 705 |
+
"\\begin{tabular}{llll}",
|
| 706 |
+
"\\toprule",
|
| 707 |
+
"Experiment layer & What is run & Question answered & Statistical unit \\\\",
|
| 708 |
+
"\\midrule",
|
| 709 |
+
(
|
| 710 |
+
"Static calibration & Per-regime dropout grid at fixed $(P,U,C)$ cells & "
|
| 711 |
+
"Where does validation loss plateau over dropout? & 15--16 cells per regime \\\\"
|
| 712 |
+
),
|
| 713 |
+
(
|
| 714 |
+
"Coefficient fit & Per-regime regression from cell targets $p^\\star$ & "
|
| 715 |
+
"Can pressure variables predict useful dropout? & MAE / leave-out MAE \\\\"
|
| 716 |
+
),
|
| 717 |
+
(
|
| 718 |
+
"4M final-prefix locked stream & Per-regime continuing model over growing prefixes & "
|
| 719 |
+
"Does decay beat the best tested fixed dropout? & 5 paired seeds per regime \\\\"
|
| 720 |
+
),
|
| 721 |
+
(
|
| 722 |
+
"L20 8M extrapolation & Per-regime 51.84M-param model with frozen coefficients & "
|
| 723 |
+
"Does the law extend to larger model/data scale? & 3 paired seeds per regime \\\\"
|
| 724 |
+
),
|
| 725 |
+
(
|
| 726 |
+
"Stage-wise audit & Per-regime decay vs best static at every prefix & "
|
| 727 |
+
"Is the schedule final-loss or per-prefix optimal? & Prefix-level deltas \\\\"
|
| 728 |
+
),
|
| 729 |
+
"\\bottomrule",
|
| 730 |
+
"\\end{tabular}",
|
| 731 |
+
]
|
| 732 |
+
(TABLE_DIR / "experiment_protocol_table.tex").write_text(
|
| 733 |
+
"\n".join(protocol_lines) + "\n", encoding="utf-8"
|
| 734 |
+
)
|
| 735 |
+
|
| 736 |
+
budget_lines = [
|
| 737 |
+
"\\begin{tabular}{llllrr}",
|
| 738 |
+
"\\toprule",
|
| 739 |
+
"Regime & Protocol & Prefix path & Sampled/stage & Batch & Block \\\\",
|
| 740 |
+
"\\midrule",
|
| 741 |
+
]
|
| 742 |
+
for key, paths in REGIMES.items():
|
| 743 |
+
for protocol_key, protocol_label in [
|
| 744 |
+
("small", paths["small_protocol"]),
|
| 745 |
+
("l20", "8M final prefix / 3 seeds"),
|
| 746 |
+
]:
|
| 747 |
+
budget = summaries[key][protocol_key]["budget"]
|
| 748 |
+
prefix_path = " $\\rightarrow$ ".join(token_label(prefix) for prefix in budget["prefix_path"])
|
| 749 |
+
sampled = ", ".join(token_label(value) for value in budget["sampled_per_stage"])
|
| 750 |
+
batch = "/".join(str(value) for value in budget["batch_sizes"])
|
| 751 |
+
block = str(budget["block_size"])
|
| 752 |
+
budget_lines.append(
|
| 753 |
+
f"{tex_escape(paths['label'])} & {tex_escape(protocol_label)} & "
|
| 754 |
+
f"{prefix_path} & {sampled} & {batch} & {block} \\\\"
|
| 755 |
+
)
|
| 756 |
+
budget_lines.extend(["\\bottomrule", "\\end{tabular}"])
|
| 757 |
+
(TABLE_DIR / "protocol_budget_table.tex").write_text(
|
| 758 |
+
"\n".join(budget_lines) + "\n", encoding="utf-8"
|
| 759 |
+
)
|
| 760 |
+
|
| 761 |
coeff_lines = [
|
| 762 |
"\\begin{tabular}{lrrrrrrrr}",
|
| 763 |
"\\toprule",
|
| 764 |
+
"Regime & Cells & A & B & D & C0 & Dropout MAE (abs. $p$) & L-model MAE & L-prefix MAE \\\\",
|
| 765 |
"\\midrule",
|
| 766 |
]
|
| 767 |
for key in REGIMES:
|
|
|
|
| 776 |
"\n".join(coeff_lines) + "\n", encoding="utf-8"
|
| 777 |
)
|
| 778 |
|
| 779 |
+
evidence_lines = [
|
| 780 |
+
"\\begin{tabular}{lrrrrr}",
|
| 781 |
+
"\\toprule",
|
| 782 |
+
"Regime & Calib. dropout MAE & 4M gain (nats) & 4M wins & 8M gain (nats) & 8M wins \\\\",
|
| 783 |
+
"\\midrule",
|
| 784 |
+
]
|
| 785 |
+
for key, paths in REGIMES.items():
|
| 786 |
+
small = summaries[key]["small"]
|
| 787 |
+
l20 = summaries[key]["l20"]
|
| 788 |
+
evidence_lines.append(
|
| 789 |
+
f"{tex_escape(paths['label'])} & {coeffs[key]['mae']:.4f} & "
|
| 790 |
+
f"{small['improvement']:.4f} & {small['paired_wins']}/{small['n']} & "
|
| 791 |
+
f"{l20['improvement']:.4f} & {l20['paired_wins']}/{l20['n']} \\\\"
|
| 792 |
+
)
|
| 793 |
+
evidence_lines.extend(["\\bottomrule", "\\end{tabular}"])
|
| 794 |
+
(TABLE_DIR / "evidence_ladder_table.tex").write_text(
|
| 795 |
+
"\n".join(evidence_lines) + "\n", encoding="utf-8"
|
| 796 |
+
)
|
| 797 |
+
|
| 798 |
val_lines = [
|
| 799 |
"\\begin{tabular}{llrrrrr}",
|
| 800 |
"\\toprule",
|
| 801 |
+
"Regime & Protocol & Decay final (nats) & Best static final (nats) & Gain (nats) & Seeds & Paired wins \\\\",
|
| 802 |
"\\midrule",
|
| 803 |
]
|
| 804 |
for key, paths in REGIMES.items():
|
|
|
|
| 815 |
"\n".join(val_lines) + "\n", encoding="utf-8"
|
| 816 |
)
|
| 817 |
|
| 818 |
+
paired_lines = [
|
| 819 |
+
"\\begin{tabular}{llrrrr}",
|
| 820 |
+
"\\toprule",
|
| 821 |
+
"Regime & Protocol & Paired gain mean & 95\\% bootstrap CI & Seeds & Wins \\\\",
|
| 822 |
+
"\\midrule",
|
| 823 |
+
]
|
| 824 |
+
for key, paths in REGIMES.items():
|
| 825 |
+
for protocol_key, protocol_label in [
|
| 826 |
+
("small", paths["small_protocol"]),
|
| 827 |
+
("l20", "8M final prefix / 3 seeds"),
|
| 828 |
+
]:
|
| 829 |
+
row = summaries[key][protocol_key]
|
| 830 |
+
paired_lines.append(
|
| 831 |
+
f"{tex_escape(paths['label'])} & {tex_escape(protocol_label)} & "
|
| 832 |
+
f"{row['paired_gain_mean']:.4f} & "
|
| 833 |
+
f"[{row['paired_gain_ci_low']:.4f}, {row['paired_gain_ci_high']:.4f}] & "
|
| 834 |
+
f"{row['n']} & {row['paired_wins']}/{row['n']} \\\\"
|
| 835 |
+
)
|
| 836 |
+
paired_lines.extend(["\\bottomrule", "\\end{tabular}"])
|
| 837 |
+
(TABLE_DIR / "paired_gain_ci_table.tex").write_text(
|
| 838 |
+
"\n".join(paired_lines) + "\n", encoding="utf-8"
|
| 839 |
+
)
|
| 840 |
+
|
| 841 |
+
path_lines = [
|
| 842 |
+
"\\begin{tabular}{llll}",
|
| 843 |
+
"\\toprule",
|
| 844 |
+
"Regime & Locked-stream prefix path & Frozen decay path & Final best static \\\\",
|
| 845 |
+
"\\midrule",
|
| 846 |
+
]
|
| 847 |
+
for key, paths in REGIMES.items():
|
| 848 |
+
stage_rows = summaries[key]["l20"]["stage_deltas"]
|
| 849 |
+
prefix_path = " $\\rightarrow$ ".join(token_label(row["prefix"]) for row in stage_rows)
|
| 850 |
+
dropout_path = " $\\rightarrow$ ".join(
|
| 851 |
+
f"{row['condition_dropout']:.3f}" for row in stage_rows
|
| 852 |
+
)
|
| 853 |
+
final_static = summaries[key]["l20"]["best_static_condition"].replace(
|
| 854 |
+
"static_dropout_", "p="
|
| 855 |
+
)
|
| 856 |
+
path_lines.append(
|
| 857 |
+
f"{tex_escape(paths['label'])} & {prefix_path} & {dropout_path} & "
|
| 858 |
+
f"{tex_escape(final_static)} \\\\"
|
| 859 |
+
)
|
| 860 |
+
path_lines.extend(["\\bottomrule", "\\end{tabular}"])
|
| 861 |
+
(TABLE_DIR / "l20_schedule_path_table.tex").write_text(
|
| 862 |
+
"\n".join(path_lines) + "\n", encoding="utf-8"
|
| 863 |
+
)
|
| 864 |
+
|
| 865 |
l20_lines = [
|
| 866 |
"\\begin{tabular}{lrrrrr}",
|
| 867 |
"\\toprule",
|
| 868 |
+
"Regime & Prefix & Decay dropout & Decay val (nats) & Best static val (nats) & Delta (nats) \\\\",
|
| 869 |
"\\midrule",
|
| 870 |
]
|
| 871 |
for key, paths in REGIMES.items():
|
|
|
|
| 906 |
}
|
| 907 |
write_calibration_curve_figure()
|
| 908 |
write_static_optima_figure()
|
| 909 |
+
write_protocol_schematic()
|
| 910 |
write_l20_stage_delta_figure(summaries)
|
| 911 |
write_final_improvement_figure(summaries)
|
| 912 |
write_tables(summaries, coeffs)
|
scripts/summarize_cross_regime_backtest.py
CHANGED
|
@@ -27,7 +27,7 @@ import statistics
|
|
| 27 |
|
| 28 |
|
| 29 |
ROOT = Path("runs/coefficient_calibration/cross_regime_backtest")
|
| 30 |
-
REPORT_PATH = Path("
|
| 31 |
|
| 32 |
|
| 33 |
FIT_DIRS = {
|
|
|
|
| 27 |
|
| 28 |
|
| 29 |
ROOT = Path("runs/coefficient_calibration/cross_regime_backtest")
|
| 30 |
+
REPORT_PATH = Path("archive/legacy_docs/cross_regime_backtest_report.md")
|
| 31 |
|
| 32 |
|
| 33 |
FIT_DIRS = {
|
src/dropout_decay/data/__init__.py
CHANGED
|
@@ -16,6 +16,8 @@ The above copyright notice and this permission notice shall be included in all
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
|
|
|
|
|
|
| 19 |
from dropout_decay.datasets import (
|
| 20 |
CachedTokenizer,
|
| 21 |
TokenSplits,
|
|
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
| 19 |
+
# Backward-compatible public exports. Dataset helpers now live in
|
| 20 |
+
# dropout_decay.datasets and experiment dataclasses live in dropout_decay.specs.
|
| 21 |
from dropout_decay.datasets import (
|
| 22 |
CachedTokenizer,
|
| 23 |
TokenSplits,
|
src/dropout_decay/experiment.py
CHANGED
|
@@ -16,6 +16,8 @@ The above copyright notice and this permission notice shall be included in all
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
|
|
|
|
|
|
| 19 |
from dropout_decay.experiments.runner import build_parser, main, run
|
| 20 |
|
| 21 |
__all__ = [
|
|
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
| 19 |
+
# Backward-compatible public exports. The implementation lives in
|
| 20 |
+
# dropout_decay.experiments.runner; historical scripts import this module.
|
| 21 |
from dropout_decay.experiments.runner import build_parser, main, run
|
| 22 |
|
| 23 |
__all__ = [
|
src/dropout_decay/model.py
CHANGED
|
@@ -16,6 +16,8 @@ The above copyright notice and this permission notice shall be included in all
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
|
|
|
|
|
|
| 19 |
from dropout_decay.models.gpt import (
|
| 20 |
Block,
|
| 21 |
CausalSelfAttention,
|
|
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
| 19 |
+
# Backward-compatible public exports. The implementation lives in
|
| 20 |
+
# dropout_decay.models.gpt; historical scripts import this module.
|
| 21 |
from dropout_decay.models.gpt import (
|
| 22 |
Block,
|
| 23 |
CausalSelfAttention,
|
src/dropout_decay/scheduler.py
CHANGED
|
@@ -16,6 +16,8 @@ The above copyright notice and this permission notice shall be included in all
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
|
|
|
|
|
|
| 19 |
from dropout_decay.schedules.dropout import DropoutDecayConfig, DropoutDecayScheduler
|
| 20 |
|
| 21 |
__all__ = [
|
|
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
| 19 |
+
# Backward-compatible public exports. The implementation lives in
|
| 20 |
+
# dropout_decay.schedules.dropout; historical scripts import this module.
|
| 21 |
from dropout_decay.schedules.dropout import DropoutDecayConfig, DropoutDecayScheduler
|
| 22 |
|
| 23 |
__all__ = [
|
src/dropout_decay/tokenizer.py
CHANGED
|
@@ -16,6 +16,8 @@ The above copyright notice and this permission notice shall be included in all
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
|
|
|
|
|
|
| 19 |
from dropout_decay.tokenization.bpe import BpeTokenizer, SPECIAL_TOKENS, SPLIT_PATTERN
|
| 20 |
|
| 21 |
__all__ = [
|
|
|
|
| 16 |
copies or substantial portions of the Software.
|
| 17 |
"""
|
| 18 |
|
| 19 |
+
# Backward-compatible public exports. The implementation lives in
|
| 20 |
+
# dropout_decay.tokenization.bpe; historical scripts import this module.
|
| 21 |
from dropout_decay.tokenization.bpe import BpeTokenizer, SPECIAL_TOKENS, SPLIT_PATTERN
|
| 22 |
|
| 23 |
__all__ = [
|
tests/test_data_and_device.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
import tempfile
|
| 4 |
+
import unittest
|
| 5 |
+
from unittest.mock import patch
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
|
| 9 |
+
from dropout_decay.data import load_cached_splits
|
| 10 |
+
from dropout_decay.experiments.device import assert_mps_only
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class DataAndDeviceTests(unittest.TestCase):
|
| 14 |
+
def test_load_cached_splits_uses_expected_train_val_partition(self):
|
| 15 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 16 |
+
cache_dir = Path(tmp)
|
| 17 |
+
(cache_dir / "tokenizer-v16.json").write_text("{}", encoding="utf-8")
|
| 18 |
+
np.save(cache_dir / "tokens-v16-uint16.npy", np.arange(100, dtype=np.uint16))
|
| 19 |
+
|
| 20 |
+
tokenizer, splits = load_cached_splits(
|
| 21 |
+
cache_dir=cache_dir,
|
| 22 |
+
vocab_size=16,
|
| 23 |
+
max_required_train_tokens=80,
|
| 24 |
+
val_tokens=10,
|
| 25 |
+
allow_short_corpus=False,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
self.assertEqual(tokenizer.vocab_size, 16)
|
| 29 |
+
self.assertEqual(len(splits.train), 90)
|
| 30 |
+
self.assertEqual(len(splits.val), 10)
|
| 31 |
+
self.assertEqual(splits.tokenizer_path, cache_dir / "tokenizer-v16.json")
|
| 32 |
+
|
| 33 |
+
def test_load_cached_splits_rejects_missing_cache(self):
|
| 34 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 35 |
+
with self.assertRaises(FileNotFoundError):
|
| 36 |
+
load_cached_splits(
|
| 37 |
+
cache_dir=Path(tmp),
|
| 38 |
+
vocab_size=16,
|
| 39 |
+
max_required_train_tokens=10,
|
| 40 |
+
val_tokens=10,
|
| 41 |
+
allow_short_corpus=False,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
def test_mps_guard_rejects_fallback_before_backend_checks(self):
|
| 45 |
+
env = dict(os.environ)
|
| 46 |
+
env["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
|
| 47 |
+
with patch.dict(os.environ, env, clear=True):
|
| 48 |
+
with self.assertRaises(SystemExit) as caught:
|
| 49 |
+
assert_mps_only()
|
| 50 |
+
|
| 51 |
+
self.assertIn("MPS_FALLBACK", str(caught.exception))
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
if __name__ == "__main__":
|
| 55 |
+
unittest.main()
|
tests/test_schedules.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import unittest
|
| 3 |
+
|
| 4 |
+
from dropout_decay.schedules import DropoutDecayConfig, DropoutDecayScheduler
|
| 5 |
+
from dropout_decay.specs import DropoutCondition, anchor_dropout
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class DropoutScheduleTests(unittest.TestCase):
|
| 9 |
+
def test_linear_decay_endpoints_and_midpoint(self):
|
| 10 |
+
scheduler = DropoutDecayScheduler(
|
| 11 |
+
DropoutDecayConfig(
|
| 12 |
+
initial_dropout=0.30,
|
| 13 |
+
final_dropout=0.10,
|
| 14 |
+
decay_tokens=100,
|
| 15 |
+
schedule="linear",
|
| 16 |
+
)
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
self.assertAlmostEqual(scheduler.value(0), 0.30)
|
| 20 |
+
self.assertAlmostEqual(scheduler.value(50), 0.20)
|
| 21 |
+
self.assertAlmostEqual(scheduler.value(100), 0.10)
|
| 22 |
+
self.assertAlmostEqual(scheduler.value(1000), 0.10)
|
| 23 |
+
|
| 24 |
+
def test_cosine_decay_midpoint(self):
|
| 25 |
+
scheduler = DropoutDecayScheduler(
|
| 26 |
+
DropoutDecayConfig(
|
| 27 |
+
initial_dropout=0.40,
|
| 28 |
+
final_dropout=0.20,
|
| 29 |
+
decay_tokens=100,
|
| 30 |
+
schedule="cosine",
|
| 31 |
+
)
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
self.assertAlmostEqual(scheduler.value(50), 0.30)
|
| 35 |
+
|
| 36 |
+
def test_invalid_scheduler_config_rejected(self):
|
| 37 |
+
with self.assertRaises(ValueError):
|
| 38 |
+
DropoutDecayScheduler(
|
| 39 |
+
DropoutDecayConfig(
|
| 40 |
+
initial_dropout=0.10,
|
| 41 |
+
final_dropout=0.30,
|
| 42 |
+
decay_tokens=100,
|
| 43 |
+
schedule="linear",
|
| 44 |
+
)
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
def test_anchor_dropout_interpolates_in_log_token_space(self):
|
| 48 |
+
anchors = ((100, 0.30), (10_000, 0.10))
|
| 49 |
+
value = anchor_dropout(1_000, anchors)
|
| 50 |
+
expected_mix = (math.log(1_000) - math.log(100)) / (
|
| 51 |
+
math.log(10_000) - math.log(100)
|
| 52 |
+
)
|
| 53 |
+
expected = 0.30 + expected_mix * (0.10 - 0.30)
|
| 54 |
+
|
| 55 |
+
self.assertAlmostEqual(value, expected)
|
| 56 |
+
|
| 57 |
+
def test_anchor_condition_requires_unique_tokens(self):
|
| 58 |
+
condition = DropoutCondition(
|
| 59 |
+
name="fit",
|
| 60 |
+
kind="anchor_decay",
|
| 61 |
+
initial=0.30,
|
| 62 |
+
final=0.10,
|
| 63 |
+
anchors=((100, 0.30), (10_000, 0.10)),
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
with self.assertRaises(ValueError):
|
| 67 |
+
condition.make_fn(fallback_decay_tokens=100)
|
| 68 |
+
|
| 69 |
+
fn = condition.make_fn(fallback_decay_tokens=100, unique_tokens=1_000)
|
| 70 |
+
self.assertAlmostEqual(fn(0), anchor_dropout(1_000, condition.anchors))
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
if __name__ == "__main__":
|
| 74 |
+
unittest.main()
|
tests/test_specs_and_parsing.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import unittest
|
| 3 |
+
|
| 4 |
+
from dropout_decay.experiments.parsing import (
|
| 5 |
+
clean_name,
|
| 6 |
+
parse_anchor_decay_spec,
|
| 7 |
+
parse_decay_spec,
|
| 8 |
+
parse_model_spec,
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class SpecParsingTests(unittest.TestCase):
|
| 13 |
+
def test_parse_model_spec_default_and_named(self):
|
| 14 |
+
default = parse_model_spec("12x8x320")
|
| 15 |
+
named = parse_model_spec("winner=12x8x320")
|
| 16 |
+
|
| 17 |
+
self.assertEqual(default.name, "L12_H8_D320")
|
| 18 |
+
self.assertEqual(named.name, "winner")
|
| 19 |
+
self.assertEqual(named.to_dict()["n_embd"], 320)
|
| 20 |
+
|
| 21 |
+
def test_parse_model_spec_rejects_incompatible_heads(self):
|
| 22 |
+
with self.assertRaises(argparse.ArgumentTypeError):
|
| 23 |
+
parse_model_spec("3x5x32")
|
| 24 |
+
|
| 25 |
+
def test_parse_decay_spec_defaults_to_cosine(self):
|
| 26 |
+
condition = parse_decay_spec("mild:0.30:0.10")
|
| 27 |
+
|
| 28 |
+
self.assertEqual(condition.name, "mild")
|
| 29 |
+
self.assertEqual(condition.kind, "decay")
|
| 30 |
+
self.assertEqual(condition.schedule, "cosine")
|
| 31 |
+
self.assertIsNone(condition.decay_tokens)
|
| 32 |
+
|
| 33 |
+
def test_parse_anchor_decay_spec_sorts_and_validates(self):
|
| 34 |
+
condition = parse_anchor_decay_spec("fit:1000=0.20,100=0.30")
|
| 35 |
+
|
| 36 |
+
self.assertEqual(condition.kind, "anchor_decay")
|
| 37 |
+
self.assertEqual(condition.anchors, ((100, 0.30), (1000, 0.20)))
|
| 38 |
+
self.assertEqual(condition.initial, 0.30)
|
| 39 |
+
self.assertEqual(condition.final, 0.20)
|
| 40 |
+
|
| 41 |
+
def test_parse_anchor_decay_spec_rejects_increasing_dropout(self):
|
| 42 |
+
with self.assertRaises(argparse.ArgumentTypeError):
|
| 43 |
+
parse_anchor_decay_spec("fit:100=0.10,1000=0.20")
|
| 44 |
+
|
| 45 |
+
def test_clean_name_keeps_stable_condition_labels(self):
|
| 46 |
+
self.assertEqual(clean_name(" mild 30->08 "), "mild_30-_08")
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
if __name__ == "__main__":
|
| 50 |
+
unittest.main()
|