返回专辑
·Johan·4 分钟阅读

MDP 五元组:写代码前先对齐任务

把任务写成 (S,A,P,R,γ) 再选算法,能避免 reward 单位、episode 边界和马尔可夫性上的 silent bug。

MDP 五元组:写代码前先对齐任务

1. Reward 突然全负,episode 永远 1000

机械臂 sim 里 reward 突然全负、episode 长度永远 1000,十有八九是 terminated 和 truncated 混用,或者状态里缺了关键量。写 RL 代码前,我习惯先把任务写成 MDP 五元组 (S, A, P, R, gamma),和 Gymnasium 环境文档对一遍。非马尔可夫状态(例如只给当前关节角、不给速度)会导致策略学不动。reward 单位搞错(毫米当米)会让 value 网络数值爆炸。Sparse reward 且 horizon 很长时,random policy 的 return 应接近 0 或略负——若 random 已经很高,先查 reward 是否被 truncate 刷分。

2. 五元组逐项对齐

状态 S:agent 每一步看到什么?关节角、速度、目标位姿是否都在 obs 里?若当前 obs 不足以决定最优动作,问题就不是 MDP,而是 POMDP——后面要 stack 帧或加 RNN。Velocities 隐藏、只有 position 是经典例子;与其立刻上 RNN,我通常先试 stack 四帧,成本低很多。动作 A:离散还是连续?物理单位是位置、速度还是力矩?action_space 的 low/high 必须和底层控制器一致。

转移 P:仿真器是否 deterministic?随机种子固定后 rollout 是否可复现?回报 R:每步 reward 的定义、量纲、稀疏还是稠密,写进 README。reward scale 直接影响 Q 值范围和合适的学习率。折扣 gamma:有限 horizon 任务常用 gamma 小于 1。Return 定义为折扣奖励之和。

3. Gymnasium 边界契约

env.step 返回 obs, reward, terminated, truncated, info。terminated 为真表示任务真结束(机器人倒地);truncated 为真通常是 TimeLimit 截断。旧代码 done 等于 terminated 或 truncated 在算 bootstrap 时要把两者分开:terminated 处下一状态价值应为 0;truncated 是否仍 bootstrap 下一状态价值要和算法实现一致(SB3 对 timeout 常仍 bootstrap)。切忌把 truncated 当成真终止去清零 bootstrap:这和 SB3 默认行为不一致时,value target 会系统性偏一截。

Monitor 记录的 return 是否包含 truncated 那步的 reward?bootstrap 是否用了 truncation 后的 obs?Episode 边界还要和日志对齐。这些细节不对,曲线能跑但 value 学歪,表现成「critic loss 降了但 policy 不动」。

4. 开训前三条短轨迹

同一 seed 下各跑几百步:random action、zero action、以及若环境提供的 scripted controller。把 return 和 episode length 记进 README 首页,以后每次改 wrapper 或 reward 都先重复这三条。HalfCheetah 上 random return 大约负二百是常见量级;若 random 已经接近 expert,先查 reward 是否被 TimeLimit 或 shaping 刷高。马尔可夫性快速自检:固定同一物理状态,历史不同但 obs 相同,看最优动作是否应相同。

5. 与 SB3 和 Monitor 对接

gymnasium.make 之后,打印 observation_space 和 action_space,确认 dtype 和 shape。SB3 的 Monitor wrapper 会把 episode return 写进 info episode,方便和 random baseline 对比。若自己写训练循环,切忌把 truncated 当成真终止去清零 bootstrap。写 README 时至少记录:每步 reward 公式、episode 上限、terminated 触发条件、obs 各维物理含义。换同事接手或隔月复现实验,这些比「用了 PPO」更重要。

6. 案例:truncated 与 bootstrap

某次实验把 truncated 当成真终止清零 bootstrap,与 SB3 默认不一致,value target 系统性偏一截,critic loss 降了但 policy 不动。对齐后 policy 才开始更新。改 reward 或 obs wrapper 后,旧 checkpoint 不可直接对比。Episode 边界还要和日志对齐:Monitor 记录的 return 是否包含 truncated 那步的 reward?bootstrap 是否用了 truncation 后的 obs?

7. 隔月复现靠 README 不靠口头

写 README 时至少记录:每步 reward 公式、episode 上限、terminated 触发条件、观测各维物理含义。换同事接手或隔月复现实验,这些比「用了 PPO」更重要。HalfCheetah 上 random return 大约负二百是 sanity check。 velocities 隐藏、只有 position 是经典部分可观测例子;与其立刻上 RNN,通常先试 stack 四帧。Monitor 记录的 return 是否包含 truncated 那步的 reward?bootstrap 是否用了 truncation 后的 obs?这些细节不对,曲线能跑但 value 学歪。

8. 验收

  • env.reset(seed=42) 后跑 random policy 几百步,return 量级和 episode length 分布合理。
  • 打印 observation_space 和 action_space,确认 dtype 和 shape。
  • README 记录 reward 公式、episode 上限、terminated 触发条件、obs 各维物理含义。
  • 改 reward 或 obs wrapper 后,旧 checkpoint 不可直接对比。
  • 马尔可夫性自检:固定同一物理状态,obs 相同则最优动作应相同。

MDP 五元组是任务契约。S/A/R/gamma 有一项对不齐,算法再先进也只是在错误问题上优化。

← 全部文章

johan's blog