1. Prompt
我是機器人RL方向的博士生正在學習ManiSkill,在學習時我嘗試使用相同命令訓練同一個任務,但是我發現最終的 success_once 指標并不是相同的,我感到十分焦慮,
我使用的命令如下:
python sac.py --env_id="StackCube-v1" \--num_envs=32 --utd=0.5 --buffer_size=500_000 \--total_timesteps=500_000 --eval_freq=50_000 \--control-mode="pd_ee_delta_pos"
I conducted two independent training runs with the same setup. Here is a comparison of the success_once
metric at different stages:
Run 1:
success_once: 0.00, return: 2.59: 0%
...
success_once: 0.88, return: 39.84: 90%
success_once: 0.88, return: 39.84: : 500032lt [1:04:37, 132.17lt/s]
Run 2:
success_once: 0.00, return: 2.59: 0%
...
success_once: 0.31, return: 36.46: 90%
success_once: 0.31, return: 36.46: : 500032lt [43:38, 199.09lt/s]
The final success rate differs drastically (0.88 vs. 0.31).
請您瀏覽 this codebase,尤其是 sac.py,請幫我看看是什么原因導致了結果不一致呢?
2. Cursor-Gpt-5-high
我先快速在倉庫里搜一下評估時 final_info
的結構、success_once
的生成方式,以及 ManiSkillVectorEnv
的實現細節,確認是否存在評估統計上的問題或非確定性來源。接著我會并行打開這些相關實現的源碼片段以驗證假設。
[5 tools called]
我將打開并閱讀 mani_skill/vector/wrappers/gymnasium.py
的類初始化部分,確認 auto_reset
、ignore_terminations
與指標統計的具體行為,以判斷評估是否可能錯誤聚合或存在非確定性來源。
[1 tool called]
我先并行查找 BaseEnv.reset
的重置與隨機種子邏輯、enhanced_determinism
的實現,以及 StackCube-v1
任務的評估與成功判定,確認是否由環境非確定性或控制模式差異導致評估波動。隨后我會核對 sac.py
的評估循環在 GPU 向量環境下是否正確聚合 success_once
。
[6 tools called]
結論(為什么同命令兩次訓練 success_once 會差這么多)
- 訓練早期的隨機動作未被固定種子控制。
sac.py
在學習開始前用envs.action_space.sample()
探索,但沒有對action_space
本身調用seed
,Gymnasium 的Space
默認用自身的 RNG(來自 OS 隨機源),這會導致最初緩沖區的數據不同,后續學習發散,導致最終指標差異很大。 - GPU 物理仿真存在不可完全復現的數值非確定性(碰撞、接觸、并行歸約順序等)。
StackCube-v1
的成功判定包含靜止判定與非常小的幾何容差;微小數值差異會放大為“某一輪成功/未成功”的不同,進一步影響采樣和學習軌跡。 - 評估環境每次
reset
(默認eval_reconfiguration_freq=1
)都會重新隨機對象位姿;盡管這對于公平評估是需要的,但它會使單次評估更敏感于策略的細微差別,從而放大不同 run 之間的差異。 - 兩次運行的訓練速度差異很大(64min vs 43min),說明系統負載/調度不同;在 GPU 物理和大批量并行時,這種差異也會輕微改變浮點執行順序,從而進一步增加非確定性。
直接可改的最關鍵點
- 固定 Gymnasium
action_space
的隨機源(最重要,成本最低,收益最大):
if isinstance(envs.action_space, gym.spaces.Dict):envs = FlattenActionSpaceWrapper(envs)eval_envs = FlattenActionSpaceWrapper(eval_envs)envs.action_space.seed(args.seed)eval_envs.action_space.seed(args.seed + 1)if args.capture_video or args.save_trajectory:eval_output_dir = f"runs/{run_name}/videos"if args.evaluate:eval_output_dir = f"{os.path.dirname(args.checkpoint)}/test_videos"print(f"Saving eval trajectories/videos to {eval_output_dir}")
進一步提升復現性的建議
- 將評估(至少評測時)切到 CPU 物理后端,或訓練也統一 CPU 后端(速度會慢,但更穩定):
- 運行時傳
--env_vectorization=cpu
或在創建環境時設置sim_backend="physx_cpu"
并將num_envs=1
(CPU 模式不支持多并行)。
- 運行時傳
- 若必須用 GPU:
- 保持固定
--seed
,并固定action_space.seed
(如上)。 - 避免在同機上并發其它重負載任務,盡量減少運行時抖動。
- 可將評估步數/回合數加大(例如把
num_eval_envs
或num_eval_steps
提高),用均值稀釋單次隨機性。
- 保持固定
- 若希望評估更穩定、對初始化不太敏感,可暫時設
--eval_reconfiguration_freq=0
(減少每次評估的對象重隨機),但要注意這會降低評估的隨機覆蓋面,長期應使用1
。
你看到的現象如何對應到上述點
-
兩次 run 的
success_once
差異巨大,且 walltime 差異明顯,符合“早期隨機軌跡不同 + GPU 物理非確定性”疊加放大的模式。 -
sac.py
里已經固定了 Python/NumPy/PyTorch 的種子,但沒有固定 Gymaction_space
的種子,這是最直接的缺口。 -
如需我直接幫你把
sac.py
加上action_space.seed
、并提供一個更“穩健評估”的命令行(CPU/GPU 兩版),我可以順手改好并給出完整命令。 -
小提示:你命令里的
--control-mode
映射到Args.control_mode
是可以的;保持與訓練/評估端一致即可。 -
若要嚴格科研可復現,建議最終報告同時給出多種子均值/方差,并在附錄說明 GPU 物理的不可完全確定性。
-
如果修復后你仍看到顯著波動,可以把評估階段切到 CPU 物理或增加評估覆蓋度;這兩招基本能穩定到小方差區間。
-
需要我繼續把評估改成“CPU-only”(只在評估時切 CPU)并給出對應命令嗎?
-
最后提醒:默認
capture_video=True
會拖慢訓練速度且引入 I/O 抖動,如果不需要視頻,可加--capture_video=False
提升穩定性。