LeRobot documentation
LeRobotDataset v3.0
LeRobotDataset v3.0
LeRobotDataset v3.0 adalah format standar untuk data pembelajaran robot. Format ini menyediakan akses terpadu ke data deret waktu multi-modal, sinyal sensorimotor, dan video multi-kamera, serta metadata yang kaya untuk indeks, pencarian, dan visualisasi di Hugging Face Hub.
Untuk melihat apa yang dipegang oleh dataset dalam format ini sebelum membaca tentang tata letaknya, buka salah satu di LeRobot Dataset Visualizer: rekaman kamera, grafik state dan action yang tersinkronisasi, serta setiap episode, di browser. Lihat Explore a Dataset in the Browser.
Dokumentasi ini akan memandu Anda untuk:
- Memahami desain dan tata letak direktori v3.0
- Rekam dataset dan unggah ke Hub
- Muat dataset untuk pelatihan dengan
LeRobotDataset - Stream dataset tanpa mengunduh menggunakan
StreamingLeRobotDataset - Terapkan transformasi gambar untuk augmentasi data selama pelatihan
- Migrasikan dataset
v2.1yang ada kev3.0 - Eksperimen dengan format dan implementasi
LeRobotDatasetlainnya seperti Lance
Apa yang baru di v3
- Penyimpanan berbasis file: Banyak episode per file Parquet/MP4 (v2 menggunakan satu file per episode).
- Metadata relasional: Batas episode dan pencarian diselesaikan melalui metadata, bukan nama file.
- Streaming native Hub: Konsumsi dataset langsung dari Hub dengan
StreamingLeRobotDataset. - Mengurangi tekanan pada sistem file: Jumlah file yang lebih sedikit dan lebih besar ⇒ inisialisasi lebih cepat dan lebih sedikit masalah pada skala besar.
- Organisasi terpadu: Tata letak direktori yang rapi dengan templat jalur yang konsisten di seluruh data dan video.
- Backend penyimpanan dataset: Dataset juga dapat disimpan sebagai tabel LanceDB untuk akses acak dan indeks langsung dari penyimpanan objek (lihat backend dataset LanceDB).
Instalasi
LeRobotDataset v3.0 disertakan dalam lerobot >= 0.4.0. Ikuti Panduan Instalasi untuk menginstalnya.
Rekam dataset
Jalankan perintah di bawah ini untuk merekam dataset dengan SO-101 dan mendorongnya ke Hub:
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem585A0076841 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=my_awesome_leader_arm \
--display_data=true \
--dataset.repo_id=${HF_USER}/record-test \
--dataset.num_episodes=5 \
--dataset.single_task="Grab the black cube" \
--dataset.streaming_encoding=true \
--dataset.encoder_threads=2
# Optional: --dataset.rgb_encoder.vcodec=autoLihat panduan rekaman untuk detail lebih lanjut.
Desain format
Prinsip inti v3 adalah memisahkan penyimpanan dari API pengguna: data disimpan secara efisien (beberapa file besar), sementara API publik menyediakan akses tingkat episode yang intuitif.
v3 memiliki tiga pilar:
- Data tabular: Sinyal berdimensi rendah dan frekuensi tinggi (state, action, timestamp) yang disimpan dalam Apache Parquet. Akses dilakukan melalui memory-mapped atau streaming via stack
datasets. - Data visual: Bingkai kamera yang digabungkan dan dikodekan menjadi MP4. Bingkai dari episode yang sama dikelompokkan; video dipecah per kamera untuk ukuran yang praktis.
- Metadata: rekaman JSON/Parquet yang menjelaskan skema (nama fitur, dtype, bentuk), frame rate, statistik normalisasi, dan segmentasi episode (offset awal/akhir ke dalam file Parquet/MP4 bersama).
Untuk berskala hingga jutaan episode, baris tabular dan bingkai video dari beberapa episode digabungkan menjadi file yang lebih besar. Tampilan spesifik episode direkonstruksi melalui metadata, bukan batas file.
Struktur direktori (disederhanakan)
meta/info.json: skema kanonik (fitur, bentuk/dtype), FPS, versi codebase, dan template path untuk menemukan shard data/video.meta/stats.json: statistik fitur global (rata-rata/standar deviasi/min/maks) yang digunakan untuk normalisasi; diekspos sebagaidataset.meta.stats.meta/tasks.parquet: deskripsi tugas bahasa alami yang dipetakan ke ID integer untuk kebijakan yang dikondisikan tugas.meta/episodes/: catatan per episode (panjang, tugas, offset) yang disimpan sebagai Parquet chunked untuk skalabilitas.data/: shard Parquet per bingkai; setiap file biasanya berisi banyak episode.videos/: shard MP4 per kamera; setiap file biasanya berisi banyak episode.
Muat dataset untuk pelatihan
LeRobotDataset mengembalikan kamus Python berisi tensor PyTorch dan terintegrasi dengan torch.utils.data.DataLoader. Berikut adalah contoh kode yang menunjukkan penggunaannya:
import torch
from lerobot.datasets import LeRobotDataset
repo_id = "yaak-ai/L2D-v3"
# 1) Load from the Hub (cached locally)
dataset = LeRobotDataset(repo_id)
# 2) Random access by index
sample = dataset[100]
print(sample)
# {
# 'observation.state': tensor([...]),
# 'action': tensor([...]),
# 'observation.images.front_left': tensor([C, H, W]),
# 'timestamp': tensor(1.234),
# ...
# }
# 3) Temporal windows via delta_timestamps (seconds relative to t)
delta_timestamps = {
"observation.images.front_left": [-0.2, -0.1, 0.0] # 0.2s and 0.1s before current frame
}
dataset = LeRobotDataset(repo_id, delta_timestamps=delta_timestamps)
# Accessing an index now returns a stack for the specified key(s)
sample = dataset[100]
print(sample["observation.images.front_left"].shape) # [T, C, H, W], where T=3
# 4) Wrap with a DataLoader for training
batch_size = 16
data_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size)
device = "cuda" if torch.cuda.is_available() else "cpu"
for batch in data_loader:
observations = batch["observation.state"].to(device)
actions = batch["action"].to(device)
images = batch["observation.images.front_left"].to(device)
# model.forward(batch)Stream dataset selama pelatihan
Set --dataset.streaming=true untuk melatih tanpa terlebih dahulu mengunduh file Parquet dan video dari dataset. Episode diambil secara langsung ke dalam pool memori terbatas, dan setiap frame yang dipilih tetap dikunjungi tepat satu kali per epoch:
lerobot-train \
--dataset.repo_id=yaak-ai/L2D-v3 \
--dataset.streaming=true \
--policy.type=act \
--output_dir=outputs/train/act_streamingReader yang sama tersedia di Python, untuk dataset Hub dan untuk dataset yang disimpan di HF Storage Bucket:
from lerobot.datasets import StreamingLeRobotDataset
dataset = StreamingLeRobotDataset("yaak-ai/L2D-v3")
bucket_dataset = StreamingLeRobotDataset("my-org/my-bucket", repo_type="bucket")Dari CLI, pilih bucket dengan --dataset.repo_type=bucket atau --dataset.root=hf://buckets/my-org/my-bucket.
Lihat Training Dataset Streaming untuk cara worker dan shard dipetakan ke konkurensi streaming, indeks sidecar MP4, pengaturan memori, resume, dan pemecahan masalah.
Transformasi gambar
Transformasi gambar adalah augmentasi data yang diterapkan pada bingkai kamera selama pelatihan untuk meningkatkan ketahanan dan generalisasi model. LeRobot mendukung berbagai transformasi, termasuk penyesuaian kecerahan, kontras, saturasi, rona, dan ketajaman.
Menggunakan transformasi saat pembuatan/perekaman dataset
Saat ini, transformasi diterapkan hanya saat pelatihan, bukan saat perekaman. Saat Anda membuat atau merekam dataset, gambar mentah disimpan tanpa transformasi. Hal ini memungkinkan Anda untuk bereksperimen dengan augmentasi yang berbeda di kemudian hari tanpa perlu merekam ulang data.
Menambahkan transformasi ke dataset yang sudah ada (API)
Gunakan parameter image_transforms saat memuat dataset untuk pelatihan:
from lerobot.datasets import LeRobotDataset
from lerobot.transforms import ImageTransforms, ImageTransformsConfig, ImageTransformConfig
# Option 1: Use default transform configuration (disabled by default)
transforms_config = ImageTransformsConfig(
enable=True, # Enable transforms
max_num_transforms=3, # Apply up to 3 transforms per frame
random_order=False, # Apply in standard order
)
transforms = ImageTransforms(transforms_config)
dataset = LeRobotDataset(
repo_id="your-username/your-dataset",
image_transforms=transforms
)
# Option 2: Create custom transform configuration
custom_transforms_config = ImageTransformsConfig(
enable=True,
max_num_transforms=2,
random_order=True,
tfs={
"brightness": ImageTransformConfig(
weight=1.0,
type="ColorJitter",
kwargs={"brightness": (0.7, 1.3)} # Adjust brightness range
),
"contrast": ImageTransformConfig(
weight=2.0, # Higher weight = more likely to be selected
type="ColorJitter",
kwargs={"contrast": (0.8, 1.2)}
),
"sharpness": ImageTransformConfig(
weight=0.5, # Lower weight = less likely to be selected
type="SharpnessJitter",
kwargs={"sharpness": (0.3, 2.0)}
),
}
)
dataset = LeRobotDataset(
repo_id="your-username/your-dataset",
image_transforms=ImageTransforms(custom_transforms_config)
)
# Option 3: Use pure torchvision transforms
from torchvision.transforms import v2
torchvision_transforms = v2.Compose([
v2.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),
v2.GaussianBlur(kernel_size=3, sigma=(0.1, 2.0)),
])
dataset = LeRobotDataset(
repo_id="your-username/your-dataset",
image_transforms=torchvision_transforms
)Jenis transformasi yang tersedia
type dari sebuah transform dapat berupa kelas apa pun dari torchvision.transforms.v2, misalnya:
ColorJitter: Menyesuaikan kecerahan, kontras, saturasi, dan ronaSharpnessJitter: Menyesuaikan ketajaman gambar secara acakRandomAffine,RandomRotation: jitter geometrisGaussianNoise,MotionBlur,JPEGCompression,GaussianPatchBrightness,RandomShadow,CoarseDropout,GammaCorrection,PlanckianJitter: Efek kamera dan pencahayaan yang terlihat pada robot sungguhanIdentity: Tidak ada transformasi (berguna untuk pengujian)
Kelas torchvision.transforms.v2 lainnya juga dapat ditunjuk sebagai type (misalnya RandomResizedCrop atau GaussianBlur); transformasi ini diterapkan satu per satu pada setiap sampel. Anda juga dapat meneruskan transformasi torchvision secara langsung ke parameter image_transforms.
Setiap transform kini di-batch, dan transform yang di-batch sama dijalankan di kedua backend. Kelas per-sampel (SharpnessJitter, GaussianNoise, MotionBlur, GaussianPatchBrightness, RandomShadow, CoarseDropout, GammaCorrection, PlanckianJitter, RandomSubsetApply) dan make_transform_from_config tetap dapat diimpor sebagai front end yang tidak lagi didukung di atas pengganti Batched* mereka dan memperingatkan saat digunakan; mereka akan dihapus dalam rilis mendatang. ImageTransforms adalah torch.nn.Module biasa yang menerima tensor (C, H, W) atau (T, C, H, W). Konfigurasi yang menamai transform berdasarkan type tidak terpengaruh.
Perubahan perilaku untuk resep yang sudah ada. Pelatihan membaca frame sebagai
uint8, dan transformasi LeRobot selainColorJitter,RandomAffine, danRandomRotationsebelumnya mengembalikan input non-float tanpa perubahan. Oleh karena itu, resep yang mengaktifkanGaussianNoise,MotionBlur,GaussianPatchBrightness,RandomShadow,CoarseDropout,GammaCorrection, atauPlanckianJittersebelumnya dilatih tanpa transformasi tersebut. Sekarang transformasi ini diterapkan di kedua backend, sehingga resep seperti itu akan dilatih dengan cara yang berbeda dari sebelumnya: ia mendapatkan augmentasi yang diminta. Transformasi yang sudah diterapkan sebelumnya tidak berubah, kecuali pembulatan, karena jalur batched menghitung dalam float dan membulatkan sekali di akhir, bukan setelah setiap transformasi.
Opsi konfigurasi
enable: Mengaktifkan/menonaktifkan transformasi (default:False)max_num_transforms: Jumlah maksimum transformasi yang diterapkan per frame (default:3)random_order: Terapkan transformasi dalam urutan acak vs. urutan standar (default:False)weight: Probabilitas sampling untuk setiap transform (lebih tinggi = lebih mungkin, jika jumlah bobot tidak sama dengan 1, bobot akan dinormalisasi)kwargs: Parameter spesifik transformasi (misalnya, rentang kecerahan)backend: Tempat transformasi dijalankan selama pelatihan,"dataloader"(default) atau"gpu"; lihat di bawahgpu_compile: Pada backend"gpu",torch.compiletransform yang di-batch (default:True)gpu_chunk_size: Pada backend"gpu", tingkatkan sejumlah sampel ini sekaligus untuk membatasi memori transien (default:32)
Menjalankan transformasi di GPU
Secara default, transformasi dijalankan per sampel di dalam worker DataLoader. Dengan beberapa kamera, hal ini sering menjadi bagian paling mahal yang dilakukan worker, sehingga GPU akhirnya menunggu data. Atur backend=gpu agar worker hanya melakukan decode dan menerapkan transformasi yang sama ke setiap batch pada perangkat policy:
lerobot-train \
--dataset.repo_id=your-username/your-dataset \
--dataset.image_transforms.enable=true \
--dataset.image_transforms.backend=gpu \
--policy.type=act \
--policy.device=cudaRandomisasi tidak berubah: setiap sampel menarik transformasi dan parameternya sendiri, dan frame dari riwayat satu kamera membaginya. Augmentasi hanya diterapkan pada batch pelatihan, sebelum preprocessor kebijakan; batch evaluasi, rollout, dan checkpoint yang disimpan tidak diubah.
Hal yang perlu diketahui:
- Memerlukan akselerator;
--policy.device=cpuditolak. Dataset yang dibuat secara manual dengan callableimage_transformsmiliknya sendiri juga ditolak, karena callable tersebut dijalankan di dalam worker. - Mendukung setiap jenis transformasi yang didukung oleh backend dataloader. Jenis yang tidak memiliki implementasi batched (
JPEGCompression, dan kelas torchvision selainColorJitter,RandomAffine,RandomRotation, danIdentity) diterapkan satu per satu di dalam batch, sehingga tidak mendapatkan percepatan;JPEGCompressionjuga melakukan round-trip melalui CPU. Transformasi yang mengubah ukuran frame ditolak pada batch yang berisi lebih dari satu sampel. - Dapat direproduksi dari
--seed, dengan setiap proses diberi seed yang berbeda. Augmentation tidak mengonsumsi stream acak dari policy, dangpu_compilesertagpu_chunk_sizetidak mengubah apa yang diterapkan. - Kedua backend menjalankan transform batched yang sama dalam float dan melakukan pembulatan sekali di akhir, sehingga sampel yang ditingkatkan pada satu backend sama dengan sampel yang sama yang ditingkatkan pada backend lainnya, asalkan parameter yang diberikan sama.
gpu_compilememakan waktu 15-30 detik sekali per bentuk gambar. Memori puncak sekitar dua salinan float dari gambar batch ditambah beberapa salinan dari satu chunk; turunkangpu_chunk_sizejika memori terbatas.random_order=truemengalikan waktu transformasi denganmax_num_transforms.
Migrasi v2.1 → v3.0
Konverter mengagregasi file per episode menjadi shard yang lebih besar dan menulis offset/metadata episode. Konversi dataset Anda menggunakan instruksi di bawah ini.
# Convert an existing v2.1 dataset hosted on the Hub:
python -m lerobot.scripts.convert_dataset_v21_to_v30 --repo-id=<HF_USER/DATASET_ID>Fungsinya
- Mengagregasi file parquet:
episode_000000.parquet,episode_000001.parquet, … →file-000.parquet, … - Mengagregasi file mp4:
episode_000000.mp4,episode_000001.mp4, … →file-000.mp4, … - Perbarui
meta/episodes/*(Parquet berchunk) dengan panjang per episode, tugas, dan offset byte/frame.
Masalah Umum
Selalu panggil finalize() sebelum mendorong
Saat membuat atau merekam dataset, Anda harus memanggil dataset.finalize() untuk menutup penulis parquet dengan benar. Lihat PR #1903 untuk detail lebih lanjut.
from lerobot.datasets import LeRobotDataset
# Create dataset and record episodes
dataset = LeRobotDataset.create(...)
for episode in range(num_episodes):
# Record frames
for frame in episode_data:
dataset.add_frame(frame)
dataset.save_episode()
# Call finalize() when done recording and before push_to_hub()
dataset.finalize() # Closes parquet writers, writes metadata footers
dataset.push_to_hub()Mengapa ini diperlukan?
Dataset v3.0 menggunakan penulisan parquet inkremental dengan metadata yang dibuffer untuk efisiensi. Metode finalize():
- Membuang semua metadata episode yang dibuffer ke disk
- Menutup penulis parquet untuk menulis metadata footer, jika tidak file parquet akan rusak
- Memastikan dataset valid untuk dimuat
Tanpa memanggil finalize(), file parquet Anda akan tidak lengkap dan dataset tidak akan dimuat dengan benar.
Format dan implementasi lainnya
Backend dataset LanceDB
Dataset v3 juga dapat disimpan sebagai tabel LanceDB. LanceDB adalah data lakehouse multimodal yang dibangun di atas format Lance untuk pola akses AI: akses acak cepat ke baris mana pun beserta byte videonya, serta indeks skalar, vektor, dan teks penuh pada tabel yang sama, sehingga EDA, penambangan, kurasi, dan pelatihan dapat dijalankan langsung dari object storage. Tata letak ini mempertahankan meta/ tanpa perubahan dan menambahkan tabel frames untuk data tabular serta tabel videos yang menyimpan MP4 sebagai blob. "storage_format": "lance" di meta/info.json memilih pembaca; API LeRobotDataset, item, dan pipeline pelatihan tidak berubah.
- Latih langsung dari Hub atau HF Storage Buckets dengan GPU yang sudah terpasang. Frame acak dibaca langsung di tempatnya, hanya byte yang dibutuhkan oleh setiap batch, sehingga setiap batch merupakan pengacakan global dan tidak ada yang diunduh terlebih dahulu.
- Konversi dengan biaya sekitar salinan file. Video tidak di-encode ulang, sehingga item identik bit-for-bit dengan sumber. DROID mengonversi dalam 34 menit.
- Rekayasa fitur tanpa salinan (zero-copy). Tambahkan kolom seperti skor, embedding, atau label yang dikoreksi ke tabel yang dibaca oleh trainer, tanpa menulis ulang video atau menyalin dataset, lalu saring dan cari di atasnya menggunakan indeks. Pembaca mengabaikan kolom yang tidak dikenalnya.
Untuk cara kerjanya, benchmark, dan contoh, lihat panduan LanceDB LeRobot.
Fitur kamera harus didukung oleh video. Dataset yang menyimpan bingkai kamera sebagai gambar tidak didukung oleh pembaca dan perlu dikode ulang sebagai video sebelum konversi.
Membaca dataset Lance memerlukan ekstra lancedb (pip install "lerobot[lancedb]"). Format ini hanya dapat dibaca: rekam dan edit dataset dalam format default, lalu konversikan dengan paket lerobot-lancedb:
pip install "lerobot-lancedb"
lerobot-lance-convert --repo-id lerobot/pusht --out ./pusht-lance # or --root <local dataset dir>Loading menggunakan kelas yang sama:
from lerobot.datasets import LeRobotDataset
# Hub dataset repo
dataset = LeRobotDataset("lance-format/pusht-lance")
# HF Storage Bucket, read in place
dataset = LeRobotDataset("my-org/pusht-lance", repo_type="bucket")
# the same bucket as a root URI (other object store URIs work the same way)
dataset = LeRobotDataset("lerobot/pusht", root="hf://buckets/my-org/pusht-lance")Opsi HF Storage Bucket berfungsi di lerobot-train:
lerobot-train \ --dataset.repo_id=my-org/pusht-lance \ --dataset.repo_type=bucket \ --policy.type=act
Visualisasi berfungsi dengan kedua viewer. lerobot-dataset-viz --repo-id lance-format/pusht-lance --episode-index 0 membuka episode di Rerun seperti biasa, dan --display-mode foxglove menyajikannya ke Foxglove melalui WebSocket. Dalam kedua cara tersebut, hanya frame yang ada di layar yang diambil, tanpa ekspor atau unduhan MCAP.