FC Emulator Toolkit 基于 nes-py 搭建,围绕 NES 红白机环境提供从 ROM 加载、Gymnasium 封装、策略库、训练脚本到日志分析的一体化工作流。近期重构聚焦于环境抽象、探索机制、诊断与日志分析,使在经典游戏上的强化学习实验更加稳定、易于复现与调试。
- 模块化环境封装:
fc_emulator.rl_env内置AutoStartController、全新的StagnationMonitor与RewardConfig,支持动态停滞阈值、score_loop检测以及stagnation_idle_frames指标,环境信息会同步写入info.metrics。 - 动作与探索解耦:动作模板、图像处理与宏动作探索分别位于
actions.py、observation.py、exploration.py,wrappers.py仅提供兼容入口,便于自定义策略组合。 - 结构化训练配置:
train.py通过TrainingConfig统一封装环境、算法、探索与日志参数,自动导出runs/run_config.json以复现实验,新增 CLI 选项可调整诊断频率与停滞策略。 - 在线诊断回调:
DiagnosticsLoggingCallback周期性输出平均前进距离、热点位置、停滞原因比例与内在奖励均值到 TensorBoard(diagnostics/*),EpisodeLogCallback则持续落地 JSONL。 - 增强日志分析:
fc_emulator.analysis支持热点分桶、停滞原因分布、近期窗口统计以及--json输出,可在不加载全部数据的情况下快速审阅大规模日志。
fc_emulator/
├── actions.py # 离散动作模板与包装器
├── auto_start.py # 标题画面自动跳过控制
├── exploration.py # 宏动作与热点驱动探索包装
├── observation.py # 图像缩放与帧堆叠包装
├── stagnation.py # 停滞检测、score_loop 识别
├── rl_env.py # NESGymEnv 主循环
├── rl_utils.py # 向量化环境与算法映射
├── callbacks.py # 训练回调(日志、诊断、熵/ε 调度)
├── analysis.py # JSONL 日志分析工具
├── train.py / infer.py # 训练与推理入口
└── wrappers.py # 向后兼容的聚合入口
要求 Python ≥ 3.10,推荐使用虚拟环境:
pip install -e . # 仅运行模拟器 / CLI
pip install -e .[rl] # 启用强化学习(Stable-Baselines3、Gymnasium 等)
# 若需图像缩放,可额外安装 pillow 或 opencv-pythonpython -m fc_emulator.cli --rom roms/SuperMarioBros.nes默认按键:WASD(方向)、J(A)、K(B)、Enter(Start)、Right Shift(Select)。
python -m fc_emulator.train --rom roms/SuperMarioBros.nes \
--algo ppo --total-timesteps 1000000 --num-envs 6 --vec-env subproc \
--frame-skip 4 --frame-stack 4 --reward-profile smb_progress \
--observation-type gray --diagnostics-log-interval 2000常用参数:
--observation-type:rgb/gray/ram/rgb_ram/gray_ram--resize H W:送入策略前的降采样尺寸(如--resize 84 84)--action-set:预设动作(default、simple、smb_forward)或自定义组合"RIGHT;A,RIGHT;B"--exploration-*:配置 epsilon 衰减以及宏动作探索强度--entropy-*:通过EntropyCoefficientCallback线性衰减策略熵系数--reward-profile:none/smb_progress/smb_dense--rnd:启用随机网络蒸馏内在奖励(默认共享策略编码器)--diagnostics-*:控制诊断日志频率、窗口长度以及热点分桶
训练流程会自动:
- 在
runs/run_config.json存储完整配置以便复现。 - 如存在断点,自动加载最新
ppo_agent_*.zip。 - 将诊断指标写入 TensorBoard,并在 JSONL 中记录每个 episode 的奖励、停滞信息与
stagnation_idle_frames。
python -m fc_emulator.infer --rom roms/SuperMarioBros.nes \
--model runs/ppo_agent_XXXXXX.zip --observation-type gray \
--frame-stack 4 --episodes 3 --deterministicEpisodeLogCallback默认写入runs/episode_log.jsonl,记录基础奖励、塑形奖励、内在奖励、停滞原因以及stagnation_idle_frames。DiagnosticsLoggingCallback会把平均mario_x、近期均值、热点位置、停滞原因占比与内在奖励均值写入 TensorBoard(diagnostics/*)。fc_emulator.analysis提供热点分桶、停滞原因统计、近期窗口指标与--json输出:python -m fc_emulator.analysis runs/episode_log.jsonl --bucket-size 32 --top 10 python -m fc_emulator.analysis runs/episode_log.jsonl --json
fc_emulator.hotspot_monitor可持续轮询 JSONL 日志,实时输出热点分布、停滞与终止占比,适合训练中监控:python -m fc_emulator.hotspot_monitor --log runs/monitor_run_v2/episode_log.jsonl --bucket-size 32 --top 8 --oneshot python -m fc_emulator.hotspot_monitor --log runs/monitor_run_v2/episode_log.jsonl --poll-interval 10
针对 12 线程 CPU、11GB 显存 RTX 2080 Ti 与 40GB RAM,我们推荐如下组合:
# PPO + RND baseline
python -m fc_emulator.train --rom roms/SuperMarioBros.nes \
--algo ppo --policy-preset baseline \
--total-timesteps 1200000 --num-envs 6 --vec-env subproc \
--frame-skip 4 --frame-stack 4 --resize 84 84 \
--reward-profile smb_progress --observation-type gray \
--n-steps 768 --batch-size 192 \
--rnd --rnd-scale 0.2 --rnd-lr 5e-5 \
--stagnation-frames 900 --stagnation-progress 1 \
--stagnation-bonus-scale 0.15 --stagnation-idle-multiplier 1.1 \
--stagnation-backtrack-penalty 1.5 \
--exploration-epsilon 0.08 --exploration-final-epsilon 0.02 --exploration-decay-steps 3000000 \
--entropy-coef 0.02 --entropy-final-coef 0.0045 --entropy-decay-steps 3000000 \
--checkpoint-freq 200000 --diagnostics-log-interval 2000 \
--best-checkpoint best_agent.zip --best-metric-key mario_x --best-metric-mode max --best-window 30 --best-patience 6 --best-min-improve 1.0 \
--episode-log episode_log.jsonl
# RecurrentPPO + IMPALA 残差基线
python -m fc_emulator.train --rom roms/SuperMarioBros.nes \
--algo rppo --policy-preset impala_lstm \
--total-timesteps 1200000 --num-envs 6 --vec-env subproc \
--frame-skip 4 --frame-stack 4 --resize 84 84 \
--reward-profile smb_progress --observation-type gray \
--n-steps 512 --batch-size 128 \
--rnd --rnd-scale 0.2 --rnd-lr 5e-5 \
--stagnation-frames 900 --stagnation-progress 1 \
--stagnation-bonus-scale 0.15 --stagnation-idle-multiplier 1.1 \
--stagnation-backtrack-penalty 1.5 \
--exploration-epsilon 0.08 --exploration-final-epsilon 0.02 --exploration-decay-steps 1500000 \
--entropy-coef 0.02 --entropy-final-coef 0.0045 --entropy-decay-steps 3000000 \
--checkpoint-freq 200000 --diagnostics-log-interval 2000 \
--best-checkpoint best_agent.zip --best-metric-key mario_x --best-metric-mode max --best-window 30 --best-patience 6 --best-min-improve 1.0 \
--episode-log episode_log_rppo.jsonl推荐理由:
num_envs=6+n_steps=512~768平衡采样吞吐与显存占用,适合单卡 11GB 环境。--rnd默认携带独立的轻量 CNN 编码器,内部归一化 + 较低 scale(0.2)可避免内在奖励压制外在信号;若需共享编码器,可传入--rnd-shared-encoder(见 CLI 参数)。stagnation-frames≈900在起始关卡给出更多穿越时间,配合宏动作探索更稳;如遇刷分,可再调大--stagnation-bonus-scale或引入热点惩罚。- 使用 IMPALA 残差 + LSTM 时请搭配
--algo rppo,并确保 rollout/batch 序列对齐以满足 RecurrentPPO 的隐藏态要求。 exploration/entropy衰减延长至 300 万步,利用热点持久化策略逐步降低随机性但保留宏动作注入窗口。stagnation-frames=720搭配持久化热点与score_loop监测,让宏动作有尝试空间同时快速截断刷分循环。checkpoint-freq=1000000与频率更高的诊断刷新(2000)确保能观察热点分布与stagnation_reason变化并及时回滚。
欢迎通过 Issue / PR 反馈需求,共同完善 FC Emulator Toolkit。
- 通过
--best-checkpoint best_agent.zip启用最优模型保存;默认以最近 20 个 episode 的mario_x平均值衡量表现,并在连续 5 个窗口无改进时回退到最佳权重继续训练。 - 可使用
--best-metric-key、--best-metric-mode(mean/max)、--best-window、--best-patience、--best-min-improve灵活控制最优模型的评估方式与灵敏度。 - 最优模型文件存放在
log_dir下指定路径,可与常规 checkpoint 配合使用,便于快速回溯。
- 近期问题、实验结果与后续计划已迁移至
docs/UPDATE_LOG.md,请在更新诊断信息或实验结论时同步维护该文件。 - 关于未来网络重构与替代架构的调研,请参阅
docs/NETWORK_RESEARCH.md。