diff options
| author | Scott Gasch <[email protected]> | 2026-10-20 09:26:44 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-20 09:26:44 -0700 |
| commit | c8c6bbc2c1a103e5b07b079a0f8bdf66c7724d80 (patch) | |
| tree | b6c2137c9ac577fa83b1e948fa0311d53dfe445d /annotate_pgns/extract_positions.py | |
| parent | 3b5d3677bb14ae14728a1c4b221176bb83667d92 (diff) | |
Wire NNUE eval into search, build the training pipeline, and add a fast
move/eval-agreement benchmark against Stockfish (tests/lop)
Implements the architecture decisions in src/docs/NNUE.md: HalfKAv2_hm
feature set, int16/int8 quantization, per-ply accumulator backup for
king moves, and a lazy-eval-ready integration into search.c/eval.c.
Adds the full annotate_pgns/ training pipeline (extraction, K-fit/
labeling, quiet filtering, tensor building, training, export) plus an
end-to-end orchestrator (run_nnue_pipeline.py) and validation tooling
(sanity_check_net.py, compare_vs_stockfish_net.py). Adds tests/lop:
a 10k-position list-of-positions benchmark comparing engine eval rank
and move choice against pre-computed Stockfish/lc0 references, much
cheaper than a full self-play match for day-to-day progress checks.
First sd10-matched self-play result against classic HCE: LLR +2.28
(H1=+2.94), -72=119+169 over 360 games, confirming the net is
"smarter per node" at matched depth. A real-time (--st 4) match is
currently weaker (candidate loses ~3 plies of depth to a ~3.3-3.7x
nps gap against an unrecalibrated search), consistent with
NNUE.md's adoption-criterion section -- pruning/reduction constants
still need retuning for the new eval's score scale before a fair
real-time comparison is possible.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'annotate_pgns/extract_positions.py')
| -rw-r--r-- | annotate_pgns/extract_positions.py | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/annotate_pgns/extract_positions.py b/annotate_pgns/extract_positions.py index 539419a..507f956 100644 --- a/annotate_pgns/extract_positions.py +++ b/annotate_pgns/extract_positions.py @@ -132,6 +132,19 @@ def main(): } if reason: rec["exact_reason"] = reason + # Mover-relative exact outcome, straight from the sign + # of the already-mover-relative score (unlike + # extract_selfplay_positions.py's foreign-engine path, + # typhoon's own "score" field here is never nulled out + # for mate/EGTB/REC rows -- only "only" (unsearched) and + # genuinely unparseable tokens carry no usable score). + # draw_recognizer ("<=>") is 0.5 regardless of sign. + if exact and reason == "draw_recognizer": + rec["r_outcome"] = 0.5 + elif exact and score is not None and reason not in ( + "unsearched_only_move",) and not ( + reason and reason.startswith("unrecognized")): + rec["r_outcome"] = 1.0 if score > 0 else 0.0 out.write(json.dumps(rec) + "\n") total += 1 if exact: |
