本任务关注 ACT。ACT 在训练集上 loss 下降,并不等于闭环部署稳定成功。尤其在 ROCm 设备上复刻时,要先证明失败不是环境、数据、显存或成功判定造成的,再讨论模型结构和数据策略。
配套实操 Notebook:03_act_dagger_diagnostics.ipynb。
建议按照下面顺序排查:
flowchart LR
A["数据动作回放"] --> B["ACT 训练"]
B --> C["teacher-forced / open-loop"]
C --> D["closed-loop rollout"]
D --> E["失败 seed 视频"]
E --> F["DAgger / oracle correction"]
每一步回答的问题不同:
| 步骤 | 回答的问题 |
|---|---|
| 数据动作回放 | 采集数据本身是否能完成任务 |
| ACT 训练 | 模型是否能学习离线动作分布 |
| open-loop | 模型在数据状态上是否能复现轨迹 |
| closed-loop | 策略自己跑时是否稳定 |
| 失败视频 | 失败发生在接近、夹取、搬运还是释放 |
| DAgger | 如何补闭环跑偏后的状态 |
| 失败类型 | 现象 | 可能原因 |
|---|---|---|
| 不接触杯子 | 夹爪停在杯子旁边 | 图像条件不足、初始位姿 OOD、闭环偏移 |
| 能抬起但不释放 | 杯子悬在盘上或被带走 | gripper 标签、尾段 release 太短 |
| 放到盘边但倒杯 | 位置接近但姿态失败 | 末端阶段示教不足、放置高度不稳 |
| open-loop 成功 closed-loop 失败 | 数据状态下会,自己跑不会 | 闭环分布偏移 |
一个适合教学的 DAgger 流程:
- 训练 reset-start 基线;
- 固定一批 seed 做闭环 rollout;
- 找出失败 seed;
- 让当前策略先跑前若干步,例如 40 个控制 tick;
- 从失败附近状态切换到 oracle 或 scripted policy;
- 保存纠偏 suffix;
- 合并数据时记录来源、timestamp offset 和采样权重;
- 重新训练并用同一批 seed 评估。
注意:correction 数据不一定越多越好。直接把 full-reset failure-bucket 数据高权重混入主训练,可能破坏原本已经学会的 reset-start 行为。
这次 ACT 不是原装脚本跑一遍就得到 17/30。原始 closed-loop 基线几乎不能通过严格物理成功判定,后面的提升来自一串可复查的改动。
第一步是把评估口径改严。旧 success 只看环境几何条件,可能把推杯、挤杯、倒杯误判成成功。本专题统一报告 physical_success:杯子要被抬起、移动到盘上,并且终态基本直立。没有这一步,后面的训练改动很容易被旧指标误导。
第二步是把失败拆成 open-loop 和 closed-loop。我们用数据集 observation 生成 ACT 动作,再把这些动作 open-loop 回放到 MuJoCo。这个诊断能区分两件事:模型在数据状态上是否已经学到动作,以及策略自己闭环跑时是否因为状态漂移而失败。结果显示,单 demo 或 clean 数据下,ACT 有时手臂轨迹接近可用,但 gripper release 很短、闭环分布偏移也很明显,所以不能只靠改 gripper 或继续训练解决。
第三步是重做 reset 对齐的数据。旧数据里不少 episode 并不是从评估 reset 姿态开始,训练时看起来 loss 正常,closed-loop 从 reset 出发却不接触杯子。后续主线改成 reset-aligned scripted oracle:每条轨迹从评估使用的 reset 状态开始,先保证数据本身能按同一物理口径回放成功。
第四步是调整 ACT 训练配置。最终主线使用 no-VAE、chunk_size=20、n_action_steps=10、timestamp state、obj_init state、gripper BCE 0.5 和 per-episode early weight。这里每一项都对应一个失败现象:
| 改动 | 解决的问题 |
|---|---|
| no-VAE | 小数据下减少采样随机性,让复刻更稳定 |
| timestamp state | 给模型显式时间相位,避免所有阶段被平均到一起 |
obj_init state |
让模型知道本轮杯子和盘子的初始几何关系 |
gripper BCE 0.5 |
强化开合爪时序,但不过度牺牲手臂轨迹 |
| per-episode early weight | 保护每条 episode 的 reset-start 前段,不让 correction 数据冲掉开头行为 |
n_action_steps=10 |
保留 chunk 连贯性,同时降低一次执行太长带来的闭环漂移 |
第五步是 prefix40 DAgger。让当前 ACT 先跑 40 个 control tick,再切到 scripted oracle 接管并保存 suffix。这样采到的是“策略自己跑偏后的状态”,比只用完美 reset-start 示教更接近 closed-loop 失败分布。
第六步是给 correction episode 加 timestamp offset。prefix40 suffix 不是从 reset 开始的完整任务,如果它的 timestamp 也从 0 开始,模型会把“中途纠偏动作”误认为“任务开头动作”。因此 correction episodes 使用 timestamp offset = 2.0,让时间相位和 reset-start episode 分开。
第七步是给 correction 数据降权。我们试过不同权重:
| correction 采样权重 | 严格结果 | 结论 |
|---|---|---|
0.1 |
1/15 | 纠偏数据太弱,release / 落点能力补不上 |
0.5 |
0/15 | 纠偏数据太强,破坏 reset-start 主分布 |
0.25 |
13/30 | 当时最好的折中 |
最后再用 best025 checkpoint 对失败 seed 做一轮 prefix40 DAgger v1,采到 3 条有效纠偏轨迹,并继续用 timestamp offset 2.0 和 sample weight 0.25 合并训练,得到当前 protected checkpoint:
ckpt/act_scripted_reset_oracle_plus_prefix40_dagger_best025_toffset2_downweight025_chunk20_n10_novae_gpu_5000_20260629_031208/step_5000
扩大评估得到 seen 6/10、mixed 4/10、heldout 7/10,合计 17/30 physical_success。后续的 DAgger v2 和 full-reset failure-bucket 直接混入都没有超过它,full-reset failure-bucket 甚至会退化到 0/15。因此教程里把这个 v1 best 当作 ACT 保护基线,而不是把所有后续尝试都写成改进。
ACT 训练通常显存占用不算高,但仍然要记录:
- batch size;
- chunk size;
n_action_steps;- 是否 no-VAE;
- 是否有 gripper 辅助损失;
- 训练温度;
- VRAM 使用;
- 是否出现 kernel crash / OOM。
如果训练失败,先用设备日志证明是不是硬件或 ROCm 问题;如果训练稳定但策略失败,优先回到数据和闭环诊断。
本轮 ACT 复刻中,单纯 clean closed-loop 基线几乎不能通过严格物理成功判定。加入 timestamp offset、downweight correction 和更合适的 DAgger 数据后,physical_success 逐步提升到 17/30。这个结果说明 ACT 已经形成了一个完整的 ROCm 闭环诊断案例,但它还不是“随机泛化已经解决”的状态。
图 1:ACT 闭环物理成功率随诊断步骤的变化。这里的提升来自数据和闭环状态纠偏,不是简单加长训练时间。
| 阶段 | physical success | 解释 |
|---|---|---|
| clean closed-loop | 0/10 | 模型在闭环状态下无法稳定接触并搬运杯子 |
| timestamp offset | 3/15 | 动作对齐改善了一部分轨迹,但仍不稳定 |
| downweight DAgger | 13/30 | correction 数据开始补上失败附近状态 |
| best DAgger | 17/30 | 当前示例中最好的 ACT ROCm 复刻结果 |
图 2:ACT best DAgger 的物理成功 rollout。可以对照抓取、搬运和释放三个阶段检查自己的视频。
图 3:ACT best DAgger 的典型失败 rollout。即使环境几何条件偶尔接近成功,也要继续检查抬升高度和终态姿态。
完成本任务后,整理这些项目:
| 项目 | 内容 |
|---|---|
| ACT checkpoint | 路径用变量表示 |
| open-loop 成功率 | 训练集或固定 seed |
| closed-loop 成功率 | 使用 physical_success |
| DAgger 数据说明 | prefix 长度、oracle 类型、采样权重 |
| 典型失败视频 | 至少 1 个 |
| 下一步判断 | 继续 DAgger / 修 gripper / 补示教 / 调 chunk |


