fix(dashboard): add alpha temperature to training losses panel

This commit is contained in:
2026-08-24 09:10:46 +02:00
parent 8eb7c53dd0
commit 8872be3ff6
2 changed files with 123 additions and 116 deletions
+15 -9
View File
@@ -5,7 +5,7 @@ Pure-stdlib SVG output (matplotlib not available on this box).
Generates ONE file:
docs/campaign_dashboard.svg - four panels, current (v2) run only:
1. test-match win % vs opponents (campaign_v4_stdout.log eval lines)
2. critic_loss / |actor_loss| (training_metrics.jsonl, shared log-y)
2. critic_loss / |actor_loss| / alpha (training_metrics.jsonl, shared log-y)
3. alpha temperature (training_metrics.jsonl, linear)
4. throughput, games/hour buckets (training_metrics.jsonl 'epoch' deltas;
1 metrics row == one 10-game chunk,
@@ -36,6 +36,7 @@ GAMES_PER_ROW = 10 # one training_metrics.jsonl row per 10-round chunk
COLORS = {"Corners": "#d62728", "Crazy": "#1f77b4", "Target": "#2ca02c",
"RamFire": "#ff7f0e", "SacTwin": "#9467bd"}
CRITIC_C, ACTOR_C = "#1f77b4", "#ff7f0e"
ALPHA_C = "#9467bd" # same purple as the dedicated alpha panel
RELOAD_JS = ('<script type="text/javascript"><![CDATA[ '
'setTimeout(function(){ location.reload(); }, 60000); ]]></script>')
W, H = 1400, 1720
@@ -51,7 +52,7 @@ ROWS = {
}
PANEL_TITLES = [
"Test matches - win % vs opponents",
"Training losses (log scale)",
"Training losses & alpha (log scale)",
"Alpha temperature",
"Throughput - games per hour",
]
@@ -285,11 +286,12 @@ def panel_losses(rows, geo):
critic = metric_col(rows, "critic_loss", positive=True)
actor = metric_col(rows, "actor_loss") # abs() applied; sign dropped
actor = [(i, v) for i, v in actor if v > 0]
if not (critic or actor):
alpha = metric_col(rows, "alpha")
if not (critic or actor or alpha):
s += f'<text x="{x0 + 10}" y="{pt + 40}" font-size="12" fill="#a00">' \
"no valid loss points</text>\n"
return
allv = [v for _, v in critic + actor]
allv = [v for _, v in critic + actor + alpha]
lo, hi = math.floor(math.log10(min(allv))), math.ceil(math.log10(max(allv)))
if lo == hi:
hi = lo + 1
@@ -301,8 +303,11 @@ def panel_losses(rows, geo):
ticks_log(lo, hi, pb, pt), "metric line number", "loss (log)")
s += polyline([(xm(i), ym(v)) for i, v in critic], CRITIC_C, 1.8)
s += polyline([(xm(i), ym(v)) for i, v in actor], ACTOR_C, 1.8)
s += legend([(CRITIC_C, "critic_loss"), (ACTOR_C, "|actor_loss|")],
x0 + 12, pb + 52)
s += polyline([(xm(i), ym(v)) for i, v in alpha], ALPHA_C, 1.8)
items = [(CRITIC_C, "critic_loss"), (ACTOR_C, "|actor_loss|")]
if alpha:
items.append((ALPHA_C, "alpha"))
s += legend(items, x0 + 12, pb + 52)
return s
def panel_alpha(rows, geo):
@@ -435,14 +440,15 @@ def selftest():
ET.fromstring(text) # whole doc must parse -> closing tag present
assert RELOAD_JS in text, "auto-reload script missing"
for t in PANEL_TITLES:
assert t in text, f"panel title missing: {t}"
assert esc(t) in text, f"panel title missing: {t}"
assert text.count(PANEL_TITLES[0]) == 1
assert "How to read" in text, "reading guide missing"
assert 'width="1400"' in text and 'height="1720"' in text
# circles: 4 eval dots (panel 1) + 2 throughput rate dots (panel 4)
assert text.count("<circle") == 6, text.count("<circle")
# 2 trends + 2 losses + 1 alpha + 1 throughput
assert text.count("<polyline") == 6, text.count("<polyline")
# 2 trends + 3 losses-panel polylines (critic, actor, alpha)
# + 1 dedicated alpha panel + 1 throughput
assert text.count("<polyline") == 7, text.count("<polyline")
# orientation guard: a known rising series (10% -> 90%) rendered through
# the FULL build path must plot upward (smaller SVG y) and forward in