fix(PPO_Bot): radar oscillation, Adam persistence, checkpoint order, channel race
- enemy_tracker: toggle lastOvershootDir each tick; make getRadarTurnRate take var tracker - training: remove threadvar Adam globals; pass adamStates as var param to ppoUpdate; export ACAdamStates - PPO_Bot: carry ACAdamStates through TrainingArgs/TrainingResult; drop trainingDone bool and Lock — use resultChan.tryRecv() directly as synchronisation - weights: sort checkpoint dirs newest-first by mtime instead of hardcoded order - tests/test_training: pass explicit ACAdamStates to ppoUpdate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+15
-6
@@ -1,6 +1,6 @@
|
||||
## weights.nim — save/load ActorCritic weights as .npy files.
|
||||
|
||||
import std/[os, times, strutils]
|
||||
import std/[os, times, strutils, algorithm, sequtils]
|
||||
import arraymancer
|
||||
import ./network
|
||||
|
||||
@@ -70,12 +70,21 @@ proc saveCheckpoint*(ac: ActorCritic, weightsRoot: string, roundNum: int) =
|
||||
saveWeightsAtomic(ac, weightsRoot / ("checkpoint_" & $slot))
|
||||
|
||||
proc loadBestAvailable*(ac: var ActorCritic, weightsRoot: string): bool =
|
||||
## Try latest/, then checkpoint_3/, checkpoint_2/, checkpoint_1/.
|
||||
## Try latest/ first, then checkpoints sorted newest-first by mtime.
|
||||
## Returns true if weights loaded, false if all fail (random init stays).
|
||||
for candidate in [weightsRoot / "latest",
|
||||
weightsRoot / "checkpoint_3",
|
||||
weightsRoot / "checkpoint_2",
|
||||
weightsRoot / "checkpoint_1"]:
|
||||
let checkpoints = [weightsRoot / "checkpoint_1",
|
||||
weightsRoot / "checkpoint_2",
|
||||
weightsRoot / "checkpoint_3"]
|
||||
# Sort checkpoints newest-first by modification time
|
||||
var existing: seq[tuple[mtime: Time, path: string]]
|
||||
for p in checkpoints:
|
||||
if dirExists(p):
|
||||
existing.add((getLastModificationTime(p), p))
|
||||
existing.sort(proc(a, b: tuple[mtime: Time, path: string]): int =
|
||||
cmp(b.mtime, a.mtime)) # descending
|
||||
|
||||
let candidates = @[weightsRoot / "latest"] & existing.mapIt(it.path)
|
||||
for candidate in candidates:
|
||||
if dirExists(candidate):
|
||||
var ok = true
|
||||
for f in weightFiles:
|
||||
|
||||
Reference in New Issue
Block a user