解读 183 · 奖励设计的艺术与陷阱
解读对象:
tasks/mdp.py的 reward 函数 +microduck_velocity_env_cfg.py的奖励权重表
需要的前置:解读 181(奖励是什么)· 解读 131(权重表逐项)
奖励就是鸭子世界里的法律:你定义"什么叫好",它就把这个"好"执行到极限——包括钻空子。
所以奖励设计的艺术不在"想要什么就奖励什么",而在让它没法假装做到了。
1. 艺术:奖励"变化",不奖励"状态"
upright_progress 奖励的是每步倾斜角的变化量 Δcos(倾斜角),不是角度本身。好处是
理论级的:potential-based shaping 保证不改变最优策略——趴着不扣、一直趴也赚不到,
从趴到立的过程全程收约 +1,没有可以躺平薅分的状态。同一家族的 height_progress 负责
"蹲了要起来"。判据句:想让策略持续做事,就付钱给"变好",别付钱给"待着"。
2. 艺术:每个正奖励配一扇门
正奖励会被薅,所以 mdp.py 里处处是门。recovery_success(起身奖金)要求先真摔
(倾角 >40°)累计满 0.5 秒才布防,起来那一刻发一次奖、立即撤防——在门口来回摇摆
一分不得。fallen_state_penalty 注释里有一句铁律:"罚坏状态是安全的;门控在坏状态
上的正奖励才会被薅。"门还要带滞回:布防用 40°、解除要"倾角 <25° 且高度达标",
两套阈值——否则策略会在门下面找个低姿态歇脚,起身永远差最后一步。
3. 陷阱一:乘法门控防"单项作弊"
glide_reward(轮滑奖励)是四个因子连乘:恰好单脚着地 × 前进速度达标 × 腿静定 × 前进
指令非零。docstring 自述它是修 bug 的产物:早先版本漏了"单脚"因子,结果"双脚着地扭着滑"
能把奖励薅走、步态倒退。经验:想要"同时满足多个条件"时,连乘,别相加——相加的话,
某一项拿满分就能掩盖另一项交白卷。
4. 陷阱二:不可逃脱的税把走路罚死
头部曾经顶着 14.6° 的低头偏差走路。第一反应是把 head_pose 跟踪的容差 std 从 0.5 收紧到
0.1——结果策略 300 迭代就干脆不走了:280 g 的头走路必然振荡,瞬时紧公差等于对每一步收
约 0.77 的不可逃脱的税。正确的做法是只对"可消除的 DC 偏置"收税(head_pose_bias,
L1,权重从 0 课程化爬到 3.0),振荡本身不罚。同理,action_rate 平滑项从 -0.1 课程化爬到
-1.0:先让步态诞生,再收紧纪律——一上来就全罚,什么都不会诞生。
5. 陷阱三:指标会骗人(expD 案)
2026-09-07 的 expD:ep_len 从 315 涨到 744,"站稳了",指标全线变好——但回放一看,
步态没成:air_time_mean 卡在 0.04 s,策略学会了 shuffle(蹭着小碎步挪)。站着不摔、
episode 就长、reward 就好看,可它始终没学会迈步——局部最优在指标上是看不出来的。
修复在 expE:把 air_time 奖励门槛从 0.125 s 降到 0.04,让"真抬脚"先变得可见、拿得到钱,
等 air_time_mean >0.10 再收紧回去。每次下结论前回放亲眼看一遍:reward 和 ep_len 是
体检表,不是诊断书。
你带走的收获
- 奖励"变化量"而非"状态量":Δcos 势函数防躺平,理论背书是 potential-based shaping。
- 正奖励必须门控,门必须带滞回;要"同时满足"就连乘,别相加。
- 罚则要可逃脱:对偏置收税、不对振荡收税;惩罚用课程慢慢加码。
- reward 涨了不等于学会了——expD 教你先看回放,再信指标。