state 被截成 6 维当成「白训了」,要求验到 [17] 才算 OK。
方向是反的:右臂任务里截断保留的前 6 维是左臂,而左臂全程不动 —— 捷径正是这样被断掉的。
四个模型的对照里,state 含正在动的那条臂的两个模型视觉斜率只有 +0.004 / +0.006,不含的两个是 +0.210 / +0.214,差 50 倍。xlerobot-team/xlerobot-left-pick-cup-sep3-clean-20260905(54 集 / 13,693 帧)--policy.input_features=null
上一批(09-07 那个 batch 64)少了这一行,导致 observation.state 从 17 维被静默砍成 6 维,
模型拿着残缺状态训了 20000 步。它不报错、不警告,只有事后翻 config.json 才看得出来。
lerobot-train \ --policy.path=lerobot/smolvla_base \ --policy.input_features=null --policy.output_features=null \ --dataset.repo_id=xlerobot-team/xlerobot-left-pick-cup-sep3-clean-20260905 \ --batch_size=16 \ --num_workers=8 \ --steps=20000 \ --save_freq=2000 \ --policy.scheduler_decay_steps=20000 \ --dataset.eval_split=0.0 \ --dataset.image_transforms.enable=true \ --dataset.image_transforms.max_num_transforms=5 \ --dataset.video_backend=torchcodec \ --seed=1000 \ --policy.device=cuda --policy.push_to_hub=false \ --output_dir=/workspace/outputs/train/left_b16 --job_name=left_b16 \ 2>&1 | tee /workspace/left_b16.log
lerobot-train \ --policy.path=lerobot/smolvla_base \ --policy.input_features=null --policy.output_features=null \ --dataset.repo_id=xlerobot-team/xlerobot-left-pick-cup-sep3-clean-20260905 \ --batch_size=64 \ --num_workers=8 \ --steps=20000 \ --save_freq=2000 \ --policy.scheduler_decay_steps=20000 \ --dataset.eval_split=0.0 \ --dataset.image_transforms.enable=true \ --dataset.image_transforms.max_num_transforms=5 \ --dataset.video_backend=torchcodec \ --seed=1000 \ --policy.device=cuda --policy.push_to_hub=false \ --output_dir=/workspace/outputs/train/left_b64 --job_name=left_b64 \ 2>&1 | tee /workspace/left_b64.log
这样跑完能直接分开两件事:上次训废到底是 state 被砍成 6 维造成的,还是 E 太高造成的。
| 结果 | 说明 |
|---|---|
| 两批都变好 | root cause 就是 state[6],E 不是问题 —— 以后 batch 随便挑,只要别漏那一行 |
| b16 好、b64 差 | E 确实有影响,往低 E 走;同时 state 那条也必须一直带着 |
| 两批都还差 | 问题不在训练配方,回到数据本身(示范阶段性、杯位覆盖) |
正式开跑前,把 --steps=20000 临时改成 --steps=40 --save_checkpoint=false 先跑一遍:
| 看什么 | 正常值 |
|---|---|
| step/s | 约 4–5 |
| mem_gb | 约 4.6(batch 16) |
| loss | 在下降 |
别急着上机。先确认这次的 state 是不是 17 维——如果还是 6,那这批又白跑了,上机测多少次都没意义。
python -c "
import json
c=json.load(open('outputs/train/left_b16/checkpoints/020000/pretrained_model/config.json'))
s=c['input_features']['observation.state']['shape']
print('state shape:', s, '->', 'OK' if s[0]==17 else '★ 又错了,不要上机 ★')
print('images:', [k for k in c['input_features'] if 'image' in k])
"
state shape: [17] -> OK,images 是 head / left_arm_wrist / right_arm_wrist。if not cfg.input_features: 不成立 → 数据集的 features 用不上两条命令都过了 03-software/scripts/check_train_cmd.py:
| 检查项 | batch 16 | batch 64 |
|---|---|---|
| 没有 rename_map | ✓ | ✓ |
| input_features=null | ✓ | ✓ |
| decay_steps == steps | ✓ | ✓ |
| 相机键名跟推理侧一致 | ✓ | ✓ |
| E(数据重复遍数) | 23.4 偏高 | 93.5 太高 |
| image_transforms | 开着 | 开着 |
b16 模型开着增强,而它是目前唯一被证实会看图的模型,所以跟着它对齐。
Pick up the cup with the left arm.