Dellboy commited on
Commit
557c9ad
·
verified ·
1 Parent(s): 3a9941b

Round 07 (teacher-distilled, regressed) and a correction: use round06 final, not checkpoint 2000

Browse files
README.md CHANGED
@@ -50,29 +50,59 @@ residual that shrank as curation improved and are marked accordingly.
50
  | `round03` | Cosine schedule, dropout, class rebalanced | 88.4% | not measured | live residual |
51
  | `round04` | Retrained on the 502-reagent lexicon | — | — | **abandoned**: trained on 36% duplicate rows |
52
  | `round05` | Deduplicated training set, 95,818 distinct pairs | 87.58% | 93.41% | first frozen-benchmark round |
53
- | `round06` | Full epoch, rank 16, 6,856 empty-answer examples | **90.52%** | 94.36% | **the one to use**, see below |
 
54
 
55
- ### Which checkpoint to use
56
 
57
- **`round06/promoted_checkpoint_2000.safetensors`, not `round06/adapters.safetensors`.**
58
 
59
- Round 06 ran 6,000 iterations. Sweeping its checkpoints against the frozen benchmark shows
60
- identification peaking at 2,000 and then *declining*, while fidelity to the rule parser climbs
61
- monotonically the whole way:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  | Iteration | Fidelity to rules | Residual identification |
64
  |---|---|---|
65
  | 500 | 80.60% | 86.80% |
66
- | 1,000 | 84.80% | 87.19% |
67
- | **2,000** | 89.60% | **90.52%** |
68
- | 4,000 | 93.20% | 88.91% |
69
  | 6,000 | 93.60% | 88.99% |
70
 
71
- That divergence is the distillation ceiling made visible. The labels are the rule parser's own
72
- output, so past ~2,000 iterations the model spends capacity imitating the teacher more exactly
73
- learning what is already in code — and pays for it on the residual, which is the only part that
74
- matters. Validation loss moved 0.003 across the whole span and pointed at 6,000 throughout, which
75
- is why it is not the stopping signal here.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  ## Using it
78
 
@@ -81,7 +111,7 @@ from mlx_lm import load, generate
81
 
82
  model, tokenizer = load(
83
  "mlx-community/SmolLM2-360M-Instruct",
84
- adapter_path="round06", # or the promoted checkpoint, renamed to adapters.safetensors
85
  )
86
 
87
  SYSTEM = (
 
50
  | `round03` | Cosine schedule, dropout, class rebalanced | 88.4% | not measured | live residual |
51
  | `round04` | Retrained on the 502-reagent lexicon | — | — | **abandoned**: trained on 36% duplicate rows |
52
  | `round05` | Deduplicated training set, 95,818 distinct pairs | 87.58% | 93.41% | first frozen-benchmark round |
53
+ | `round06` | Full epoch, rank 16, 6,856 empty-answer examples | **90.52%** at iter 2,000 | 94.36% | **the one to use** — the *final* adapter, see below |
54
+ | `round07` | Trained on 32B-teacher labels for the residual | — | — | **regressed**: recall +2.4 (not significant), precision 99.6% → 92.3% |
55
 
56
+ ### Which checkpoint to use, and a correction
57
 
58
+ **Use `round06/adapters.safetensors`, the final adapter.**
59
 
60
+ An earlier version of this card said to use `round06/promoted_checkpoint_2000` instead, on the
61
+ strength of a checkpoint sweep against a frozen 2,000-record benchmark. Measured against
62
+ **hand-labelled truth**, that was wrong:
63
+
64
+ | Round 06 adapter | Precision | Recall | F1 | False positives |
65
+ |---|---|---|---|---|
66
+ | **final, 6,000 iterations** | **99.6%** | **91.5%** | **95.4** | **1** |
67
+ | checkpoint 2,000 | 95.7% | 91.2% | 93.4 | 12 |
68
+
69
+ Twelve extra false positives against one, p = 0.0034. The checkpoint is kept in the repo because
70
+ the disagreement is the interesting part, not because it should be used.
71
+
72
+ **Why the sweep chose wrongly.** It ranked checkpoints on *identification* — whether an emitted
73
+ reagent name exists in the curated lexicon. That metric cannot see a name which is real, present
74
+ in the text, and simply not what the depositor meant, so a checkpoint that invents plausible
75
+ chemistry scores well on it. Only labelled truth separates the two. The frozen benchmark remains
76
+ useful for comparing rounds; it is not sufficient for choosing between them.
77
+
78
+ The sweep is still worth reading for what it shows about distillation:
79
 
80
  | Iteration | Fidelity to rules | Residual identification |
81
  |---|---|---|
82
  | 500 | 80.60% | 86.80% |
83
+ | 2,000 | 89.60% | 90.52% |
 
 
84
  | 6,000 | 93.60% | 88.99% |
85
 
86
+ Fidelity climbs monotonically while identification turns over: past a point the model spends its
87
+ capacity imitating the rule parser learning what is already in code rather than reading the
88
+ residual. Validation loss moved 0.003 across the whole span, which is why it is not the stopping
89
+ signal here.
90
+
91
+ ### Round 07, and why it is not recommended
92
+
93
+ `round07` was trained on labels from a local Qwen2.5-32B teacher, to get past the ceiling above.
94
+ It did not work, and is published because the negative result is worth having:
95
+
96
+ | | round 06 final | round 07 |
97
+ |---|---|---|
98
+ | Precision | **99.6%** | 92.3% |
99
+ | Recall | 91.5% | **93.9%** |
100
+ | False positives | **1** | 23 |
101
+
102
+ Paired on the same 96 records: recall recovered 18 reagents and lost 11 (p = 0.26, not
103
+ significant), while false positives went from 1 to 23 (p < 0.0001). The teacher's own labels
104
+ carried a 7.4% false-positive rate and the student learned it. The signal transferred weakly; the
105
+ noise transferred strongly.
106
 
107
  ## Using it
108
 
 
111
 
112
  model, tokenizer = load(
113
  "mlx-community/SmolLM2-360M-Instruct",
114
+ adapter_path="round06", # the final adapter, not promoted_checkpoint_2000
115
  )
116
 
117
  SYSTEM = (
round07/adapter_config.json ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "adapter_path": "data/interim/slm/runs/r1-parse-residual-smollm2-360m-round07",
3
+ "batch_size": 16,
4
+ "clear_cache_threshold": 0,
5
+ "config": "data/interim/slm/runs/r1-parse-residual-smollm2-360m-round07/training_config.yaml",
6
+ "data": "data/interim/slm_r7",
7
+ "fine_tune_type": "lora",
8
+ "grad_accumulation_steps": 1,
9
+ "grad_checkpoint": true,
10
+ "iters": 2000,
11
+ "learning_rate": 0.0001,
12
+ "lora_parameters": {
13
+ "rank": 16,
14
+ "dropout": 0.05,
15
+ "scale": 20.0
16
+ },
17
+ "lr_schedule": {
18
+ "name": "cosine_decay",
19
+ "arguments": [
20
+ 0.0001,
21
+ 1950,
22
+ 1e-05
23
+ ],
24
+ "warmup": 50,
25
+ "warmup_init": 1e-06
26
+ },
27
+ "mask_prompt": true,
28
+ "max_seq_length": 1024,
29
+ "model": "mlx-community/SmolLM2-360M-Instruct",
30
+ "num_layers": 16,
31
+ "optimizer": "adam",
32
+ "optimizer_config": {
33
+ "adam": {},
34
+ "adamw": {},
35
+ "muon": {},
36
+ "sgd": {},
37
+ "adafactor": {}
38
+ },
39
+ "project_name": "toppdblx",
40
+ "report_to": "wandb",
41
+ "resume_adapter_file": null,
42
+ "save_every": 100,
43
+ "seed": 17,
44
+ "steps_per_eval": 50,
45
+ "steps_per_report": 10,
46
+ "test": false,
47
+ "test_batches": 500,
48
+ "train": true,
49
+ "val_batches": 25
50
+ }
round07/adapters.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4acba0cc853e035f4b3bbd79fe1777bd8814841cb1dad0dd0bcaa3ab69fc6b50
3
+ size 17391108
round07/training_config.yaml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ lora_parameters:
2
+ rank: 16
3
+ dropout: 0.05
4
+ scale: 20.0
5
+ lr_schedule:
6
+ name: cosine_decay
7
+ arguments:
8
+ - 0.0001
9
+ - 1950
10
+ - 1.0e-05
11
+ warmup: 50
12
+ warmup_init: 1.0e-06