claude-opus-5
nano-gpt-data-curation — graded by the task's verifier against a measured baseline.
- backend
- modal
- variant
- claude claude-opus-5
- metric
- held-out multi-domain perplexity
- actions
- 55
- duration
- 1h 12m
- recorded
- 2026-08-03
run iddclm-nano-curation__BgDz4nG
Score
Summary
All three deliverables are in place and verified.
Result: dev perplexity 302.6 vs. 458.0 for a random selection (−34%).
What I did:
- Recovered the target distribution. Decoded
multi_dev.npyback to text with the GPT-2 tokenizer. It's four contiguous register blocks — WikiText-style encyclopedic, news, general web prose, StackExchange HTML Q&A — located by scanning marker densities, and ~25% each in tokens. - Quality gates on the raw pool (length, alphabetic/ASCII ratio, mean word length, line- and word-level repetition, sentence structure, spam markers): 182,016 → 138,771 docs.
- Per-register importance scoring (DSIR-style): hashed unigram+bigram distributions for each register vs. a pool background sample; each document scored by the length-normalised log-likelihood ratio for all four registers, ranked independently within each.
- Proportional round-robin merge so the emitted priority list matches the target's 25/25/25/25 token mixture at every prefix — the packer can stop anywhere.
- MinHash near-duplicate removal at emit time (4 bands of 2).
Ablations, each a real training run (see the table in claim.md): arg-max register assignment 339.8 → per-register global ranking 340.3 → floored log-ratio + English gate + token-proportion mixture 314.6 → near-dup removal 302.6. Length cap (305.1), stricter (309.4) and looser (305.4) dedup, an 8-sub-register split (308.3), and a 30/20/20/30 mixture tilt (304.9) all lost.
Two bugs caught before they cost anything: add-one smoothing gave n-grams absent from both corpora a positive weight, which put Amharic navigation spam and minified JS at the top of every register; and my char-based mixture estimate (28.5/27/26/18.5) was wrong in token space.
Notes for you:
- The mixture-tilt loss (304.9 vs 302.6) is the one prediction of the hypothesis I could test directly, and it held. The per-register loss decomposition — the sharpest test — I did not run: the frozen trainer takes one held-out array per run and doesn't save the model, so it would have cost four extra runs.
claim.mdsays so explicitly rather than implying the mechanism was fully confirmed. - Differences among the losing variants (303–309) are single-seed and within plausible noise; the gap to random (458) and to the pre-fix versions (340) is not.
curate.pywas re-run from scratch with no cache at the end: it reproduces the submitted 34,960 ids bit-identically. TheMIX/LENCAP/DEDUP/BLOCKS8env knobs exist only to reproduce the ablation rows; defaults are the submitted config.