From 0bf1d52132a606946d7277d1fd2a30f9881a68a3 Mon Sep 17 00:00:00 2001 From: Janis Date: Wed, 8 Apr 2026 14:18:28 +0200 Subject: [PATCH] feat: enhance training and evaluation processes with new parameters and normalization options --- CLAUDE.md | 1 + .../scala/de/nowchess/bot/bots/nnue/NNUE.scala | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 692b8e1..81f9b3f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,6 +19,7 @@ Try to stick to these commands for consistency. | `api` | Model / shared types | (none) | | `core` | Primary business logic | api, rule | | `rule` | Game rules | api | +| `bot` | Bots and AI | api,rule,io | | `io` | Export formats | api, core | | `ui` | Entrypoint & UI | core, io | diff --git a/modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala b/modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala index 4b1b81c..5a912d3 100644 --- a/modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala +++ b/modules/bot/src/main/scala/de/nowchess/bot/bots/nnue/NNUE.scala @@ -133,8 +133,15 @@ class NNUE: for j <- 0 until 32 do output += l2Output(j) * l3Weights(j) - // Convert from sigmoid(output) back to centipawns (output is trained as sigmoid(eval/400)) - // Inverse sigmoid: eval/400 = ln(output / (1 - output)) - // But for simplicity, just scale directly: output ≈ sigmoid(eval/400), so eval ≈ 400 * (output - 0.5) * 2 - val cp = (output * 400f).toInt + // Convert from tanh-normalized output back to centipawns + // Training uses: eval_normalized = tanh(eval_cp / 300) + // Inverse: eval_cp = 300 * atanh(output) + // atanh(x) = 0.5 * ln((1 + x) / (1 - x)) + val cp = if math.abs(output) >= 0.9999f then + // Clamp for numerical stability (avoid ln of very small numbers) + if output > 0f then 20000 else -20000 + else + val atanh = 0.5f * math.log((1f + output) / (1f - output)).toFloat + (300f * atanh).toInt + math.max(-20000, math.min(20000, cp))