LeRobot v3.0 数据集迁移指南:从 GB 级到 TB 级,按规模选对路线少走弯路
【免费下载链接】lerobot🤗 LeRobot: Making AI for Robotics more accessible with end-to-end learning项目地址: https://gitcode.com/GitHub_Trending/le/lerobot
升级 lerobot 之后,不少同事发现老数据集加载报错、初始化慢得离谱——说白了就是 v2.1 和 v3.0 的存储结构变了。做 LeRobot 数据集的 v3.0 格式迁移,最忌讳上来就无脑跑脚本:GB 级的数据单机几分钟搞定,TB 级的硬扛要拖上几周。咱们先按数据规模把路线选明白,再分路线给命令,最后把踩过的坑列出来。
升级前 3 分钟,搞懂 v3.0 到底改了什么
不用背全部文档,抓住三个变化就够用了,每个变化都对应一个真实影响。
1)文件从"每 episode 一个"变成"分片里装一堆"。v2.1 里episode_000000.parquet、episode_000001.parquet各占一个文件,几千条 episode 就是几千个小文件;v3.0 把多个 episode 合并进一个file-000.parquet(视频同理,合并进file-000.mp4)。影响很直接:文件数量少了一大截,初始化更快,官方给出的加载提速在 3~5 倍,磁盘占用也省约 30%。
2)元数据从 JSONL 换成 Parquet。meta/episodes.jsonl这种逐行文本,换成了meta/episodes/chunk-000/file-000.parquet。好处是能用 pandas / PyArrow 直接做结构化查询,episode 的边界靠元数据里的偏移量定位,而不是靠文件名猜。查询快了,也才能支撑"episode 级 API + 分片存储"这种解耦设计。
3)按分片处理,天然可扩展。既然数据是按分片组织的,就可以把分片拆开并行处理——这就是后面 SLURM 方案的由来。另外 v3.0 还支持StreamingLeRobotDataset,不下载、直接从 Hub 流式读,千万级 episode、TB 级数据才压得住。
详细设计可以看官方文档 docs/source/lerobot-dataset-v3.mdx,迁移教程在 docs/source/porting_datasets_v3.mdx。
对号入座:按数据量选路线
迁移前先看一眼你的数据有多大、什么来源,对号入座即可:
| 数据规模 | 数据来源 | 推荐路线 | 预期耗时 |
|---|---|---|---|
| GB 级(几百 GB 以内) | 已有的 v2.1 LeRobot 数据集 | 路线 A:单机官方脚本一键转 | 分钟~小时 |
| 百 GB 级(第三方格式,单机扛得住) | DROID 样本、RLDS 等 | 路线 A:单机导入脚本,分片调试 | 数小时~1 天 |
| TB 级(如 DROID 1.7TB,2048 分片) | 巨型第三方数据集 | 路线 B:SLURM 集群分片并行 | 2~3 天 |
判断标准很简单:数据是"已经是 LeRobot 格式、只是版本旧"还是"外部格式要第一次导进来"?前者走转换脚本,后者走导入脚本。规模决定单机还是集群。
路线 A|中小规模:单机迁移实操
已有 v2.1 数据集,一键升到 v3.0
转换脚本在src/lerobot/scripts/convert_dataset_v21_to_v30.py,它对 Hub 上和本地的数据集都能处理:
python src/lerobot/scripts/convert_dataset_v21_to_v30.py \ --repo-id your_namespace/your_dataset \ --root /path/to/local_dataset \ --push-to-hub=false--root指向本地已经存在的那个 v2.1 数据集目录(里面有meta/、data/、videos/),脚本会原地转成 v3.0;--push-to-hub=false表示只在本地落盘、不上传。如果数据集本来就在 Hub 上,把--root和--push-to-hub=false都去掉,脚本会拉下来转换、推回 Hub,并打一个v3.0标签。脚本还会顺手生成每 episode 的统计、删掉废弃的stats.json、更新info.json里的版本号。
想控制分片大小可以加--data-file-size-in-mb和--video-file-size-in-mb(默认数据块 100MB、视频块 500MB),episode 特别多时调大一点能进一步减少文件数。
第三方数据集导入:以 DROID 为例
这类数据的来源是外部格式(DROID 是 TF Records / RLDS),得用examples/port_datasets/port_droid.py。先装依赖、拉数据:
pip install tensorflow tensorflow_datasets # 2GB 样本,先验证流程跑通 gsutil -m cp -r gs://gresearch/robotics/droid_100 /data/droid_test # 全量 1.7TB gsutil -m cp -r gs://gresearch/robotics/droid/1.0.1 /data/droid_raw转换命令:
python examples/port_datasets/port_droid.py \ --raw-dir /data/droid_raw \ --repo-id your_namespace/droid_v3 \ --push-to-hub--raw-dir是原始数据目录,--push-to-hub加不加决定完事要不要直接上传。
强烈建议先只跑一个分片调试,DROID 固定切成 2048 片:
python examples/port_datasets/port_droid.py \ --raw-dir /data/droid_raw \ --repo-id your_namespace/droid_test \ --num-shards 2048 \ --shard-index 0--num-shards 2048 --shard-index 0的意思是从 2048 片里只挑第 0 片处理。为什么先跑一片?因为它便宜、快,能提前暴露 schema 不匹配、字段映射错这类问题,别等全量跑几天才发现问题。
路线 B|TB 级:SLURM 集群分布式迁移
单机扛 1.7TB 要 7 天以上,换成集群把 2048 个分片摊到多节点,能压到 2~3 天。整套流程是分片并行 → 监控进度 → 聚合上传三步。
先备环境和确认资源:
pip install datatrove # HF 的分布式流水线库,SLURM 脚本靠它调度 sinfo --format="%R %c %m" # 看分区名、CPU 核数、内存,挑一个 CPU 分区就行数据迁移不吃 GPU,纯 CPU 分区即可。
第一步:分片并行处理
python examples/port_datasets/slurm_port_shards.py \ --raw-dir /data/droid_raw \ --repo-id your_namespace/droid_v3 \ --logs-dir /data/logs/porting \ --job-name droid_port \ --partition cpu_high \ --workers 2048 \ --cpus-per-task 8 \ --mem-per-cpu 1950M--workers 2048对应 DROID 的 2048 个分片,一片一个 worker;--cpus-per-task 8是给视频编码留的多线程余量;--mem-per-cpu 1950M即每核约 2GB,8 核合计约 16GB,够装得下原始帧。
💡 上千 worker 之前,先用--slurm 0本地串行跑一条,确认依赖、日志目录这些没毛病,再正式投集群。
第二步:监控进度
squeue -u $USER -p cpu_high # 当前还在跑的任务 python examples/port_datasets/display_error_files.py \ --logs-dir /data/logs/porting \ --job-name droid_port # 汇总哪些分片失败了 less /data/logs/porting/droid_port/slurm_jobs/12345_0.out # 看某个 worker 的日志display_error_files.py会把"缺了哪些 worker"一次性列出来,比逐个翻日志快得多。
第三步:聚合上传
# 把 2048 个分片合并成一个完整数据集 python examples/port_datasets/slurm_aggregate_shards.py \ --repo-id your_namespace/droid_v3 \ --logs-dir /data/logs/aggregation \ --job-name droid_agg \ --partition cpu_high # 并行上传到 Hub python examples/port_datasets/slurm_upload.py \ --repo-id your_namespace/droid_v3 \ --logs-dir /data/logs/upload \ --job-name droid_upload \ --partition cpu_high \ --workers 50聚合本质是"分片 → 整集",默认单 worker 就够,--workers不用加。上传那步注意--workers 50:上传是网络瓶颈不是算力瓶颈,worker 开太多反而没意义,别照搬第一步的 2048。
迁移后的体检清单
转完别急着删源数据,按这三点验一遍:
- 版本号:
meta/info.json里的codebase_version应为v3.0; - episode 数:和源数据对得上;
- 数据块:
data/下应是file-000.parquet这种"一块多 episode"的结构,videos/<camera>/chunk-000/file-000.mp4同理。
from lerobot.datasets import LeRobotDataset ds = LeRobotDataset("your_namespace/droid_v3") print(ds.meta.codebase_version) # 期望: v3.0 print(len(ds.meta.episodes)) # episode 总数,应等于源数据 print(len(ds.data_files)) # 数据块(parquet 分片)数量跑一下能正常出图、按 index 取一条样本不报错,基本就可以放心用了。
这些坑我先替你踩了
坑 1:加载报"版本 / 结构不兼容"多半是本地还挂着旧的 v2.1 缓存,或info.json版本没刷新。解法:清掉本地缓存目录(默认$HF_LEROBOT_HOME,即~/.cache/huggingface/lerobot,或你--root指的那个目录)后重跑;如果目标已经存在 v3.0 版本、想强制覆盖,转换时加--force-conversion。
坑 2:视频编码中断、文件写一半典型原因是目标盘空间不够——转换过程有临时文件。解法:目标分区预留大于源数据 2 倍的空间;空间紧张时可以用--video-file-size-in-mb调小视频块(默认 500MB),降低编码峰值占用。
坑 3:SLURM 任务频繁超时 / OOM通常是单个 worker 资源给少了。解法:先--slurm 0本地串行定位是不是单 worker 本身会挂;确认单 worker 稳了再放大--workers;内存吃紧就提--mem-per-cpu,而不是无脑堆 worker 数。
写在最后:v3.1 会带来什么
v3.0 靠分片存储、Parquet 元数据和可扩展的流式读取,把 GB 级到 TB 级的迁移都理顺了。官方 roadmap 里 v3.1 打算再补三块:增量数据更新(不用整集重转)、多模态数据联合索引、以及自动的数据质量检测。对维护大团队的同事来说,这三点基本是刚需,值得盯一下后续版本。
想深入细节,建议直接翻 docs/source/porting_datasets_v3.mdx 和examples/port_datasets/下的脚本源码,参数都有 help 说明。迁移这件事,路线选对了,剩下的基本就是按部就班跑命令。
【免费下载链接】lerobot🤗 LeRobot: Making AI for Robotics more accessible with end-to-end learning项目地址: https://gitcode.com/GitHub_Trending/le/lerobot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考