本教程介绍如何将大规模机器人 dataset 迁移到 LeRobot Dataset v3.0 格式。我们将以 DROID 1.0.1 dataset 作为主要示例,它演示了如何在 SLURM 集群上处理带有数千个分片的数 TB 级 dataset。
Dataset v3.0 从根本上改变了数据的组织和存储方式:
v2.1 结构(基于 episode):
dataset/ ├── data/chunk-000/episode_000000.parquet ├── data/chunk-000/episode_000001.parquet ├── videos/chunk-000/camera/episode_000000.mp4 └── meta/episodes.jsonl
v3.0 结构(基于文件):
dataset/
├── data/chunk-000/file-000.parquet # Multiple episodes per file
├── videos/camera/chunk-000/file-000.mp4 # Consolidated video chunks
└── meta/episodes/chunk-000/file-000.parquet # Structured metadata这种从单个 episode 文件到基于文件的分块的转变,大幅提升了性能并降低了存储开销。
Dataset v3.0 为处理大型 dataset 带来了显著改进:
dataset.meta.episodes 直接访问 pandas DataFrame在迁移大型 dataset 之前,请确保你具备:
DROID 1.0.1 是一个大规模机器人 dataset 的绝佳示例:
gsutil 公开访问该 dataset 包含多样的操作 demonstration,包括:
DROID_FEATURES = {
# Episode markers
"is_first": {"dtype": "bool", "shape": (1,)},
"is_last": {"dtype": "bool", "shape": (1,)},
"is_terminal": {"dtype": "bool", "shape": (1,)},
# Language instructions
"language_instruction": {"dtype": "string", "shape": (1,)},
"language_instruction_2": {"dtype": "string", "shape": (1,)},
"language_instruction_3": {"dtype": "string", "shape": (1,)},
# Robot state
"observation.state.gripper_position": {"dtype": "float32", "shape": (1,)},
"observation.state.cartesian_position": {"dtype": "float32", "shape": (6,)},
"observation.state.joint_position": {"dtype": "float32", "shape": (7,)},
# Camera observations
"observation.images.wrist_left": {"dtype": "image"},
"observation.images.exterior_1_left": {"dtype": "image"},
"observation.images.exterior_2_left": {"dtype": "image"},
# Actions
"action.gripper_position": {"dtype": "float32", "shape": (1,)},
"action.cartesian_position": {"dtype": "float32", "shape": (6,)},
"action.joint_position": {"dtype": "float32", "shape": (7,)},
# Standard LeRobot format
"observation.state": {"dtype": "float32", "shape": (8,)}, # joints + gripper
"action": {"dtype": "float32", "shape": (8,)}, # joints + gripper
}对于 DROID 而言:
pip install tensorflow pip install tensorflow_datasets
对于其他 dataset,请安装适合你源格式的读取器。
使用 gsutil 从 Google Cloud Storage 下载 DROID:
# Install Google Cloud SDK if not already installed
# https://cloud.google.com/sdk/docs/install
# Download the full RLDS dataset (1.7TB)
gsutil -m cp -r gs://gresearch/robotics/droid/1.0.1 /your/data/
# Or download just the 100-episode sample (2GB) for testing
gsutil -m cp -r gs://gresearch/robotics/droid_100 /your/data/大型 dataset 需要大量时间和存储空间:
- 完整 DROID (1.7TB):取决于带宽,下载需要数天
- 处理时间:本地迁移完整 dataset 需要 7 天以上
- 上传时间:推送到 Hugging Face Hub 需要 3 天以上
- 本地存储:处理后的 LeRobot 格式约 400GB
python examples/port_datasets/port_droid.py \
--raw-dir /your/data/droid/1.0.1 \
--repo-id your_id/droid_1.0.1 \
--push-to-hub在开发阶段,你可以迁移单个分片:
python examples/port_datasets/port_droid.py \
--raw-dir /your/data/droid/1.0.1 \
--repo-id your_id/droid_1.0.1_test \
--num-shards 2048 \
--shard-index 0这种方法适用于较小的 dataset 或测试,但大型 dataset 需要集群计算。
对于 DROID 这样的大型 dataset,跨多个节点的并行处理可大幅缩短处理时间。
pip install datatrove # Hugging Face's distributed processing library查找你的分区信息:
sinfo --format="%R" # List available partitions
sinfo -N -p your_partition -h -o "%N cpus=%c mem=%m" # Check resources选择一个 CPU 分区 - dataset 迁移不需要 GPU。
python examples/port_datasets/slurm_port_shards.py \
--raw-dir /your/data/droid/1.0.1 \
--repo-id your_id/droid_1.0.1 \
--logs-dir /your/logs \
--job-name port_droid \
--partition your_partition \
--workers 2048 \
--cpus-per-task 8 \
--mem-per-cpu 1950M--workers:并行任务数量(DROID 的分片数量最多 2048)--cpus-per-task:建议 8 个 CPU 以并行化帧编码--mem-per-cpu:加载原始帧约需 16GB 总 RAM(8×1950M)先使用较少的 worker(例如 100)测试你的集群配置,然后再启动数千个任务。
查看正在运行的任务:
squeue -u $USER监控总体进度:
jobs_status /your/logs
查看单个任务日志:
less /your/logs/port_droid/slurm_jobs/JOB_ID_WORKER_ID.out
调试失败的任务:
failed_logs /your/logs/port_droid
所有迁移任务完成后:
python examples/port_datasets/slurm_aggregate_shards.py \
--repo-id your_id/droid_1.0.1 \
--logs-dir /your/logs \
--job-name aggr_droid \
--partition your_partition \
--workers 2048 \
--cpus-per-task 8 \
--mem-per-cpu 1950Mpython examples/port_datasets/slurm_upload.py \
--repo-id your_id/droid_1.0.1 \
--logs-dir /your/logs \
--job-name upload_droid \
--partition your_partition \
--workers 50 \
--cpus-per-task 4 \
--mem-per-cpu 1950M上传使用较少的 worker(50),因为它是网络受限而非计算受限。
你完成后的 dataset 将具有这种现代结构:
dataset/
├── meta/
│ ├── episodes/
│ │ └── chunk-000/
│ │ └── file-000.parquet # Episode metadata
│ ├── tasks.parquet # Task definitions
│ ├── stats.json # Aggregated statistics
│ └── info.json # Dataset information
├── data/
│ └── chunk-000/
│ └── file-000.parquet # Consolidated episode data
└── videos/
└── camera_key/
└── chunk-000/
└── file-000.mp4 # Consolidated video files这用高效的、大小最优的分块取代了旧的每 episode 一文件结构。
如果你有 v2.1 格式的现有 dataset,请使用迁移工具:
python src/lerobot/scripts/convert_dataset_v21_to_v30.py \
--repo-id your_id/existing_dataset这会自动:
Dataset v3.0 为大型 dataset 提供了显著改进: