Skip to content

Latest commit

 

History

History
173 lines (123 loc) · 6.75 KB

File metadata and controls

173 lines (123 loc) · 6.75 KB

JPRobot 训练反思笔记

记录训练实验的诊断、根因、修复过程。每次遇到值得记录的问题都更新这里。


Backflip 训练 v1 → v2(2026-02-23)

v1 训练结果(全部失败)

阶段 平均奖励 旋转度数 起跳率 落地率 成功率 结论
jump 13.4 9.5° 0% 0% 0% agent 几乎不动
rotate 554.0 51.2° 100% 100% 0% 跳不翻
land 1364.3 54.9° 100% 100% 0% 跳不翻
full 1877.2 59.9° 100% 100% 0% 跳不翻,6.5M 步无突破

根因:Reward Gaming(奖励函数被游戏化)

Agent 发现的捷径:跳起来不旋转直接落地。

这条路径同时拿到三项奖励:

  • 起跳奖励(W_JUMP=3.0 × vz):向上速度大就给
  • 落地奖励(W_LANDING=10.0):只要脚着地就给,没有旋转门槛
  • 姿态引导奖励(W_POSE_GUIDE=1.5 × 每步):帧2(腾空收腿)匹配即得

"不旋转纯跳" 的总收益远超 "费力翻转"。W_ROTATION=5.0 的旋转奖励根本无法竞争。

关键设计缺陷:

  1. W_LANDING 无旋转门槛 → agent 无需翻转就能拿到最大落地奖励
  2. W_ROTATION=5.0 太弱 → 即使腾空旋转,收益也比 "跳+落" 低
  3. 腾空时不旋转没有惩罚 → agent 在空中 "呆站" 等重力下拉完全合理

jump 阶段模型为什么 0% 起跳率?

jump 阶段(training_phase="jump")只有起跳奖励和姿态引导,没有落地奖励。 v1 实现中,姿态引导奖励在静止站立时已经不小(框架0 蹲伏姿态匹配)。 Agent 发现"原地不动"也能拿到稳定的 W_POSE_GUIDE 奖励,跳起来反而触发侧倒惩罚。 → 最优策略是:静止趴着,稳稳拿姿态分。

rotate 阶段为什么突然 100% 起跳?

rotate 阶段引入了 W_LANDING:有了落地奖励目标,agent 被激励起跳(否则拿不到落地分)。 但它学会的是 "最小化成本的起跳":跳得刚好够高、然后立刻落地, 旋转对它来说是没有收益的额外代价。

v2 修复方案

修改项 v1 v2 原因
W_ROTATION 5.0 15.0 旋转奖励必须压过 "jump+land 不旋转" 的总收益
落地奖励旋转门槛 ROTATION_GATE = π/2(90°) 断掉 gaming 捷径;至少翻 90° 才能拿落地分
腾空不旋转惩罚 W_NO_SPIN = 0.5/步 惩罚"空中僵站",制造旋转压力

修改文件: jprobot/training/env_backflip.py

# 权重变更
W_ROTATION = 15.0   # 原 5.0

# 新增常量
ROTATION_GATE = math.pi / 2   # 落地奖励的最低旋转要求(90°)
W_NO_SPIN     = 0.5            # 腾空不旋转惩罚系数

# 落地奖励加门槛(env_backflip.py step() 中)
if (self._launched and not self._airborne and n_feet >= 2
        and abs(self._pitch_accumulated) >= ROTATION_GATE):   # ← 新增
    reward += W_LANDING * (n_feet / 4)

# 腾空不旋转惩罚(env_backflip.py step() 中)
if self._airborne and abs(self._pitch_accumulated) < 0.1:
    reward -= W_NO_SPIN

旧训练数据备份: trained/backflip_v1/(保留以供对比)

v2 训练启动: 2026-02-23,从 jump 阶段重新开始完整 6.5M 步课程。

方法论总结

这是一个经典的 Reward Gaming 案例。

强化学习中,agent 会 精确地 优化你定义的奖励函数,而不是你 意图 的行为。 一旦奖励函数有漏洞,agent 一定会找到。

检查奖励函数的问题清单:

  1. 每项奖励有没有可被单独绕过的路径?
  2. 组合路径的总收益有没有超过"正确行为"路径?
  3. "不做 X" 有没有惩罚?(只奖励做了 X 是不够的)
  4. 中间阶段奖励会不会成为终局的局部最优?

后空翻训练特别注意:

  • 落地奖励必须有旋转前置条件,否则 agent 会学纯跳不翻
  • 旋转奖励权重需要明显大于(起跳 + 落地)的总和才有意义
  • 姿态引导奖励(pose guide)应该辅助而不能主导 —— 权重太高会让 agent 原地模仿而不运动

步态训练教训(参考 CLAUDE.md 血泪教训)

详见 CLAUDE.md 中的"血泪教训"章节,不在此重复。 关键条目:

  • 永远不要硬编码 PyBullet 关节索引(血泪 #1)
  • 物理量必须检查单位和缩算(血泪 #2)
  • opencat-gym 的 arm_contact 是逐 link 计数(血泪 #3)

JPRobot 使用的 RL 算法(2026-02-28)

算法对比:PPO vs SVG vs SAC

算法 全称 类型 JPRobot 是否使用
PPO Proximal Policy Optimization On-policy,策略梯度 ✅ 用过(四足行走、后空翻)
SVG Stochastic Value Gradient Off-policy,值梯度(学术向) ❌ 未使用
SAC Soft Actor-Critic Off-policy,Actor-Critic 当前人形机器人主力算法

为什么人形机器人选 SAC

  • PPO 是 on-policy(每批数据用完即丢),CPU 上样本量不够,人形行走 8M 步也只到 ep_len=146
  • SAC 是 off-policy,有 1M 容量的回放缓冲区,历史数据可以反复学习,样本效率高 5-10 倍
  • 实测:SAC 在 0.48M 步就突破 ep_len=500,PPO 8M 步做不到

SAC 内部结构

SAC 同时训练两类网络:

Policy(Actor,策略网络)

  • 输入:机器人当前状态(376 维观测)
  • 输出:每个关节的力矩(17 维动作)
  • 决定机器人"怎么动"

Value(Critic,价值网络)

  • 输入:状态 + 动作
  • 输出:这个状态 + 动作有多好(Q 值)
  • SAC 用两个 Critic(防止高估),取小值
  • 决定"当前动作好不好"

更新顺序:

改奖励函数权重
    → Critic 重新学"哪个姿态更值钱"
        → Actor 跟着 Critic 调整动作输出
            → 机器人行为改变

调参时在调什么

调的东西 本质 影响谁
healthy_z_min 环境硬约束(生死门槛) Critic 和 Actor 都要重新学
w_height / w_upright 软奖励权重 先改变 Critic 的学习目标,再带动 Actor
net_arch=[400,300] 网络结构 Actor 和 Critic 的表达能力
buffer_size=1M 回放缓冲区大小 可用历史经验的数量
use_sde=True 状态相关探索 Actor 的探索方式(人形必须开)

各任务算法选择

任务 算法 原因
四足 BittleX 行走 PPO 已跑通,任务相对简单
四足后空翻 PPO 离散阶段式任务,当时尚未切 SAC
人形机器人行走 SAC 高维连续控制,PPO 根本跑不动
人形直立行走课程 SAC 同上,热启 + 课程学习组合