From 200129d16da08de21f4fb679c3b0e917b2b084cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=8B=9C=EC=9B=90?= Date: Mon, 11 May 2026 06:43:50 +0900 Subject: [PATCH] Add diagnostic value-head metrics: rmse, target stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex flagged that mcts/value_prediction_error mathematically reconciles with loss/value (MSE / value_scale^2 = 0.05) but the latter looks healthy while the former says the value head is far off. To make this clearer in W&B, expose: - mcts/value_rmse — sqrt(MSE), in raw score units (interpretable) - mcts/v_target_abs_mean — magnitude of |v_target|, indicates if game outcomes are very lopsided (always negative for a losing agent) - mcts/v_target_std — spread, low std means targets are saturated to one end (e.g., always -100ish) These let us see whether value head is failing because targets are unlearnable variance, or just hard-to-predict, or because of saturation at the value_scale=100 tanh boundary. Tests: 19/19 passing. --- src/coolrl_lost_cities/games/classic/ismcts/trainer.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/coolrl_lost_cities/games/classic/ismcts/trainer.py b/src/coolrl_lost_cities/games/classic/ismcts/trainer.py index d9cf695..e509bff 100644 --- a/src/coolrl_lost_cities/games/classic/ismcts/trainer.py +++ b/src/coolrl_lost_cities/games/classic/ismcts/trainer.py @@ -365,9 +365,15 @@ class IsMctsTrainer: with torch.inference_mode(): _logits, value_pred = self.network(info, legal) value_error = nn.functional.mse_loss(value_pred, target) + value_rmse = float(value_error.item()) ** 0.5 + target_abs_mean = float(target.abs().mean().item()) + target_std = float(target.std().item()) if target.numel() > 1 else 0.0 return { "mcts/avg_visit_entropy": float(np.mean(entropies)) if entropies else 0.0, "mcts/value_prediction_error": float(value_error.item()), + "mcts/value_rmse": value_rmse, + "mcts/v_target_abs_mean": target_abs_mean, + "mcts/v_target_std": target_std, "mcts/policy_mcts_kl": float(np.mean(policy_kls)) if policy_kls else 0.0, }