# نقل مجموعات البيانات الكبيرة إلى مجموعة بيانات LeRobot الإصدار 3.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

تُقدّم مجموعة البيانات v3.0 تحسينات جوهرية في التعامل مع مجموعات البيانات الكبيرة:

### 🏗️ **تنظيم محسّن للملفات**

- **البنية القائمة على الملفات**: أصبحت الحلقات مجمّعة في ملفات مقسّمة بدلاً من ملفات حلقات فردية
- **أحجام ملفات قابلة للتخصيص**: لملفات البيانات والفيديو
- **كفاءة تخزين محسّنة**: ضغط أفضل وتقليل في الأعباء

### 📊 **إدارة البيانات الوصفية الحديثة**

- **بيانات وصفية مبنية على Parquet**: استبدال JSON Lines بتنسيق parquet الأكثر كفاءة
- **الوصول المهيكّل إلى الحلقات**: الوصول المباشر إلى إطار بيانات pandas عبر `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
```

اختر **تقسيم وحدة المعالجة المركزية** - لا حاجة إلى وحدة معالجة رسومات لنقل مجموعة البيانات.

### الخطوة 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 معالجات CPU لتوازي ترميز الإطارات
- **`--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) نظرًا لأنّه يعتمد على الشبكة وليس على الحساب.

## هيكل ملفات مجموعة البيانات 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
- يجمع الإحصاءات ويُنشئ إحصاءات لكل حلقة
- تحديث معلومات الإصدار

## فوائد الأداء

توفر مجموعة البيانات v3.0 تحسينات كبيرة للمجموعات الكبيرة من البيانات:

- **تحميل أسرع**: تقليل زمن التهيئة بنسبة 3 إلى 5 أضعاف
- **كفاءة الذاكرة**: استخدام أفضل للذاكرة العشوائية (RAM) من خلال تعيين الذاكرة
- **معالجة قابلة للتوسع**: يتعامل مع ملايين الحلقات بكفاءة
- **تحسين التخزين**: تقليل عدد الملفات وتحسين الضغط

