|
Download README.md from Physicsru/compgen-checkpoints: direct link, hf CLI and curl.
- Browser
- Download file 11.1 kB
-
https://huggingface.co/Physicsru/compgen-checkpoints/resolve/main/README.md
- Command line
-
hf download hf://Physicsru/compgen-checkpoints/README.md
-
curl -L -o README.md https://huggingface.co/Physicsru/compgen-checkpoints/resolve/main/README.md
11.1 kB
| license: apache-2.0 | |
| base_model: Qwen/Qwen3-4B-Base | |
| tags: | |
| - compositional-generalization | |
| - interpretability | |
| - recall-then-assemble | |
| - grpo | |
| language: | |
| - en | |
| # Compositional-generalization checkpoints (recall-then-assemble, Qwen3-4B-Base) | |
| ## TL;DR | |
| 15 checkpoints of Qwen3-4B-Base from **one controlled study of whether a model can compose skills it has | |
| only ever seen in isolation**. Every checkpoint is one cell of that study; cells differ in exactly one | |
| training variable, so pairs of folders isolate one effect each. One subfolder = one complete HF model | |
| directory (fp32 `model.safetensors` β 16 GB, tokenizer, chat template). | |
| ```python | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| import torch | |
| repo, sub = "Physicsru/compgen-checkpoints", "sft-eco-s1" # any folder from the table below | |
| tok = AutoTokenizer.from_pretrained(repo, subfolder=sub) | |
| model = AutoModelForCausalLM.from_pretrained(repo, subfolder=sub, torch_dtype=torch.float32) | |
| ``` | |
| **Which two folders compare what** (held-out compositional accuracy at depth 4 / depth 8 unless stated): | |
| | contrast | without | with | effect | | |
| |---|---|---|---| | |
| | **Co-occurrence atomic data** (several independent single-skill tasks in one prompt/answer, width 2-4) β cleanest version: identical task stream and steps | `sft-matched-isolated-s1` | `sft-matched-grouped-s1` | 0.65 / 0.16 β 0.93 / 0.47 | | |
| | **Co-occurrence atomic data** β the paper's two models (same compositions; E-co has fewer rows) | `sft-v1-s1` | `sft-eco-s1` | 0.53 / 0.09 β 0.97 / 0.73 | | |
| | **Composition demos (depth 2-4, train skills only)**, atomics single-task | `sft-d1-s1` | `sft-v1-s1` | 0.00 / 0.00 β 0.53 / 0.09 | | |
| | **Composition demos**, atomics in co-occurrence groups | `sft-c1-s1` | `sft-eco-s1` | 0.66 / 0.08 β 0.97 / 0.73 | | |
| | **Depth of the demos** (depth-2 only vs depth 2-4, same row count) | `sft-c4-s1` | `sft-c4b-s1` | 0.70 / 0.12 β 0.90 / 0.62 | | |
| | **RL** (GRPO on train-skill chains + atomic prompts; held-out skills never composed) β good outcome | `sft-eco-s1` | `rl-mdb-step100` | held-out chains d20 0.50 β 0.95 | | |
| | **RL** β drifted outcome (one held-out skill loses a parameter) | `sft-eco-s1` | `rl-r1a-step100` | d20 0.50 β 0.61; `func_24` arity error 25% | | |
| | **Seed only** (same RL pool, same init) | `rl-r1a-step100` | `rl-r1b-step100` | d20 0.61 vs 0.89; arity error 25% vs 1% | | |
| | **Same RL run over time** (drift switches on, then off) | `rl-mda-step5` β `rl-mda-step50` | β `rl-mda-step100` | arity error 6% β 44% β 0.3%; d20 0.82 β 0.57 β 0.93 | | |
| | **The recall-then-assemble format itself** | `stage15b-init` | any `sft-*` | 0.03 / 0.00 β β¦ | | |
| The four SFT cells `sft-d1-s1`, `sft-v1-s1`, `sft-c1-s1`, `sft-eco-s1` form a 2Γ2 (co-occurrence no/yes Γ | |
| demos no/yes); all SFT cells start from `stage15b-init`; all RL runs start from `sft-eco-s1`. | |
| ## The task | |
| A library of 25 string operators with opaque names `func_0` β¦ `func_24` (e.g. `func_3` = sort the | |
| characters; `func_24` = a backtracking palindrome transform with a semantically unused `depth` parameter). | |
| The model first learns every operator **as an atomic skill** (closed-book: given `def main_solution(x): | |
| return func_3(x)` and an input, recall the body of `func_3` and write a program). It is then trained on | |
| **compositions** (`func_5(func_3(func_1(x, 2)), 'ab')`) built **only from the 13 train operators**; the 12 | |
| **held-out operators** are never composed in any training data. The test asks the model to compose the | |
| held-out operators. The answer format is *recall-then-assemble* (RA): one `Recall func_N: <gloss>` block | |
| with the definition per operator, then one `Assemble:` block with all definitions plus `main_solution`. | |
| Metrics: **held-out d4 / d8** = program accuracy on held-out-operator programs of expression depth 4 / 8 | |
| (256 per depth, `eval/heldout_trees_d1-8.parquet`); **chains d20** = pure nesting chains f1(f2(β¦f20(x))) | |
| over held-out operators (`eval/heldout_chains_d1-20.parquet`); **arity error** = fraction of `Recall | |
| func_24` blocks that drop the second parameter (`def func_24(s):`), the single failure that separates good | |
| and bad RL outcomes. Greedy decoding, 3,072 new tokens. | |
| ## Lineage | |
| ``` | |
| Qwen3-4B-Base | |
| ββ stage 1: atomic skills with bodies shown (RFT on code execution) | |
| ββ stage 1.5 "closed-book": 20k depth-1 atomic tasks over all 25 ops + 12k depth-2..4 TRAIN-op | |
| compositions, prose + one code block (no RA format) β stage15b-init | |
| ββ RA bootstrap SFT cells (2 epochs, batch 128, LR 2e-5, seed 1) β sft-* | |
| β all cells share the SAME 10,000 atomic tasks (400 per op, all 25 ops) and differ in | |
| β (a) how atomic tasks are packed into answers and (b) which composition rows are added | |
| ββ (from sft-eco-s1) GRPO, KL 0.01 to the init, 100 steps β rl-* | |
| ``` | |
| ## Checkpoints | |
| | folder | init | atomic side (10k single-op tasks) | composition side | RL pool | steps | held-out numbers | | |
| |---|---|---|---|---|---|---| | |
| | `stage15b-init` | stage 1 | 20k closed-book depth-1 rows, prose + one code block | 12k depth-2..4 train-op comps (same format) | β | 500 | d4 / d8 = 0.03 / 0.00 (no RA format yet) | | |
| | `sft-d1-s1` | stage15b-init | **single-task**: one op per answer | **none** | β | 152 | 0.00 / 0.00 | | |
| | `sft-v1-s1` | stage15b-init | single-task | 15,979 mixed-structure train-op comps, depth 2-4 | β | 400 | 0.53Β±0.15 / 0.09Β±0.05 (3 seeds; this seed 0.75 / 0.15) | | |
| | `sft-c1-s1` | stage15b-init | **co-occurrence groups**: 1-4 independent single-op tasks in one answer (all ops) | **none** | β | 58 | 0.66Β±0.14 / 0.08Β±0.04 | | |
| | `sft-eco-s1` ("E-co") | stage15b-init | co-occurrence groups | the same 15,979 comps | β | 308 | 0.97Β±0.02 / 0.73Β±0.15 (this seed 0.98 / 0.83); chains d20 0.50 | | |
| | `sft-c4-s1` | stage15b-init | co-occurrence groups | 12,452 mixed comps, **depth 2 only** | β | 252 | 0.70Β±0.03 / 0.12Β±0.05 | | |
| | `sft-c4b-s1` | stage15b-init | co-occurrence groups | 12,436 mixed comps, **depth 2-4** (same count as c4) | β | 252 | 0.90Β±0.04 / 0.62Β±0.13 | | |
| | `sft-matched-isolated-s1` | stage15b-init | per step: 48 atomic tasks as 48 single-task rows | per step: 76 comps (same stream as grouped) | β | 400 | 0.65Β±0.08 / 0.16Β±0.02 (3 paired seeds) | | |
| | `sft-matched-grouped-s1` | stage15b-init | per step: the SAME 48 atomic tasks packed into 20 grouped rows | the same 76 comps | β | 400 | 0.93Β±0.03 / 0.47Β±0.04 | | |
| | `rl-r1a-step100` | sft-eco-s1 | β | β | 1:1 mix of train-op serial chains d10-20 and all-op multi-task atomic prompts (widths 1-12) | 100 | chains d8/d12/d20 0.85 / 0.63 / 0.61; arity error 226/903 = 25% | | |
| | `rl-r1b-step100` | sft-eco-s1 | β | β | same pool, different seed | 100 | 0.94 / 0.97 / 0.89; 9/903 = 1% | | |
| | `rl-mda-step5` | sft-eco-s1 | β | β | **mixed-depth pool**: chains + prompts holding one deep train-op chain task followed by 1-2 long-literal atomic tasks over all ops | 5 | 0.95 / 0.92 / 0.82; 57/903 = 6% | | |
| | `rl-mda-step50` | sft-eco-s1 | β | β | same run | 50 | 0.91 / 0.63 / 0.57; 396/903 = **44%** | | |
| | `rl-mda-step100` | sft-eco-s1 | β | β | same run | 100 | 0.97 / 0.97 / 0.93; 3/903 = 0.3% | | |
| | `rl-mdb-step100` | sft-eco-s1 | β | β | mixed-depth pool, second replicate | 100 | 0.99 / 0.98 / 0.95; 33/903 = 3.7% | | |
| "Mixed-structure comps" = train-op compositions whose expression trees mix unary nesting, binary operators | |
| and literals (the benchmark's native generator). "Co-occurrence groups" put several *independent* atomic | |
| tasks into one prompt/answer so each definition is recalled next to others (no data flow between them). | |
| Held-out operators appear in every cell only as depth-1 atomic tasks. All steps: batch 128; SFT 2 epochs. | |
| ## What each contrast shows (for choosing an analysis) | |
| - **Co-occurrence** (`isolated` vs `grouped`, `v1` vs `eco`): the failure of the "without" model is a | |
| *chimera* β a held-out name written with a train operator's body (1,102 of 1,175 wrong bodies in v1). | |
| Decomposed inference (each helper recalled in its own forward pass, then assembled mechanically) scores | |
| 1.00 for v1, so the whole gap is nameβdefinition retrieval under multi-definition load, not missing | |
| knowledge. In the matched pair the gap opens from step 100. | |
| - **Composition demos** (`d1` vs `v1`, `c1` vs `eco`): without co-occurrence the demos are what makes any | |
| multi-helper program possible (d1 never writes one); with co-occurrence the model already composes at | |
| mid depth without a single demo (c1 0.66) and the demos buy depth (d8 0.08 β 0.73). Demo *diversity* | |
| matters (c4 vs c4b), demo *volume* does not (2k vs 12k depth-2 demos: 0.77 vs 0.70). | |
| - **RL** (`eco` vs `mdb` / `r1a`, `r1a` vs `r1b`, `mda` over time): RL on train-operator chains lifts deep | |
| serial execution for every operator (d20 0.50 β 0.9+), but in some seeds one held-out operator | |
| (`func_24`, whose dropped parameter is semantically inert) loses its second parameter when its call is | |
| nested among other library calls. The drift is latent in the SFT init (E-co writes `func_24(s)` in | |
| 0 / 5 / 18% of blocks at nameβargument distance <40 / 40-150 / 150+ chars), tracks the number of other | |
| library calls' argument tails between the name and the own argument, is not triggered by builtin-method | |
| tails, long literals, definition load or a preceding chain (probe families 1b/1d/1f/1g in `eval/`), and | |
| reverses inside one run (`mda` 44% β 0.3%). KL 0.01 keeps RL weights close to `sft-eco-s1`, so | |
| weight-difference analyses between `eco` and any `rl-*` folder, or between `mda` steps, are meaningful. | |
| ## Evaluation inputs (`eval/`) | |
| | file | rows | what | | |
| |---|---|---| | |
| | `heldout_trees_d1-8.parquet` | 2,048 | held-out-operator programs, depths 1-8 Γ 256 (the d4 / d8 numbers) | | |
| | `trainop_trees_d1-8.parquet` | 2,048 | the same over the 13 train operators | | |
| | `heldout_chains_d1-20.parquet` | 2,816 | pure nesting chains over held-out operators, d β {1,2,4,β¦,20} Γ 256, outputs β€ 1,000 chars | | |
| | `trainop_chains_d1-20.parquet` | 2,816 | the same over train operators | | |
| | `probe_1b.parquet` | 6,912 | definition-load probe: target op recalled after r other recalls (teacher-forced prefix) | | |
| | `probe_1d.parquet` | 1,792 | chain-position probe: target op at the outer / middle / inner position of a deep chain | | |
| | `probe_1f.parquet` | 2,048 | builtin-method argument tails in front of the op's own argument | | |
| | `probe_1g.parquet` | 1,280 | long literal (8-200 chars) as the op's first argument | | |
| Rows are in the verl code-execution format: `prompt` (chat messages), `reward_model.ground_truth` (JSON | |
| with `ref_code`, `ref_input`, `ref_output`), `extra_info` (depth, k = distinct ops, probe condition). | |
| ## Provenance | |
| Every number is traceable in the project ledger `verl/analysis/RESULTS_PROVENANCE.md` (sections MAIN | |
| RESULT, C1βC5 CAUSAL TABLE, MATCHED SFT, DEEP CHAINS, Mixed-depth arm RESULT, PROBES) to a job id, a | |
| sweep directory and a CI / classification report; 3-seed bands are mean Β± sd over trainer seeds 1 / 7 / 123. | |