# Портинг больших датасетов в LeRobot Dataset v3.0

В этом руководстве объясняется, как перенести крупные робототехнические датасеты в формат LeRobot Dataset v3.0. В качестве основного примера мы будем использовать датасет **DROID 1.0.1**, который демонстрирует работу с наборами данных объёмом в несколько терабайт, содержащими тысячи шардов на кластерах SLURM.

## Организация файлов: v2.1 и v3.0

Dataset v3.0 принципиально меняет способ организации и хранения данных:

**Структура v2.1 (на основе эпизодов)**:

```
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
```

Такой переход от отдельных файлов эпизодов к файловым чанкам значительно повышает производительность и снижает накладные расходы на хранение.

## Что нового в Dataset v3.0

Dataset v3.0 вносит значительные улучшения для работы с большими наборами данных:

### 🏗️ **Улучшенная организация файлов**

- **Файловая структура**: эпизоды теперь сгруппированы в файлы с чанками, а не в отдельные файлы эпизодов
- **Настраиваемые размеры файлов**: для файлов данных и видео
- **Повышенная эффективность хранения**: лучшее сжатие и снижение накладных расходов

### 📊 **Современное управление метаданными**

- **Метаданные на основе Parquet**: JSON Lines заменён на эффективный формат parquet
- **Структурированный доступ к эпизодам**: прямой доступ к pandas DataFrame через `dataset.meta.episodes`
- **Статистика по эпизодам**: улучшенный учёт статистики на уровне эпизода

### 🚀 **Улучшения производительности**

- **Доступ с отображением в память**: улучшенное использование ОЗУ за счёт отображения памяти PyArrow
- **Более быстрая загрузка**: значительное сокращение времени инициализации набора данных
- **Повышенная масштабируемость**: Разработано для наборов данных с миллионами эпизодов

## Предварительные требования

Перед переносом больших наборов данных убедитесь, что у вас есть:

- **LeRobot установлен** с поддержкой v3.0. Следуйте нашему [Руководству по установке](./installation).
- **Достаточный объём хранилища**: исходные наборы данных могут быть очень большими (например, DROID требует 2 ТБ)
- **Доступ к кластеру** (рекомендуется для больших наборов данных): SLURM или аналогичный планировщик заданий
- **Зависимости, специфичные для набора данных**: для DROID вам понадобятся утилиты TensorFlow Dataset

## Понимание набора данных DROID

[DROID 1.0.1](https://droid-dataset.github.io/droid/the-droid-dataset) — отличный пример крупномасштабного набора данных для робототехники:

- **Размер**: 1,7 ТБ (формат RLDS), 8,7 ТБ (исходные данные)
- **Структура**: 2048 заранее определённых фрагментов набора данных TensorFlow
- **Содержание**: более 76 000 траекторий манипуляций роботов Franka Emika Panda
- **Область применения**: задачи манипуляции в реальных условиях в нескольких средах и с различными объектами
- **Формат**: изначально в формате TensorFlow Records/RLDS, требуется конвертация в формат LeRobot
- **Хостинг**: Google Cloud Storage с публичным доступом через `gsutil`

Набор данных содержит разнообразные демонстрации манипуляций с:

- Несколько видов с камер (камера на запястье, внешние камеры)
- Описания задач обработки естественного языка
- Собственная чувствительность и действия робота
- Аннотации об успехе/неудаче

### Схема функций DROID

```python
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": "video", "shape": (180, 320, 3), "names": ["height", "width", "channels"]},
    "observation.images.exterior_1_left": {"dtype": "video", "shape": (180, 320, 3), "names": ["height", "width", "channels"]},
    "observation.images.exterior_2_left": {"dtype": "video", "shape": (180, 320, 3), "names": ["height", "width", "channels"]},

    # 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
}
```

## Подход 1: Перенос на один компьютер

### Шаг 1: Установка зависимостей

В частности, для DROID:

```bash
pip install tensorflow
pip install tensorflow_datasets
```

Для других наборов данных установите соответствующие модули чтения для вашего исходного формата.

### Шаг 2: Загрузка исходных данных

Скачайте DROID из Google Cloud Storage с помощью `gsutil`:

```bash
# 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/
```

> [!WARNING]
> Большие наборы данных требуют значительного времени и места для хранения:
>
> - **Полный DROID (1,7 ТБ)**: загрузка занимает несколько дней в зависимости от пропускной способности канала - **Время обработки**: более 7 дней для локальной переработки полного набора данных - **Время загрузки**: более 3 дней для отправки на Hugging Face Hub - **Локальное хранилище**: ~400 ГБ для обработанного формата LeRobot

### Шаг 3: Перенос набора данных

```bash
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
```

### Разработка и тестирование

Для разработки можно перенести один шард:

```bash
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
```

Этот подход подходит для небольших наборов данных или тестирования, но для больших наборов данных требуется кластерное вычисление.

## Подход 2: перенос на кластер SLURM (рекомендуется)

Для больших наборов данных, таких как DROID, параллельная обработка на нескольких узлах значительно сокращает время обработки.

### Шаг 1: Установка зависимостей кластера

```bash
pip install datatrove  # Hugging Face's distributed processing library
```

### Шаг 2: Настройка окружения SLURM

Найдите информацию о вашем разделе:

```bash
sinfo --format="%R"  # List available partitions
sinfo -N -p your_partition -h -o "%N cpus=%c mem=%m"  # Check resources
```

Выберите **CPU partition** — для переноса набора данных GPU не требуется.

### Шаг 3: Запуск параллельных задач переноса

```bash
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`**: количество параллельных задач (максимум 2048 для количества шардов DROID)
- **`--cpus-per-task`**: рекомендуется 8 ЦП для параллельного кодирования кадров
- **`--mem-per-cpu`**: ~16 ГБ общей оперативной памяти (8×1950M) для загрузки необработанных кадров

> [!TIP]
> Начните с меньшего количества воркеров (например, 100), чтобы протестировать конфигурацию кластера перед запуском тысяч задач.

### Шаг 4: Отслеживание прогресса

Проверка запущенных задач:

```bash
squeue -u $USER
```

Контроль общего прогресса:

```bash
jobs_status /your/logs
```

Просмотреть логи отдельных заданий:

```bash
less /your/logs/port_droid/slurm_jobs/JOB_ID_WORKER_ID.out
```

Отладка неудачных заданий:

```bash
failed_logs /your/logs/port_droid
```

### Шаг 5: Агрегация шардов

После завершения всех задач по переносу:

```bash
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 1950M
```

### Шаг 6: Загрузка в Hub

```bash
python 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
```

> [!NOTE]
> Загрузка использует меньше рабочих процессов (50), так как она ограничена сетью, а не вычислительными мощностями.

## Структура файлов Dataset v3.0

Ваш готовый набор данных будет иметь следующую современную структуру:

```
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
```

Это заменяет старую структуру «один эпизод на файл» эффективными блоками оптимального размера.

## Переход с Dataset v2.1

Если у вас есть существующие наборы данных в формате v2.1, используйте инструмент миграции:

```bash
python src/lerobot/scripts/convert_dataset_v21_to_v30.py \
    --repo-id your_id/existing_dataset
```

Это автоматически:

- Преобразует структуру файлов в формат v3.0
- Перенос метаданных из JSON Lines в parquet
- Собирает статистику и создаёт статистику по эпизодам
- Обновление информации о версии

## Преимущества производительности

Dataset v3.0 обеспечивает значительные улучшения для больших наборов данных:

- **Более быстрая загрузка**: сокращение времени инициализации в 3–5 раз
- **Эффективность использования памяти**: лучшее использование ОЗУ за счёт отображения памяти
- **Масштабируемая обработка**: Эффективно обрабатывает миллионы эпизодов
- **Оптимизация хранилища**: уменьшено количество файлов и улучшено сжатие

