← reports index
训练 · 2026-09-04

昨天那批数据怎么训:合并 + 租 GPU 一次跑通

2026-09-04 · 证据等级标注:实测 = 本机跑过;源码 = 指到文件行号;未测 = 没跑过,别当结论用。

结论

能训,但不能「直接加进去」。 lerobot 0.6.2 不支持多数据集训练,所以合并要在训练前做好(两个合并集本机已做好;202 集那份已推 Hub,sameview 待推)。租 GPU 后一条命令:./train_smolvla_lr.sh。配方和现役模型 b16-3cam-u20k 完全一致,这次唯一变的变量是数据。

一次约 1.3 小时、约 $1(4090 @ $0.75/h)。建议跑两个变体各一次,共约 $2.5。

0. 三件会让你白跑的事(先看)

#事实出处后果
1昨天那批是左臂数据,现役模型是右臂meta/stats.json action.std:sep3 只有第 0–5 维动,6–11 维全 0;0826 反过来 · 实测不是「多了 60 集同样的数据」,是另一个任务。任务串不同(…with the left arm. / …with the right arm.),SmolVLA 靠语言区分
2--dataset.repo_id 传列表不行lerobot/datasets/factory.py:128 直接 raise NotImplementedError("The MultiLeRobotDataset isn't supported for now.") · 源码configs/default.py:30-33 的注释说「可以传列表」——那是过时注释,别信。必须先合并成一个数据集
3不要传 rename_map现役 checkpoint config.json 输入名是 observation.images.head / right_arm_wrist / left_arm_wrist(train_config.json 里 rename_map={});推理端 run_policy_trials.py:415-417 按这套原名喂 · 源码REMOTE-GPU-SMOLVLA-4090.md §6/§7 那行 camera1/2/3 映射如果加上,新模型的输入名和机器人喂的对不上

1. 数据盘点(实测)

换爪之后的全部 13 个数据集,特征签名完全一致(17 维 action/state、三路相机分辨率、30 fps、v3.0)——可以直接合并。

批次数据集臂集帧头部视角
0826right-pick-cup-20260826-0042右4016,487低头看桌 (pan 1985 / tilt 2332)
sep2right-pick-cup-sep2-* ×4右5114,103抬头 ~6°(tilt 2261),看到对面椅子
sep2left-pick-cup-sep2-* ×2左5114,293同上
sep3(昨天)left-pick-cup-sep3-* ×6左6015,581低头看桌 (pan 1985 / tilt 2333) —— 和 0826 一样

头部视角这一列是逐帧看过的(各解一帧头相机画面对比),不只是读数字。sep2 那批录制时头抬高了,画面里杯子在最下面、背景是椅子和墙 —— 和部署视角不一致。部署用的标准视角由操作者定为 cup-grasp-v0(预置位 trial = pan 2003 / tilt 2619);数据集里记的头部 state 读出来是 tilt≈2332,两者差 287 tick —— 这条差异记在这里,训练完跑测如果视角敏感,先回来看这一行。

所以做了两个合并集:

变体内容集帧Hub用途
sameview(默认)0826 + sep310032,068xlerobot-team/xlerobot-pick-cup-lr-sameview-20260904主跑。视角与部署一致,左右各半
all全部 13 个20260,464xlerobot-team/xlerobot-pick-cup-lr-merge-20260904对照。多一倍数据,但混了一个视角

两句任务串都在 meta/tasks.parquet 里:索引 0 = 右臂句,索引 1 = 左臂句。

2. 合并是怎么做的(本机实测)

# 在 Jetson 上,lerobot 环境。封装的是 lerobot 自带的 datasets/aggregate.py。
cd ~/Robotic_challenge/03-software/scripts
O=xlerobot-team
~/miniconda3/envs/lerobot/bin/python aggregate_datasets.py --json \
  --out $O/xlerobot-pick-cup-lr-sameview-20260904 \
  --repo-ids $O/xlerobot-right-pick-cup-20260826-0042 \
             $O/xlerobot-left-pick-cup-sep3-20260903-{1824,1853,1906,1927,2015,2054}

顺手修了一个 bug:第一次跑直接失败——aggregate_datasets 在 roots=None 时优先走 $HF_LEROBOT_HOME/hub/datasets--*/snapshots/<sha>/ 那个「按 revision 的缓存」,那里只有 meta(24 KB),没视频,于是元数据校验 13/13 全过、复制视频时 FileNotFoundError。现在 aggregate_datasets.py 显式传 roots 和 aggr_root,指向本地完整目录。面板上的「合并」按钮走的也是这个脚本,所以一起修好了。

推送:LeRobotDataset(...).push_to_hub(private=<和参考集一致>),本机上传约 9 MB/s,1 GB 两分钟。

3. 租 GPU 后逐条做

Pod 规格(沿用 REMOTE-GPU-SMOLVLA-4090.md §2 已验证过的):1× RTX 4090 24 GB · ≥8 vCPU · ≥32 GB RAM · 40 GB 容器盘 · RunPod PyTorch 2.8 / CUDA 12.8 模板 · ~$0.75/h。

# ① 进 pod,先开 tmux —— 家里网断了训练不会死,但 pod 照样计费
tmux new -s train

# ② 环境(§3 原样)
nvidia-smi
pip install -U "lerobot[dataset,training,smolvla]" huggingface_hub
hf auth login          # 用有 xlerobot-team 读权限 + Suyang99 写权限的 token
hf auth whoami

# ③ AV1 解码后端必须是 torchcodec,否则 data_s 飙高、GPU 空转(§4 原话)
python -c "import torch, torchcodec; print(torch.__version__, torchcodec.__version__)"
ffmpeg -decoders | grep -E "av1_cuvid"
# torchcodec 报 undefined symbol → pip install "torchcodec==0.7.0"

# ④ 把脚本放进去(从 Jetson scp,或者直接粘贴,就一个文件)
mkdir -p /workspace && cd /workspace
# scp robomates@100.107.145.111:~/Robotic_challenge/05-training/train_smolvla_lr.sh .
chmod +x train_smolvla_lr.sh

# ⑤ 40 步烟测(一分钟)。看 step/s≈4-5、data_s<0.07、loss 在降、grdn 有限
BENCH=1 ./train_smolvla_lr.sh

# ⑥ 正式跑(默认 sameview;约 67-83 分钟)
./train_smolvla_lr.sh
#    对照:  VARIANT=all ./train_smolvla_lr.sh
#    Ctrl-B D 脱开 tmux,tmux attach -t train 回来

# ⑦ 传 checkpoint(先建仓库,再传;先确认传上去了再 Terminate pod)
hf repo create xlerobot-smolvla-lr-sameview-b16-u20000 --repo-type model --private --exist-ok
hf upload Suyang99/xlerobot-smolvla-lr-sameview-b16-u20000 \
   /workspace/outputs/train/smolvla_lr-sameview_b16_u20000/checkpoints/020000 checkpoints/020000 \
   --repo-type model

脚本里每个值的出处:B_EFF=16 / MICRO_BATCH=16 / UPDATES=20000 / WARMUP=1000 / LR=1e-4 / AUG=1(含 affine) / eval_split=0 / seed=1000 全部逐项抄自现役模型 checkpoints/020000/pretrained_model/train_config.json。改任何一个 = 改了第二个变量。

顺带一条之前没人写下来的:现役模型的 affine 增强是开着的(train_config.json → tfs.affine.weight=1.0)。REMOTE-GPU 文档 §10 担心 affine 的 ±0.05 平移会抹掉杯位线索——那个担心可能成立,但现役模型就是带着它训出来的。这次保持一致;要不要关是下一个实验。

4. 拉回 Jetson、跑测

# Jetson 上。面板从 05-training/*/checkpoints/*/pretrained_model 列模型(robot_server.py:2511),
# 所以目录结构照现役模型的来。checkpoint 1.3 GB,根分区还剩 ~30 GB。
cd ~/Robotic_challenge/05-training
hf download Suyang99/xlerobot-smolvla-lr-sameview-b16-u20000 \
   --local-dir xlerobot-smolvla-lr-sameview-b16-u20000

跑测必须明说用哪只臂。 run_policy_trials.py 以前从数据集自动取任务串——它取的是第一句。合并集第一句是右臂。今天加了守卫(run_policy_trials.py:_dataset_task_sentence):数据集里多于一句时拒绝自动选并把两句打印出来,必须传 --task,逐字:

--task "Pick up the cup with the left arm."
--task "Pick up the cup with the right arm."

面板/现场控制台走 /api/trials/control 的 task 字段,同一条规则。发错句子 = 换了任务,bartender_tasks.py:14 记着上次这么错了 31 次两天没发现。

5. 没验证的(读到这里再决定信多少)

事项状态
train_smolvla_lr.sh 在 4090 上实际跑起来未测。本机没有可用于此的 GPU。bash -n + DRY=1 过了;每个参数都是现役模型用过的,只换了 repo_id、去掉 rename_map
合并后 SmolVLA 真能按任务句区分左右臂未测 —— 这正是这次训练要回答的问题。风险:起始画面下左右臂 episode 的观测几乎一样,只有语言不同
左臂的安全地板teleop_safety.yaml:59 有 arms.left 包络(z 0.061–0.35),但俯仰补偿的爪长/腕距只校过右臂(yaml 注释在 right 块下)。跑左臂前要看拒帧率
sep2 那批「视角不一致」对训练的影响有多大未测。sameview vs all 两个变体跑完对比就知道
sameview 合并集本机已完成(100 集 / 32,068 帧,实测)。202 集那份已推 Hub;sameview 还没推——推之前 VARIANT=sameview 在 pod 上拉不到,先用 VARIANT=all 或让远程推一下

6. 成本

项时间费用
pod 设置 + 烟测~15 min~$0.2
sameview 正式67–83 min~$1.0
all 对照67–83 min~$1.0
上传 + 收尾~10 min~$0.1
合计~2.5 h~$2.5

相关文件