# ACT 下一轮训练（v2）· 计划与核对 · 2026-08-20

来源：操作者提供的《ACT 下一轮训练建议》(`ACT_next_training_zh.html`)。
本文件 = **该建议的核对结果 + 三点补充**。凡是我核对过的，都标了实际值。

---

## 〇、先说核对结论：那份建议 13 项断言全部属实

我逐条对着 `05-training/runs/act_20260820-0429/checkpoints/020000/pretrained_model/train_config.json`
查过，没有一处编造，可以直接采用。

| 断言 | 实际值 | |
|---|---|---|
| `eval_split` | `0.0` | ✓ |
| `eval_steps` | `0` | ✓ |
| `image_transforms.enable` | `False` | ✓ |
| `use_vae` | `True` | ✓ |
| `kl_weight` | `10.0` | ✓ |
| `chunk_size` / `n_action_steps` | `100` / `100` | ✓ |
| `vision_backbone` | `resnet18` | ✓ |
| `optimizer_lr` | `1e-05` | ✓ |
| `grad_clip_norm` | `10.0`（在 `optimizer` 块内） | ✓ |
| `scheduler` | `None` | ✓ |
| `batch_size` / `steps` | `2` / `20000` | ✓ |
| `wandb.enable` | `False` | ✓ |

---

## 一、它指出的、我第一轮的真实缺陷

**50 集全部用于训练，`eval_split = 0.0`，所以没有 validation 曲线。**

这意味着我此前汇报「l1_loss 降到 0.094、收敛良好」时**话说过头了**：
在没有 validation 的情况下，训练 loss 下降只能证明模型在**拟合训练集**，
**不能证明它学到了泛化能力**。两者在小数据集上经常背道而驰。

**这条要记住：训练 loss 不是验收指标。**

---

## 二、最重要的一条：位置记忆测试（原文第 6 节）

> 把杯子从训练位置**平移 2–3 cm**。如果动作仍然总往同一个固定位置走，
> 即使 loss 很低，也说明存在 **position memorization**。

**这是唯一能区分「学会了看杯子」和「背下了 5 个坐标」的实验，比任何 loss 数字都重要。**

我们的数据集只有 5 个离散杯位（P1–P5），策略完全可能学成
「看到大致这个画面 → 走到第 3 号坐标」，而根本没有在看杯子。
这种策略在训练位置上成功率可以很高，在任何新位置上直接失效。

每个 checkpoint 记录：成功率、杯位、是否接近正确目标、是否闭爪、是否抬起、是否正确放下、失败类型。

---

## 三、补充 1：validation 必须按位置**分层**抽样，不能随机切

原文建议 `eval_split = 0.2` 并让 5 个杯位各留 validation episode。**方向对，但有个坑。**

我们的实际分布是 **P1 11 · P2 12 · P3 9 · P4 8 · P5 10**，**不均匀**。
按 0.2 随机切分，很可能某个位置的 validation 只有 1 集甚至 0 集 ——
那个位置的过拟合就完全测不出来。

**做法**：按位置分层，每位固定抽 2 集作 validation（共 10 集，正好 20%），
其余 40 集训练。这样每个位置都有 validation 覆盖。

---

## 四、补充 2：图像增强会让 v2 的 loss 变高，**这是预期的，不是退步**

原文建议的增强（平移 ±2%、旋转 ±3°、亮度/对比/饱和 0.9–1.1、色相 ±0.02）在一般任务上很轻。
但我们有一个特殊情况：

**头部相机是锁定的**（`WORKSPACE_LOCK`，整个数据集里视角完全不变）。
这意味着策略很可能已经把**图像中的绝对像素位置**当成了坐标系 ——
这正是第二节说的 position memorization 的实现方式。

加入平移增强会**打破这个隐含假设**，强迫它依赖杯子的视觉特征而不是像素坐标。
**这正是我们想要的**，但直接后果是：

> **v2 的训练 loss 一定会比 v1 高。不要把它误判为退步。**

判断 v2 好坏要看 **validation loss** 和**位置记忆测试**，不看训练 loss。

---

## 五、补充 3：硬件变更没被考虑进去，它会决定 v2 用什么数据

原文默认下一轮在同样的硬件上训。但我们正准备把 Fin-Ray 刀片从 **68 mm 换成 90 mm** ——
力臂和柔顺度都变了，旧数据的动力学**不再适用于新硬件**。

**所以顺序必须是：**

1. **先用旧夹爪把 v1 实机测了**（第二节那套位置记忆测试）
   → 20 分钟就能知道「数据 → 训练 → 实机」这条链通不通，以及有没有 position memorization
2. **然后再决定 v2 用什么数据**：
   - 如果 v1 链路通、只是泛化差 → v2 用**旧数据 + validation + 增强**重训，问题在数据多样性
   - 如果 v1 链路根本不通 → 那是别处有问题，换爪和 v2 都救不了
   - 如果决定换爪 → **必须重录**，且新数据单独分组，不与旧数据混训
     （见 `GRIPPER-SWAP-CHECKLIST.md`）

**先测再训，不要先训再测。**

---

## 六、v2 配置：只改三项，其余与 v1 完全一致

原文第 7 节的纪律是对的 —— **一次只改少数变量，否则不知道变化来自哪里**。

### 改
| 项 | v1 | v2 |
|---|---|---|
| `eval_split` | `0.0` | **`0.2`，按位置分层** |
| `image_transforms.enable` | `False` | **`True`，轻量参数见第四节** |
| 训练日志 | 只有 stdout | **结构化记录**：total / l1 / kld / grad_norm / lr / **val_loss** |

### 不改（原文第 7 节，我同意）
`optimizer_lr=1e-5` · `batch_size=2` · ACT 架构 · `chunk_size=100` / `n_action_steps=100` ·
`resnet18` backbone · `kl_weight=10` · `grad_clip_norm=10.0`

### 第二阶段再单独试（原文第 8 节）
AMP / 混合精度（先单独做 Jetson 稳定性测试）· LR scheduler（cosine / warmup）·
精简 inactive action dimensions（当前 17 维里左臂是 parked constant，
但为了和 baseline 直接比较，**v2 先不动 schema**）

---

## 七、checkpoint 比较：不要默认 20k 最好

50 集是小数据集，训练 loss 继续下降**不代表**真实泛化继续变好。
最佳 checkpoint 很可能早于 20k。

**至少比较 8k / 12k / 16k / 20k 四个点的真实机器人表现**，不是比 loss。
v1 的这四个 checkpoint 都在本地：
`05-training/runs/act_20260820-0429/checkpoints/`

---

## 八、关于 total loss 数值的一个澄清（原文第 4 节）

ACT 用 VAE，`use_vae=True`、`kl_weight=10`，所以：

```
total loss ≈ l1_loss + 10 × kld_loss
```

v1 step 100 时 `loss=11.630`、`l1_loss=0.413`、`kld_loss=1.122` —— 这组数字是自洽的
（0.413 + 10×1.122 = 11.63）。**总 loss 高主要来自 KL 权重，不代表动作误差本身有 11.63。**
看动作精度要看 `l1_loss`。
