Train a PPO agent (SB3) for Atari tasks (Ms. Pacman, Amidar, Qbert) with a recovery mechanism:
- Detect when policy behavior is stuck in a local loop.
- Temporarily switch to heuristic recovery (RTHS-style action fallback).
- Return control to PPO once recovery is reached.
World-model style representation learning inspired by PPGS:
- Encoder
h_theta: observations_t-> 16D hyperspherical latentz_t. - Forward model
f_phi: predictsz_{t+1}from(z_t, a_t). - Inverse model
p_omega: predictsa_tfrom(z_t, z_{t+1})to reduce latent collapse.
Atari environments include moving distractors even when agent position is unchanged.
Main hypothesis: enforce NOOP invariance in latent space.
- Standard margin-style separation can overreact to distractor motion.
- Modified behavior: when action is
NOOP, push||z_{t+1} - z_t||^2 -> 0. - Intended effect: latent features track controllable state changes, not distractor-only motion.
- PPO acts normally.
- Latent trajectory is monitored for short-horizon stagnation/oscillation ("stuck").
- If stuck, fallback policy iterates through ranked PPO action alternatives until progress.
- Resume PPO after recovery signal.
compare_rths.py: Compares subopt vs main policies, vanilla vs RTHS, using raw episodic return frominfo["raw_ep_return"](unclipped ALE score), not SB3evaluate_policyclipped rewards. Supports--render(passesrender_mode="human"throughmake_eval_env, same pattern asgames/*/eval.py).- Warmup / false positives: For the first
Nenv steps per episode (--start-tracking-step), RTHS does not override the policy and does not updateLatentStateTracker. If the flag is omitted,Ndefaults to the same counts as manual-play post-reset warmup —DEFAULT_WARMUP_NOOPS_BY_GAMEinrths/env/wrappers.py: qbert 39, pacman 66, amidar 12. Use0for immediate RTHS (legacy). run_rths_policy.py: Same semantics ascompare_rths.pyfor--start-tracking-step.
DEFAULT_WARMUP_NOOPS_BY_GAME in rths/env/wrappers.py: qbert 39, pacman 66, amidar 12. Used by debug/manual_play_atari.py, debug/demo_action_sequence.py, and (when omitted) --start-tracking-step in compare_rths.py / run_rths_policy.py. Ms. Pac-Man: 66 post-reset NOOPs so the 67th env step is the first where directional input lines up with intent.
Observed with make_eval_env + SDL manual control (debug/manual_play_atari.py); full detail: debug/qbert_manual_play_timing.md.
- ~39 NOOP
env.steps after reset for Q*bert: playfield / sprites / HUD tend to fully appear and inputs feel trustworthy (same as default warmup above). - Trailing NOOPs after each key (Q*bert):
debug/manual_play_atari.pydefaults to--noop-after-action 10for--game qbert(action first, then 10 NOOPs — a cooldown so the next key lines up with what you see; Q*bert feels sluggish / desynced without it). Use--noop-after-action 0to try raw one-step-per-key. - Pac-Man / Amidar: default
--noop-after-action 0. Control feels immediate on the action step; extra trailing NOOPs are not needed for that Q*bert-style alignment. (EachNOOPis still neutral input and advances the env; on Pac-Man you often still see motion during those steps because the game keeps moving along corridors until a wall or turn—not because the API repeats the last action.)
Trailing --noop-after-action (per key, Q*bert-only default) is not the same thing as RTHS delay or post-reset warmup. Not a change to PPO’s per-step action semantics—those remain one action per step.
- Keep this file concise and durable (what/why/current direction).
- Move ephemeral experiment details to the tracker below instead of expanding sections above.
- [2026-03-21] Type: Change
Env/Setup: Repo layout.
What changed: Moved
manual_play_atari.py,demo_action_sequence.py,manual_play_log.jsonl, andnotes/qbert_manual_play_timing.md→debug/(debug/README.md). Path logic indebug/manual_play_atari.pyresolves repo root whether the script lives at repo root or underdebug/.agent_context.mdandrths/env/wrappers.pycomment updated. Observation: Run asuv run python debug/manual_play_atari.pyfrom repo root. Next action: — - [2026-03-20] Type: Change
Env/Setup: RTHS eval (
compare_rths.py,run_rths_policy.py). What changed:DEFAULT_WARMUP_NOOPS_BY_GAMEinrths/env/wrappers.py(qbert 39, pacman 66, amidar 12). Manual play / demo import it;--start-tracking-stepdefaults toNoneand resolves to that map per--gamewhen omitted.README.md/agent_context.mdupdated. Observation: RTHS “kick-in” step count aligned with empirical post-reset readiness (same as--warmup-noopsdefaults). Next action: Override per experiment with explicit--start-tracking-stepif needed. - [2026-03-20] Type: Result
Env/Setup: Ms. Pac-Man manual SDL;
make_eval_envstack. What changed: Default--warmup-noopsfor--game pacmanset to 66 indebug/manual_play_atari.pyanddebug/demo_action_sequence.py(responsive from cumulative step 67; was briefly 150 / 67 during tuning).agent_context.md— “Manual play / demo warmup” section updated. Observation: 66 warmup NOOPs → first trustworthy directional step at 67. Next action: Tune if a different ROM/wrapper combo needs a different count. - [2026-03-20] Type: Result
Env/Setup: Q*bert manual SDL play;
make_eval_envstack. What changed: Addeddebug/qbert_manual_play_timing.md(warmup ~39; Q*bert default--noop-after-action 10indebug/manual_play_atari.py; later moved with other harnesses underdebug/). Linked under “Q*bert human-play timing”. Observation: Human-facing boot/spacing differs from PPO’s one-action-per-step training. Next action: Keep RTHSstart-tracking-stepseparate unless experiments tie them. - [2026-03-20] Type: Result
Env/Setup: RTHS eval UX and early-episode false positives (esp. Q*bert).
What changed:
compare_rths.py— added--render; added--start-tracking-step(default5) and gated RTHS override +record_actionuntilstep >= Nper episode (aligned withrun_rths_policy.py).run_rths_policy.py— default--start-tracking-stepchanged from0to5, help text expanded.README.md— documented warmup,compare_rths--render/--start-tracking-step, andrun_rths_policywarmup note. Observation: Priorcompare_rthspath recorded latents from step 0, so spurious “loops” at spawn could force a bad second-choice action; warmup defers RTHS until a few policy steps have executed. Next action: TuneNper game if needed; consider documenting raw vs clipped reward distinction next togames/*/eval.pyif confusion recurs. - [2026-03-04] Type: Attempt Env/Setup: Context doc restructuring. What changed: Added persistent tracker for bugs/issues/attempts related to distractor-invariant encoder work. Observation: No experiment result recorded yet. Next action: Add concrete entries after each training/eval run (metrics + failure mode).
- [2026-03-04] Type: Result
Env/Setup: Refactor and tooling updates across Pacman/Amidar/Qbert latent workflow.
What changed: Added offline dataset generation (
generate_data.py) with PPO rollouts, 8 parallel env support, tqdm progress, NOOP/random action mixing (5%/5%), and reward logging in dataset. Reworked alltrain_latent.pyscripts to train from.pkldatasets (no rollout collection), added pre-training visual dataset sanity checks (5 samples, NOOP-forced final sample), and added training progress bars. Updated save paths so checkpoints land in bothmodels/latent/and model-specific folders (models/encoder,models/forward,models/inverse). Added legacy checkpoint compatibility shim (impala.py) so old PPO zips load after module moves. Observation: LegacyModuleNotFoundError: impalaissue is resolved; latent checkpoints now appear in per-model folders as expected. Next action: Run comparative latent training sweeps and evaluate loop-recovery behavior using the updated offline dataset pipeline. - [2026-03-16] Type: Attempt
Env/Setup: Hyperparameter study for loop detection false-negative reduction.
What changed: Created
run_hyperparam_study.py— full Optuna-based HPO pipeline that sweeps latent model training params (lr, margin, loss weights, latent_dim, hidden dims, batch size, epochs, updates_per_epoch) and jointly evaluates loop-detection thresholds. Uses NOOP reidentification rate as primary false-negative proxy, combined with inverse accuracy, forward MSE, and margin satisfaction into a composite score weighted 40% toward recall. Monitoring: Optuna SQLite + optuna-dashboard (local web UI), TensorBoard per-trial curves, JSON per-trial logs. Addedoptunatopyproject.tomldeps;optuna-dashboardis optional ([dashboard]extra). Observation: Script imports clean, CLI tested, no lint errors. Awaiting dataset generation before first run. Next action: Generate dataset withgenerate_data.py, runrun_hyperparam_study.py, analyze best config and false-negative rates. Later: add orientation-aware loop detection.