Repository navigation
laya: tools/laya_finetune, the routing head's CPU fine-tune over --dump-encoder dumps, with before/after on the game (Refs #1313) - #2117
Conversation
…mp-encoder dumps, with before/after on the game (Refs #1313) Item 3 of engine #1313, the only engine item left (audit on the issue): a head-only fine-tune of Laya's routing head (type_emb, two head layers, scorer; encoder frozen) on the CPU, over the dumps `1bit route --dump-encoder` already writes. The output is an ordinary --laya-model dir: only the head tensors' bytes change, the temperature is refit on dev (kept when the refit hits the grid's edge), finetune.json records the run. metrics.py reads --per-case files with laya/eval.cpp's definitions. Measured on the game's logged decisions, episodes held out whole (base / fine-tuned): test 33/33 of 39, log loss 0.543/1.395; test2 107/106 of 110, 0.478/0.294; test3 55/55 of 56, 0.475/0.188. A failed-reflex outcome label taught nothing (0/10 held-out rows moved) and is documented as such. tests/laya_finetune_test.py (ctest laya_finetune, skip 77 without torch): synthetic checkpoint + dump; dev log loss 0.676 -> 0.002, accuracy 0.688 -> 1.000; every non-head byte identical; refuses an existing --out; metrics.py against a hand-computed per-case file. 14/14. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
ready for review at d371d01 |
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at d371d01: READY
The laya_finetune package (head.py, metrics.py, train_head.py) with its test registered, and — the detail I look for — if(Python3_Interpreter_FOUND) plus SKIP_RETURN_CODE 77, so on a machine without an interpreter the row reports skipped rather than quietly doing nothing or failing for the wrong reason.
Splitting head/metrics/train means the routing accuracy metric can be driven on its own, which is what makes a fine-tune claim checkable: "routing accuracy went from A to B" is only worth the metric's correctness, and the metric now has a unit.
Together with #2112 this is #1313's demo path: one tool fits, the other scores, and both halves come from the same dump.
|
VERDICT: READY at Why this is the right shape for a demo blocker
Two things to pin, both about reproducibility
And, since this is "the only engine item left" on a blocker row: say explicitly what remains after it, so the row's lead can see the end from here. |
|
VERDICT: READY at Why this verdict exists when one already does: the earlier READY says "at On the content, the three things I checked because they decide whether the number this produces means anything:
Not claimed by this verdict: that the fine-tune improves routing. The PR's own wording is "item 3, the only engine item left" for |
Refs #1313. This is item 3, the only engine item left; see the audit on the issue and the claim right after it.
What
tools/laya_finetune/is a head-only fine-tune of Laya's routing head on the CPU, over the dumps1bit route --dump-encoderalready writes (docs/laya-models.md, "Measuring and fine-tuning the router").head.py: the head oflaya/scorer.cppin torch (type_emb, two pre-norm encoder layers, the option markers,scorer). The encoder is frozen; its output is in the dump.train_head.py: trains on Laya's proper reward (log score + 0.5 spherical), class-weighted, with early stopping on dev log loss. Then it refits thechoice:ktemperature on dev, keeping the checkpoint's own when the refit hits the grid edge. It writes a copy of the--laya-modeldir with only the head tensors' bytes replaced, plusfinetune.json. It refuses an existing--out.metrics.py: accuracy, ECE, log loss and decision p50 from--eval --per-casefiles, withlaya/eval.cpp's definitions.Serve takes the result unchanged:
--laya-model NEW_DIR.Measured on the game
The labels are the step kind each logged decision was made for, and whole episodes are held out:
Accuracy is unchanged. The router is much surer on the game's own steps. On the hand-written
testset it is overconfident on its misses, and the docs say so.I also tried an outcome label: a failed reflex step labelled as plan. It taught the head nothing (0 of 10 held-out rows moved), because the failure is not visible in the reflex state. The docs record that too.
This fine-tuned router (ft2) is the one in tonight's game runs. ep015 finished wood → iron → furnace → shelter → survive the night: 11 goals, 1174 s, 0 deaths. The footage stays private (owner hold).
Tests
tests/laya_finetune_test.pyis ctestlaya_finetune. It needs no checkpoint and no device, and skips with 77 when torch or numpy is missing.choice:2, and an existing--outis refused.Result: 14/14. Wall time on this box was 4m40, almost all of it thermal-run pauses; it used 15 s of CPU.
Local checks:
tools/copyright.py --checkpasses (rc 0, run with the new files staged).python_test_order_check,tests_referenced_checkandci_targets_checkare all OK.🤖 Generated with Claude Code