Сторінка посібника AY-Robots для навчання GR00T N1.7 на руці SO-100, що показує необхідний рівень GPU, формат набору даних та налаштування тренера за замовчуванням
GR00T N1.7SO-100ДоопрацюванняLeRobotVLA

Як навчити GR00T N1.7 на власному наборі даних SO-100

AY-Robots ResearchAugust 23, 202628 хв читання

Перевірений покроковий посібник для доопрацювання NVIDIA GR00T N1.7 на наборі даних LeRobot SO-100: реальні прапорці, modality.json, вимога v2.1, скільки коштує запуск та підводні камені.

NVIDIA постачає приклад тонкого налаштування саме для тієї руки, яку ви, ймовірно, маєте. У репозиторії Isaac-GR00T є папка під назвою demo_data/cube_to_bowl_5: п'ять епізодів, 4148 кадрів зі швидкістю 30 кадрів/с, вже записані як LeRobot v2.1, з відповідною конфігурацією модальності в examples/SO100/. Його meta/info.json повідомляє robot_type: so101_follower, що в LeRobot є тим самим класом конфігурації, що й so100_follower. Це справді корисно, оскільки це означає, що еталонний шлях для GR00T N1.7 на шести-ступенях свободи хобі-руки підтримується людьми, які написали модель. Це не зменшена демонстрація гуманоїда, це та сама рука.

Погана новина полягає у відстані між I recorded 60 episodes та the arm does the task. Існує близько шести місць, де цей конвеєр тихо, а не голосно, виходить з ладу, і чотири з них знаходяться у файлах, які більшість людей ніколи не відкривають: meta/modality.json, конфігурація даних Python, meta/relative_stats.json, та власний рядок версії набору даних. Цей посібник проходить ручний шлях від початку до кінця з реальними командами, а потім показує ту саму роботу як форму на AY-Robots. Усе нижче було перевірено на відповідність головній гілці Isaac-GR00T станом на 20 серпня 2026 року (лінія n1.7-release) та lerobot 0.6.1, опублікованому на PyPI 3 серпня 2026 року. Розробка відбувається швидко, і якщо прапор було перейменовано, ця стаття про це повідомляє.

Що потрібно знати перед початком

  • Для тонкого налаштування GR00T N1.7 потрібно 40 ГБ або більше VRAM. NVIDIA рекомендує вузли H100 або L40. RTX 4090 з 24 ГБ не впорається з цим завданням, хоча вона може тренувати SmolVLA та ACT.
  • Набір даних має бути LeRobot v2 (v2.0 або v2.1) плюс GR00T-специфічний meta/modality.json. Набір даних LeRobot v3.0 не завантажується і має бути конвертований до нижчої версії.
  • Точкою входу є gr00t/experiment/launch_finetune.py, CLI tyro. Він не має прапора --seed, тому запуски не є побітово відтворюваними.
  • Для кастомної руки тег втілення — NEW_EMBODIMENT, і цей тег робить --modality-config-path обов'язковим.
  • Постачаний рецепт SO-100 передбачає суглоби руки як ВІДНОСНІ дельти, а захват — як АБСОЛЮТНУ ціль. Зворотне поєднання є тихою відмовою, а не помилкою.
  • На AY-Robots та сама робота є формою: 20000 steps, batch 32, learning rate 1e-4, приблизно 4 to 12 USD на рівні A100 80 GB або H100.

Що насправді є GR00T N1.7

GR00T N1.7 — це візуально-мовна модель дій з двосистемною архітектурою, описаною в оригінальній статті GR00T N1: візуально-мовний модуль, який зчитує дані з камер та інструкції, і дифузійний трансформер, який перетворює це на блок безперервних моторних команд. N1.7 замінив першу половину. Основа Eagle з N1.6 зникла, замінена на nvidia/Cosmos-Reason2-2B на архітектурі Qwen3-VL, і модель була попередньо навчена на приблизно 20 000 годин егоцентричного людського відео на додаток до даних робота. Власна публікація NVIDIA вказує цифру 20 854 години та повідомляє, що перехід від 1 тис. до 20 тис. годин більш ніж подвоює середнє виконання завдань.

Друга половина також змінилася, і це важливо для вашого запуску. Голова дій зменшилася з 32 дифузійних шарів до 16, передбачуваний блок дій зріс з 16 кроків до 40, а максимальна ширина стану та дії збільшилася з 29 до 132. Ці три числа взяті з журналу змін у README репозиторію; власна публікація NVIDIA все ще описує Систему 1 як 32-шаровий DiT, тому там, де вони розходяться, довіряйте репозиторію, який ви збираєтеся клонувати. Дії за замовчуванням виражаються у відносному просторі кінцевого ефектора, дельтами від поточної пози, а не абсолютними цілями, що дозволяє переносити попередні знання про маніпуляції, отримані з людського відео, у керування роботом. Сама голова є зіставлення потоків дифузійним трансформером, тієї ж родини, що й Pi0.5, але з іншою основою перед ним. Якщо ви все ще використовуєте попереднє покоління, N1.7 проти N1.5 охоплює, чи виправдовує оновлення переробку вашого конвеєра.

ВластивістьЗначенняДжерело
Параметри3,000,000,000Картка моделі Hugging Face
Візуально-мовна основаnvidia/Cosmos-Reason2-2B (Qwen3-VL), gated on Hugging FaceREADME репозиторію
Голова дійFlow-matching diffusion transformer, 16 layers (N1.6 had 32)README репозиторію
Прогнозований горизонт дій40 steps for the base checkpoint (N1.6 had 16)getting_started/policy.md та README репозиторію
Максимальна ширина стану та дії132 (N1.6 had 29)README репозиторію
Ліцензія на кодApache 2.0Репозиторій Isaac-GR00T
Ліцензія на вагиNVIDIA Open Model License Agreementкартка моделі
Затримка, H100 80 ГБ, PyTorch eager, 4 кроки денойзингу, 1 камера85.8 ms end to end, 11.7 Hzтаблиця часу картки моделі
Те саме обладнання, повний конвеєр TensorRT27.9 ms end to end, 35.9 Hzтаблиця часу картки моделі
Затримка, яку AY-Robots вказує для свого розгорнутого GR00T N1.7152 ms per action stepКаталог політик AY-Robots

Ці останні три рядки пояснюють більшість розчарувань, про які повідомляють люди. Заявлені 27.9 мс — це рушій TensorRT на H100 з однією камерою та чотирма кроками денойзингу. Звичайний PyTorch на тій самій карті становить 85.8 мс, і картка моделі вказує на розрив у 3.08x. Жодне з цих чисел не включає шар обслуговування, другу камеру або мережевий стрибок. 152 мс на крок дії, які AY-Robots вказує для свого розгорнутого GR00T N1.7, — це показник з обслуговуванням у циклі, і до цього додається час на передачу даних через публічний інтернет. Докладніше про це в кінці. Щодо чисел поруч з іншими моделями, GR00T N1.7 проти Pi0.5 та GR00T N1.7 проти SmolVLA порівнюють їх пліч-о-пліч.

Сторінка моделі AY-Robots для GR00T N1.7, що показує кількість параметрів, рівень GPU, затримку висновку та заявлені сильні сторони та обмеження моделі
Сторінка /policies/groot-n1-7 містить ту саму смугу специфікацій, яку ви б інакше збирали вручну з картки моделі та файлу README репозиторію.

Що потрібно для запуску, перш ніж щось вводити

ВимогаДоопрацюванняВисновок
VRAM, рекомендації NVIDIA40 ГБ або більше, рекомендовано H100 або L4016 ГБ або більше, працює RTX 4090
Python та CUDA на dGPU3.12 and CUDA 12.83.12 and CUDA 12.8
Відео бекендtorchcodec 0.8.0, FFmpeg 4 to 7 onlyте саме
Формат набору данихLeRobot v2 plus meta/modality.jsonне застосовується
Доступ до Hugging Faceapproved for nvidia/Cosmos-Reason2-2Bте саме
Інші інструментиgit-lfs and uvuv
Рівень GPU AY-Robots для тренера groot1.7A100 80 GB or H100 80 GBпод надається автоматично
Закритий бекбон зупинить вас під час першого запуску

Кожен чекпоінт GR00T, включаючи базовий nvidia/GR00T-N1.7-3B, завантажує nvidia/Cosmos-Reason2-2B при першому використанні, і цей репозиторій є закритим. Файл README точно вказує на помилку: завантаження моделі не вдається з GatedRepoError / 401 Client Error. Що не згадується, так це коли це відбувається, а саме після того, як ви орендували карту і запуск розпочався. Запитайте доступ на сторінці моделі, потім запустіть uv run huggingface-cli login або експортуйте HF_TOKEN, перш ніж щось орендувати.

Крок 0: самі епізоди

Все нижчезазначене передбачає, що ви вже записали епізоди. Якщо ні, то це справжній перший крок, і саме він вирішує, наскільки хорошим може бути результат, тому що імітаційне навчання не може відновити інформацію, якої немає в даних. Спочатку відкалібруйте обидві руки, потім керуйте веденим маніпулятором за допомогою ведучого маніпулятора поки lerobot-record записує файли parquet та потоки з камер. Якщо калібрування вимкнено, значення суглобів у вашому наборі даних описують дещо іншого робота, ніж той, який пізніше виконуватиме політику, і жодна кількість тренувань цього не виправить.

bash
lerobot-record \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.id=my_follower_arm \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}" \
    --teleop.type=so100_leader \
    --teleop.port=/dev/ttyACM1 \
    --teleop.id=my_leader_arm \
    --dataset.repo_id=${HF_USER}/cube-into-bowl \
    --dataset.num_episodes=60 \
    --dataset.single_task="put the cube in the yellow bowl" \
    --display_data=true
lerobot-record на поточному LeRobot. Довжина епізоду за замовчуванням становить 60 с, а час скидання — 60 с. so100_follower та so101_follower обидва зареєстровані в одному класі конфігурації LeRobot, тому приклад Isaac-GR00T SO100 використовує назви so101; обидва працюють на SO-100. Назви камер, які ви обираєте тут (front, wrist), — це назви, які мають знову з'явитися в modality.json.

Власна порада LeRobot полягає в тому, щоб записати щонайменше 50 епізодів, приблизно по 10 на кожне місце розташування об'єкта, тримати камери нерухомими та підтримувати послідовну поведінку захоплення. Додавайте варіації пізніше, а не на початку. Варто пам'ятати правило: якщо ви не змогли виконати завдання самостійно, лише за зображеннями з камери, то політика також не зможе. Для налаштування, специфічного для маніпулятора, початок роботи з SO-100 та сторінка LeRobot для SO-100 охоплюють порти, калібрування та індекси камер. На AY-Robots ви також можете зробити це через інтернет з браузера, використовуючи телеоперацію і записувати безпосередньо з сесії.

Крок 1: набір даних має бути LeRobot v2.1

Це найпоширеніша перешкода. Поточна CODEBASE_VERSION LeRobot у гілці main — це v3.0, тому все, що ви записуєте сьогодні за допомогою поточного набору інструментів, виходить як v3.0. Завантажувач GR00T очікує v2. Репозиторій чітко пояснює, чому: багато вихідних наборів даних, таких як DROID, LIBERO та Bridge, опубліковані у v2, і нативна підтримка обох планується, але ще не реалізована. Отже, конвертація лежить на вас, і вона запускається у власному віртуальному середовищі з конкретної причини: scripts/lerobot_conversion має власний pyproject, який вимагає Python 3.10 або 3.11 і прив'язує lerobot до одного git-коміту, тоді як сам Isaac-GR00T вимагає Python 3.12. Встановіть конвертер з кореня репозиторію, і ви отримаєте пакет gr00t замість того, що є помилкою, про яку попереджає його README. Якщо ви новачок у цьому форматі, запис у глосарії набір даних LeRobot пояснює, що насправді знаходиться всередині.

bash
# from the Isaac-GR00T repo root
cd scripts/lerobot_conversion
uv venv
source .venv/bin/activate
uv pip install -e . --verbose

# pulls the dataset from the Hub and writes a v2.1 copy into the default cache
python convert_v3_to_v2.py --repo-id <your-hf-user>/<your-dataset>

# or, back in the repo root, keep it next to the SO-100 example
uv run --project scripts/lerobot_conversion \
  python scripts/lerobot_conversion/convert_v3_to_v2.py \
  --repo-id <your-hf-user>/<your-dataset> \
  --root examples/SO100/my_dataset_lerobot
Конвертер приймає --repo-id, необов'язковий --root та --force-conversion, який видаляє будь-який існуючий локальний знімок і завантажує його повторно. Він записує codebase_version: v2.1 у meta/info.json.
Конвертація перезаписує на місці

Якщо набір даних v3.0 вже існує локально, скрипт створює макет v2.1 поруч з ним, а потім міняє місцями: оригінал переміщується до сусідньої папки з доданою версією, <name>_v3.0, а конвертована копія займає оригінальний шлях. (Власний docstring скрипта називає цю папку _v30; код додає рядок версії, тому ви насправді отримуєте _v3.0.) Другий сюрприз: вихідні дані завжди потрапляють у <root>/<repo-id>, тому --root examples/SO100/my_dataset_lerobot дає вам examples/SO100/my_dataset_lerobot/<your-hf-user>/<your-dataset>, і цей довший шлях є тим, що --dataset-path вимагатиме пізніше. Коли завдання навчання відхиляє ваш набір даних через причини версії, сторінка про відхилення набору даних як v3 перераховує точні симптоми.

Структура, яку GR00T очікує після конвертації, — це класичний макет v2: meta/info.json, meta/episodes.jsonl, meta/tasks.jsonl, файли parquet у data/chunk-000/, файли MP4 у videos/chunk-000/observation.images./, і один додатковий файл, якого немає у стандартному LeRobot. Саме в цьому додатковому файлі міститься більшість решти помилок.

Крок 2: modality.json, шість чисел, які вирішують усе

У наборі даних LeRobot стан робота та дія зберігаються як плоскі масиви float32. Для SO-100 обидва мають форму [6]: п'ять суглобів руки та захват. Демонстраційний набір даних називає їх shoulder_pan.pos, shoulder_lift.pos, elbow_flex.pos, wrist_flex.pos, wrist_roll.pos, gripper.pos, але ці назви знаходяться в info.json і ніщо у файлі parquet не вказує, який індекс є яким. meta/modality.json надає це відображення, і GR00T не буде навчатися без нього. Ось той, що постачається репозиторієм для SO-100, дослівно.

json
{
  "state": {
    "single_arm": {
      "start": 0,
      "end": 5
    },
    "gripper": {
      "start": 5,
      "end": 6
    }
  },
  "action": {
    "single_arm": {
      "start": 0,
      "end": 5
    },
    "gripper": {
      "start": 5,
      "end": 6
    }
  },
  "video": {
    "front": {
      "original_key": "observation.images.front"
    },
    "wrist": {
      "original_key": "observation.images.wrist"
    }
  },
  "annotation": {
    "human.task_description": {
      "original_key": "task_index"
    }
  }
}
examples/SO100/modality.json. Індекси нульові та відповідають зрізам Python, тому single_arm — це [0:5], а gripper — [5:6].

Скопіюйте його у ваш перетворений набір даних за адресою meta/modality.json і перейменуйте ключі відео відповідно до фактичних назв ваших камер. Якщо ви записували однією верхньою камерою під назвою top, тоді original_key є observation.images.top а зручна назва — це те, на що посилатиметься ваша конфігурація даних. Ці дві назви мають збігатися, і жодна з них не перевіряє іншу за вас. Анотація мови гірша, тому що один і той же ключ має з'являтися в трьох місцях.

РівеньФайлФорма SO-100, що використовується в репозиторії
Стовпець Parquetdata/chunk-*/episode_*.parquetannotation.human.task_description
Ключ modality.jsonmeta/modality.json, у розділі "annotation", без префіса annotation.human.task_description
modality_keys у конфігурації данихyour so100_config.pyannotation.human.task_description
Чому мовний ключ викликає проблеми

Сегменти після annotation. обираються тим, хто створив набір даних. Демо-дані SO-100 використовують annotation.human.task_description; LIBERO та SimplerEnv використовують annotation.human.action.task_description. Обидва варіанти дійсні. Якщо ви скопіювали конфігурацію з прикладу LIBERO і вказали її на власний запис SO-100, мовний канал не розпізнається, і модель навчається на порожній інструкції. Втрати все одно зменшуються. Політика все одно щось робить. Вона просто ігнорує те, що ви їй сказали зробити.

Крок 3: конфігурація даних, відносна рука та абсолютний захват

Конфігурація модальності є файлом Python, а не JSON, оскільки вона також визначає, як представлена кожна група дій. Це та частина робочого процесу N1.7, яка не існувала в такій самій формі в N1.5, і та частина, яку варто прочитати двічі. Постачана конфігурація SO-100 передбачає п'ять суглобів руки як ВІДНОСНІ дельти від поточного стану, а захоплювач як АБСОЛЮТНУ цільову позицію, оскільки бінарний сигнал відкрито/закрито поводиться краще як ціль, ніж як дельта.

python
from gr00t.configs.data.embodiment_configs import register_modality_config
from gr00t.data.embodiment_tags import EmbodimentTag
from gr00t.data.types import (
    ActionConfig, ActionFormat, ActionRepresentation, ActionType, ModalityConfig,
)

so100_config = {
    "video": ModalityConfig(
        delta_indices=[0],                       # current frame only
        modality_keys=["front", "wrist"],        # must match modality.json
    ),
    "state": ModalityConfig(
        delta_indices=[0],
        modality_keys=["single_arm", "gripper"],
    ),
    "action": ModalityConfig(
        delta_indices=list(range(0, 16)),        # predict 16 future steps
        modality_keys=["single_arm", "gripper"],
        action_configs=[
            ActionConfig(rep=ActionRepresentation.RELATIVE,   # arm joints
                         type=ActionType.NON_EEF,
                         format=ActionFormat.DEFAULT),
            ActionConfig(rep=ActionRepresentation.ABSOLUTE,   # gripper
                         type=ActionType.NON_EEF,
                         format=ActionFormat.DEFAULT),
        ],
    ),
    "language": ModalityConfig(
        delta_indices=[0],
        modality_keys=["annotation.human.task_description"],
    ),
}

register_modality_config(so100_config, embodiment_tag=EmbodimentTag.NEW_EMBODIMENT)
examples/SO100/so100_config.py, скорочено до найважливішого. NON_EEF означає простір суглобів; EEF очікував би дев'ятивимірний вектор x, y, z плюс 6D обертання.

Дві деталі тут коштуватимуть вам дня, якщо ви їх не знаєте. По-перше, action_configs є позиційним: документація вимагає такої ж довжини та такого ж порядку, як modality_keys, і вони прямо говорять про наслідки помилки, яка полягає в тому, що неправильне представлення застосовується мовчазно. Ваш захоплювач навчається як дельта, а ваша рука як абсолютна ціль, і повідомлення про помилку відсутнє. По-друге, register_modality_config стверджує, що тег ще не зареєстрований, тому друга конфігурація NEW_EMBODIMENT в тому ж процесі Python завершується з помилкою Embodiment tag ... already registered. Ви не можете імпортувати дві такі конфігурації в один скрипт. Третє правило застосовується пізніше, під час розгортання: дія delta_indices повинна бути неперервним діапазоном, що починається з нуля. Розріджене вікно, таке як [0, 4, 8], відхиляється, оскільки все подальше індексує передбачений фрагмент лінійно і в іншому випадку виконало б неправильні рядки.

Змініть delta_indices, і ви повинні повторно згенерувати статистику

Статистика нормалізації, зокрема meta/relative_stats.json, обчислюється для довжини горизонту, яку ви мали під час їх генерації. Скоротіть горизонт дії з 16 до 8 без повторної генерації, і навчання завершиться з помилкою IndexError: boolean index did not match indexed array ... dimension is 8 but corresponding boolean dimension is 16. Виправлення полягає в одній команді: python gr00t/data/stats.py --dataset-path <path> --embodiment-tag NEW_EMBODIMENT --modality-config-path examples/SO100/so100_config.py. Запустіть її після будь-якої зміни delta_indices.

Крок 4: середовище

N1.7 перемістив репозиторій до та Python 3.12. Старий шлях conda плюс pip install -e . все ще існує у згорнутому розділі README, але він попереджає, що залежності GPU, включаючи flash-attn та TensorRT, можуть потребувати ручної установки. Використовуйте uv, якщо у вас немає конкретної причини не робити цього. Щодо flash-attn, одна деталь запобігає плутанині: ви побачите Installing flash-attn при кожному запуску uv run. Це не перезбірка. uv повторно перевіряє закріплений URL-адресою wheel, який вже кешований, і це займає дві-три секунди.

  1. 1
    Встановіть git-lfs, потім клонуйте з підмодулями

    git-lfs є обов'язковим, а не опціональним. Без нього файли parquet у demo_data/ завантажуються як заглушки-покажчики, і демонстраційний запуск завершується помилкою на наборі даних, який виглядає присутнім у списку файлів.

    bash
    sudo apt install git-lfs && git lfs install
    git clone --recurse-submodules https://github.com/NVIDIA/Isaac-GR00T
    cd Isaac-GR00T
  2. 2
    Встановіть uv та синхронізуйте середовище

    Установка за замовчуванням завантажує залежності GPU, включаючи flash-attn та TensorRT. На чистому образі A100 або H100 це найдовший окремий крок, тому виконайте його, перш ніж звертати увагу на щось інше.

    bash
    curl -LsSf https://astral.sh/uv/install.sh | sh
    sudo apt-get update && sudo apt-get install -y ffmpeg
    uv sync --python 3.12
    uv run python -c "import gr00t; print('GR00T installed successfully')"
  3. 3
    Автентифікація проти Hugging Face

    Зробіть це перед першим запуском навчання, а не після того, як воно завершиться помилкою через вісім хвилин.

    bash
    uv run huggingface-cli login   # or: export HF_TOKEN=<your_token>
  4. 4
    Перевірка працездатності на наданих демонстраційних даних SO-100

    Перш ніж торкатися власного запису, запустіть 2000 кроків на demo_data/cube_to_bowl_5. Це п'ять епізодів, він швидко завершується і доводить працездатність середовища, а не ваших даних. Якщо цей запуск завершиться помилкою, ніщо, що ви зробите зі своїм набором даних, не допоможе.

    bash
    CUDA_VISIBLE_DEVICES=0 uv run python \
        gr00t/experiment/launch_finetune.py \
        --base-model-path nvidia/GR00T-N1.7-3B \
        --dataset-path demo_data/cube_to_bowl_5 \
        --embodiment-tag NEW_EMBODIMENT \
        --modality-config-path examples/SO100/so100_config.py \
        --num-gpus 1 \
        --output-dir /tmp/test_finetune \
        --max-steps 2000 \
        --global-batch-size 32 \
        --dataloader-num-workers 4
Дві пастки середовища, які виглядають як помилки моделі

FFmpeg 8. torchcodec 0.8.0 підтримує лише FFmpeg 4 до 7, а Ubuntu 25.10 і новіші версії постачаються з версією 8. Помилка Could not load libtorchcodec, що виглядає як пошкоджена установка, а не конфлікт версій. Встановіть старішу версію, наприклад conda install -c conda-forge 'ffmpeg<8', і додайте її бібліотеки до LD_LIBRARY_PATH. CUDA_HOME не встановлено. Тонке налаштування повністю завершується помилкою. Запустіть bash scripts/deployment/dgpu/install_deps.sh один раз, або просто export CUDA_HOME=/usr/local/cuda.

Крок 5: команда тонкого налаштування та її фактичні значення за замовчуванням

Замініть демонстраційний набір даних на свій і додайте потрібні параметри. Нижче наведено повну форму, яку репозиторій використовує у власному посібнику з нового втілення, включаючи прапорці для аугментації та контрольних точок, які відсутні в короткому прикладі README. Це у вузькому сенсі: мовний каркас і візуальний кодер залишаються замороженими, а тренуються лише проектор і дифузійна головка дії.

bash
export NUM_GPUS=1
CUDA_VISIBLE_DEVICES=0 uv run python \
    gr00t/experiment/launch_finetune.py \
    --base-model-path nvidia/GR00T-N1.7-3B \
    --dataset-path ./my_dataset_lerobot \
    --embodiment-tag NEW_EMBODIMENT \
    --modality-config-path examples/SO100/so100_config.py \
    --num-gpus $NUM_GPUS \
    --output-dir /tmp/so100 \
    --save-total-limit 5 \
    --save-steps 2000 \
    --max-steps 20000 \
    --use-wandb \
    --global-batch-size 32 \
    --color-jitter-params brightness 0.3 contrast 0.4 saturation 0.5 hue 0.08 \
    --dataloader-num-workers 4
Одна відеокарта. Для восьми карт замініть запуск на uv run torchrun --nproc_per_node=8 --master_port=29500 і встановіть --num-gpus 8. Використовуйте uv run torchrun, а не просто torchrun, інакше ви отримаєте неправильне середовище.
ПрапорецьЗначення за замовчуванням у FinetuneConfigЩо він робить
--global-batch-size64Загальний розмір пакету для всіх GPU до накопичення градієнтів. Приклади, що постачаються, використовують 32.
--learning-rate1e-4Те саме значення, яке AY-Robots надсилає для свого тренера groot1.7.
--max-steps10000Загальна кількість кроків оптимізатора. Обгортка examples/finetune.sh також за замовчуванням встановлює 10000.
--gradient-accumulation-steps1Множить ефективний розмір пакету. Значення вище 1 видають попередження, що вказує на накопичений розмір.
--save-steps and --save-total-limit1000 and 5Частота збереження контрольних точок і скільки їх зберігається. Старіші видаляються.
--weight-decay and --warmup-ratio1e-5 and 0.05Також явно встановлюється за допомогою examples/finetune.sh.
--state-dropout-prob0.2 in the CLI, 0.8 in the model configВипадково відкидає пропріоцептивний стан під час навчання. Зменшіть його, якщо ваше завдання залежить від стану.
--tune-llm and --tune-visualFalse and FalseКаркас за замовчуванням залишається замороженим.
--tune-projector and --tune-diffusion-modelTrue and TrueПроектор і дифузійна головка дії — це те, що фактично тренується.
--use-percentilesTrueНормалізувати за допомогою q01 і q99 замість сирих мінімальних і максимальних значень.
--dataloader-num-workers2Завантажувач за задумом базується на CPU. Приклади збільшують це значення до 4.
--seeddoes not existУ цьому CLI немає прапорця seed.

Цей останній рядок — не помилка. launch_finetune.py — це CLI tyro, згенерований з dataclass, і цей dataclass не має поля seed. У README окремо зазначено 5-6 відсотків відхилення між запусками, спричинене недетермінованою аугментацією зображень. Два запуски з ідентичними прапорцями не дадуть ідентичних контрольних точок, що має велике значення, коли ви намагаєтеся вирішити, чи допомогла зміна гіперпараметра, чи вам просто пощастило. Для порівняння, власний тренажер lerobot за замовчуванням використовує seed 1000, а рецепт LeRobot GR00T явно передає --seed=42 явно.

Валідація вимкнена за замовчуванням, а задокументований прапорець відсутній у цьому CLI

Доопрацювання запускається з eval_strategy="no", тому кривої втрат валідації взагалі немає. Ви отримуєте лише втрати навчання і нічого більше. Посібник з нового втілення радить увімкнути його за допомогою --eval-strategy steps --eval-steps 500, але цей прапорець не існує в launch_finetune.py: CLI генерується tyro з dataclass FinetuneConfig, а eval_strategy, eval_steps та eval_batch_size є полями TrainingConfig. Їхні значення за замовчуванням там: "no", 500 та 2. Щоб отримати до них доступ, використовуйте повнішу точку входу gr00t/experiment/launch_train.py, де вкладений прапорець — --training.eval-strategy. У будь-якому випадку, саме по собі падіння втрат навчання мало що говорить про узагальнення, що є саме тією ситуацією, яка описана на втрати падають, але політика нічого не робить.

Скільки коштує запуск на 20000 кроків

GR00T N1.7 потрібна карта на 80 ГБ, тому питання вартості має вузьку відповідь. На AY-Robots тренажер groot1.7 працює на рівні A100 80 ГБ або H100 80 ГБ, де запуск займає від 3 до 6 годин за ціною від 1.20 до 2.00 USD за годину на спотовому ринку. Це приблизно від 4 до 12 USD за стандартне завдання на 20000 кроків. Те саме завдання на SmolVLA або ACT виконується на карті 24 ГБ за 0.30 до 0.60 USD за годину та 1 до 3 USD за запуск. Це справжній компроміс: GR00T коштує приблизно в чотири рази дорожче за спробу, і ви не можете запустити його на 4090 під своїм столом.

МодельРівень GPUТиповий запускТипова вартістьМінімальна кількість епізодів
GR00T N1.7A100 80 GB or H100 80 GB3 to 6 hours4 to 12 USD50
GR00T N1.5A100 80 GB or H100 80 GB3 to 6 hours4 to 12 USD50
Pi0.5A100 80 GB or H100 80 GB3 to 6 hours4 to 12 USD50
SmolVLARTX 4090 or any 24 GB card2 to 5 hours1 to 3 USD30
ACTRTX 4090 or any 24 GB card2 to 5 hours1 to 3 USD50

Мінімум у 50 епізодів — це мінімум, а не ціль. Власний FAQ NVIDIA є більш вимогливим: приблизно 100 траєкторій для простого захоплення та розміщення у фіксованому місці, 500 або більше для складних або багатоетапних сцен, і від 100 до 500 для точної маніпуляції. Якщо у вас є 20 епізодів, проведіть день за записом, а не вечір за налаштуванням. Посібник зі збору даних охоплює те, що відрізняє корисний епізод від марного, запишіть свій перший набір даних — це коротка версія, а збір даних SO-100 — це версія для конкретного маніпулятора.

Посібник з навчання AY-Robots для GR00T N1.7 на SO-100, що показує смугу специфікацій з рівнем GPU, необхідним форматом набору даних та значеннями за замовчуванням тренажера.
Посібник /train/groot-n1-7-on-so-100 починається з фактів, які інакше довелося б відновлювати вручну: рівень GPU, формат набору даних та точні значення за замовчуванням, які надсилає тренажер.

Крок 6: оцінка у відкритому циклі, перш ніж торкатися маніпулятора

Не ставте свіжий контрольний пункт на фізичну руку, щоб дізнатися, чи спрацювало навчання. Спочатку запустіть оцінку у відкритому циклі. Вона відтворює записаний епізод, запитує у моделі дії на кожному кроці та будує графік прогнозування порівняно з істинними даними з MSE та MAE. Це нічого не коштує і виявляє помилки відображення з кроків 2 і 3.

bash
uv run python gr00t/eval/open_loop_eval.py \
    --dataset-path ./my_dataset_lerobot \
    --embodiment-tag NEW_EMBODIMENT \
    --model-path /tmp/so100/checkpoint-20000 \
    --traj-ids 0 \
    --execution-horizon 16 \
    --steps 400 \
    --modality-keys single_arm gripper
Графіки зберігаються в /tmp/open_loop_eval/traj_<id>.jpeg, якщо ви не передасте --save-plot-path. За замовчуванням: --execution-horizon 16, --steps 200, --denoising-steps 4, --traj-ids 0.

Репозиторій свідомо відмовляється публікувати цільовий MSE для власних даних, і це правильне рішення: це число залежить від ваших одиниць дії, вашого завдання та розміру вашого набору даних, тому поріг, скопійований з чужої руки, нічого не означає. Значущим є тренд. Ось еталонний запуск, який репозиторій документує на одному H100 з демонстраційним набором даних з п'яти епізодів та 2000 кроками.

Контрольний пунктСередній MSE на траєкторії 0Середній MAE на траєкторії 0
50087.55.63
100025.43.30
150013.22.18
200010.01.76

Форма є сигналом, а не абсолютними значеннями. Помилка повинна стабільно зменшуватися, коли накопичуються. Усереднений за всіма п'ятьма епізодами навчання, а не лише за траєкторією 0, фінальний контрольний пункт репозиторію набрав приблизно 7.5 MSE та 1.5 MAE, тому навіть еталонний запуск інтерпретується по-різному залежно від того, які епізоди ви усереднюєте. Запишіть свій власний базовий показник за допомогою незміненої демонстраційної команди, перш ніж змінювати щось у своїх даних: якщо ви не можете відтворити відомий успішний запуск, ви не зможете відрізнити помилку налаштування від проблеми з даними. Репозиторій також зіставляє поширені симптоми з причинами, і кожен з них є операційним, а не помилкою моделі.

СимптомЙмовірна причина
MSE є стабільним або зростає між контрольними точкамиШвидкість навчання занадто низька, або дані взагалі не завантажуються. Перевірте --dataset-path та працівників завантажувача даних.
Крива прогнозу є плоскою або постійноюКлючі modality.json або --modality-config-path не збігаються. Ключі дій не зіставлені.
MSE величезне, або втрата NaN під час навчанняНормалізація дій та стану. Перевірте meta/stats та переконайтеся, що діапазони дій є фізично правдоподібними.
Добре на traj 0, погано на відкладених епізодахНестача даних, а не помилка. П'ять демонстраційних епізодів не можуть узагальнювати.

Інший шлях: lerobot-train замість Isaac-GR00T

Поточний реліз LeRobot, 0.6.1 на PyPI з 3 серпня 2026 року, пропонує другий і досить відмінний спосіб доналаштування тих самих базових ваг. LeRobot представляє GR00T N1.7 як тип політики та навчає його через власну lerobot-train точку входу. Тут важливі дві речі. CLI LeRobot — це набір консольних скриптів, тому все, що ви читаєте, де сказано python lerobot/scripts/train.py є застарілим і не працюватиме. А LeRobot повністю видалив підтримку GR00T N1.5, відхиляючи контрольні точки та конфігурації N1.5 з приміткою про міграцію, тому якщо вам потрібен N1.5 через LeRobot, вам доведеться закріпити lerobot==0.5.1, останній реліз, який його підтримує, опублікований 7 квітня 2026 року.

bash
pip install "lerobot[groot]" "lerobot[training]"
hf auth login

lerobot-train \
  --dataset.repo_id=$HF_USER/$DATASET_NAME \
  --dataset.image_transforms.enable=true \
  --policy.type=groot \
  --policy.device=cuda \
  --policy.base_model_path=nvidia/GR00T-N1.7-3B \
  --policy.embodiment_tag=new_embodiment \
  --policy.chunk_size=16 \
  --policy.n_action_steps=16 \
  --policy.use_relative_actions=true \
  --policy.relative_exclude_joints='["gripper"]' \
  --policy.use_bf16=true \
  --seed=42 \
  --batch_size=64 \
  --steps=20000 \
  --save_freq=5000 \
  --output_dir=$OUTPUT_DIR
Рецепт GR00T N1.7, нативний для LeRobot. Зверніть увагу на relative_exclude_joints: захват виключено з відносних дій, що є тим самим рішенням, яке so100_config.py приймає з ActionRepresentation.ABSOLUTE.
АспектIsaac-GR00T launch_finetune.pylerobot-train --policy.type=groot
Версія набору данихТільки LeRobot v2, потрібне перетворенняНативний набір даних LeRobot, без пониження версії
Відображення модальностіmeta/modality.json плюс конфігурація даних Pythonбез modality.json; поведінка встановлюється прапорцями --policy.* у командному рядку
Зерножодного прапорця seed--seed, LeRobot за замовчуванням 1000
Відносні діїActionConfig для кожного ключа в конфігурації даних--policy.use_relative_actions плюс --policy.relative_exclude_joints
Опубліковані еталонні результатиТенденція SO-100 open-loop MSE на демонстраційних данихНабори LIBERO, 96.5 відсотка в середньому по чотирьох наборах
Шлях розгортанняrun_gr00t_server.py плюс eval_so100.py через ZMQlerobot-rollout, з чанкінгом у реальному часі (queue_threshold має залишатися на рівні 5 або нижче)
Самостійне виконання доналаштування
Переваги
  • Кожен прапорець видимий і змінюваний. Ви можете розморозити візуальний кодер, перемістити state_dropout_prob або скоротити горизонт дії.
  • Графіки відкритого циклу є локальними файлами. Порівняння checkpoint-5000 з checkpoint-20000 — це команда оболонки.
  • Ви не залежите від того, чи залишається якась платформа онлайн, і контрольна точка зберігається на вашому диску у стандартному форматі.
  • Приклади бенчмарків репозиторію для LIBERO, SimplerEnv та DROID надають вам відомі успішні запуски для відтворення, перш ніж довіряти власним даним.
Компроміси
  • Середовище — це більша частина роботи. Версія FFmpeg, CUDA_HOME, git-lfs, gated backbone, torchcodec: жодна з цих проблем не є проблемою моделі, і кожна з них зупиняє виконання.
  • Перетворення з v3.0 на v2.1 потребує окремого віртуального середовища зі своїм кроком встановлення, і воно перезаписує ваш каталог набору даних на місці.
  • Оренда GPU починає тарифікуватися, коли ви починаєте налагодження, а не коли починається навчання, і ніщо не зупиняє екземпляр після завершення виконання.
  • Відсутність зерна означає відсутність побітової відтворюваності, на додаток до 5-6 відсотків варіативності між запусками лише через аугментацію.

Два способи отримати одну й ту саму контрольну точку

Ви орендуєте GPU і контролюєте кожен крок. Реалістично, це займе один день вперше і двадцять хвилин кожного наступного разу.

  1. Записуйте епізоди за допомогою lerobot-record на SO-100. Ви отримаєте набір даних LeRobot v3.0.
  2. Конвертуйте його до v2.1 за допомогою scripts/lerobot_conversion/convert_v3_to_v2.py у власному віртуальному середовищі.
  3. Напишіть meta/modality.json та конфігурацію модальності Python, зареєстровану під EmbodimentTag.NEW_EMBODIMENT.
  4. Орендуйте 80 ГБ карту, клонуйте з субмодулями, синхронізуйте uv, автентифікуйтесь у Hugging Face.
  5. Запустіть launch_finetune.py, потім open_loop_eval.py на кількох контрольних точках і порівняйте тенденцію MSE перед тим, як торкатися обладнання.
  6. Витягніть контрольну точку з машини, перш ніж знищити екземпляр, потім побудуйте шлях обслуговування до маніпулятора.
Крок, про який усі забувають

Скопіюйте контрольну точку з орендованого екземпляра, перш ніж вимкнути його. --save-total-limit 5 також означає, що старіші контрольні точки видаляються в міру продовження навчання, тому контрольна точка, яку ви хотіли на кроці 5000, може більше не існувати на кроці 20000.

Матриця навчання AY-Robots з п'ятьма моделями політики як рядками та чотирма роботизованими маніпуляторами як стовпцями, кожна клітинка посилається на конкретний посібник з навчання
Матриця /train: п'ять моделей проти чотирьох маніпуляторів. Рядок GR00T N1.7 також охоплює SO-101, Koch v1.1 та LeKiwi.

Повернення контрольної точки на маніпулятор

Isaac-GR00T використовує розділення сервер-клієнт через ZMQ. Політика виконується на GPU, а тонкий клієнт на машині робота надсилає спостереження та отримує фрагменти дій. Приклад SO-100 є достатньо повним для копіювання: запустіть run_gr00t_server.py з вашою контрольною точкою та --embodiment-tag NEW_EMBODIMENT, потім запустіть eval_so100.py на стороні робота з послідовним портом, ідентифікатором робота, індексами камери та мовною інструкцією. Назви камер у цій команді повинні відповідати дружнім назвам з вашого modality.json, а не номерам пристроїв ОС.

bash
# GPU side
uv run python gr00t/eval/run_gr00t_server.py \
  --model-path /tmp/so100/checkpoint-20000 \
  --embodiment-tag NEW_EMBODIMENT \
  --device cuda:0 \
  --host 0.0.0.0 --port 5555

# robot side, from gr00t/eval/real_robot/SO100
uv run --no-sync python eval_so100.py \
  --robot.type=so101_follower \
  --robot.port=/dev/ttyACM2 \
  --robot.id=orange_follower \
  --robot.cameras="{ front: {type: opencv, index_or_path: 6, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}" \
  --policy_host=localhost --policy_port=5555 \
  --lang_instruction="put the cube in the yellow bowl"
--execution-horizon контролює, скільки з передбачених кроків виконується перед переплануванням. Воно має бути не більше, ніж action_horizon політики, і це число є довжиною delta_indices дії у вашій конфігурації модальності, а не базової моделі. Постачана конфігурація SO-100 передбачає 16, тому 16 є вашою межею; базова контрольна точка nvidia/GR00T-N1.7-3B налаштована на 40, і policy.md чітко вказує, що доналаштовані контрольні точки можуть відрізнятися. Перевищіть її, і ви отримаєте ValueError, що називає обидва числа. 8 – це значення, яке документація пропонує для розгортання в реальному часі. Стара назва прапора --action-horizon все ще працює, але видає попередження.
7.4 V, а не 12 V

Поки ви підключаєте руку назад: SO-100 використовує шинні сервоприводи Feetech STS3215 на шині 7.4 V. Подача на них 12 V знищує їх, і це легка помилка, якщо у вас також є LeKiwi, чия база працює на 12 V, тоді як його рука – ні. Перевірте живлення перед першим увімкненням, а не після диму. Дивіться сторінку обладнання SO-100 та SO-100 проти LeKiwi. Якщо рука вмикається, але нічого не рухається, сервопривід не відповідає – це місце, з якого варто почати.

Тепер чесна частина про те, де виконується політика, тому що навчання та обслуговування мають різні історії з обладнанням. Доналаштування вимагає 40 GB або більше. Висновок – ні: README вказує 16 GB або більше і прямо називає RTX 4090, тому карта, яку ви вже маєте, може обслуговувати контрольну точку, яку вона ніколи не могла б створити. Що вирішує, чи буде політика чутливою, це не VRAM, а те, де знаходиться сервер. На AY-Robots GR00T N1.7 є лише хмарним, тому цикл керування оплачує зворотний шлях через публічний інтернет на додаток до 152 ms за крок дії, і лише SmolVLA та ACT також працюють локально. Для повільного вибору та розміщення віддалений под є прийнятним. Для чогось реактивного – ні: політика стає нерішучою таким чином, що виглядає точно як збій навчання, але таким не є. ACT з 20 ms за крок дії є моделлю, яка толерує найщільніший цикл, SmolVLA знаходиться на 245 ms, і жодна кількість налаштування затримки не поверне зворотний шлях, який вже був витрачений. Запустіть свою першу політику детально розглядає сторону обслуговування.

Що насправді йде не так

  • GatedRepoError під час першого запуску. Вам не надано доступ до nvidia/Cosmos-Reason2-2B, або ви не пройшли автентифікацію. Це відбувається після того, як тактова частота GPU вже почала працювати.
  • Набір даних відхилено під час завантаження. Майже завжди це набір даних v3.0. Перетворіть його на попередню версію. Дивіться набір даних відхилено як v3.
  • IndexError щодо невідповідності булевих розмірностей. Ви змінили delta_indices і не відновили статистику.
  • Недостатньо пам'яті на пакеті 32. Зменшіть --global-batch-size та збільшіть --gradient-accumulation-steps, або зменшіть --num-shards-per-epoch, що явно пропонується в конфігурації, коли VRAM обмежена. Дивіться недостатньо пам'яті під час навчання.
  • Втрати падають, політика нічого не робить. За замовчуванням немає розділення на валідаційний набір, тому чиста крива навчання мало що доводить. Ця сторінка охоплює діагностику.
  • Працює у вашій конфігурації і ніде більше. Очікувано для невеликого набору даних, знятого за одних умов освітлення. NVIDIA рекомендує аугментацію кольорового джиттера плюс від 20 до 50 епізодів за різних умов освітлення. Більше тут.
  • Захват ніколи не закривається належним чином. Перевірте, що дія захвату є ABSOLUTE, а суглоби руки RELATIVE, саме в такому порядку в action_configs. Захват не закривається перераховує інші причини.
  • Камера мовчки вимикається під час запису. Епізод все ще зберігається, і ключ відео все ще існує, ось чому це неприємно. Камера не виявлена охоплює це.

Повний покажчик режимів відмов знаходиться на . Якщо ви вибираєте між моделями, а не налагоджуєте одну, то та мають показники бенчмарків із зазначеними джерелами, а — це порівняння, яке насправді потрібне більшості людей, оскільки це вибір між моделлю, яку можна навчати на карті під вашим столом, і тією, для тонкого налаштування якої потрібно орендувати вузол на 80 ГБ. Щоб зрозуміти, чому ці моделі поводяться саме так, варто спочатку прочитати та . А якщо у вас ще немає маніпулятора, то транслює фізичний SO-100 без реєстрації.

Скільки епізодів мені потрібно, перш ніж тонке налаштування GR00T N1.7 стане виправданим?

AY-Robots встановлює мінімум у 50 епізодів для тренера groot1.7. Власний FAQ NVIDIA є більш вимогливим: приблизно 100 траєкторій для простого захоплення та розміщення у фіксованому місці, 500 або більше для складних або багатоетапних сцен, і від 100 до 500 для тонкої маніпуляції. Якщо у вас менше 50 епізодів, майже завжди краще записати більше даних, ніж налаштовувати гіперпараметри. Якщо успіх стабілізується після цього, NVIDIA рекомендує HG-DAgger: запустіть політику, втручайтеся, коли вона зазнає невдачі, і додайте ці виправлення до набору даних.

Чому мій набір даних не завантажується, і як визначити його версію?

Відкрийте meta/info.json і прочитайте codebase_version. Поточна CODEBASE_VERSION LeRobot на main — v3.0, тому все, що записано за допомогою нещодавнього набору інструментів, є v3.0, а завантажувач GR00T очікує v2. Перетворіть за допомогою scripts/lerobot_conversion/convert_v3_to_v2.py з репозиторію Isaac-GR00T, який записує codebase_version: v2.1 у перетворений набір даних. Скрипт запускається у власному віртуальному середовищі, оскільки йому потрібна інша версія lerobot, ніж та, яку використовує GR00T.

Чи можу я тонко налаштувати GR00T N1.7 на RTX 4090?

Ні. NVIDIA рекомендує 40 ГБ або більше VRAM для тонкого налаштування та називає вузли H100 або L40; інші карти працюють, але набагато довше. 4090 має 24 ГБ. AY-Robots пропонує GR00T N1.7 лише на рівні A100 80 ГБ та H100 80 ГБ з тієї ж причини. Висновок — це інша історія: 16 ГБ достатньо для обслуговування моделі, тому 4090 може запускати політику, яку вона не може навчати. Якщо ви хочете VLA, який можна навчати на 24 ГБ, це SmolVLA з приблизно 450 мільйонами параметрів або ACT з приблизно 80 мільйонами.

Чому два запуски з ідентичними прапорцями дають різні контрольні точки?

Тому що launch_finetune.py не має seed. Це CLI tyro, згенерований з dataclass, який не містить поля seed, тому ніщо не фіксує RNG. Репозиторій окремо зазначає 5-6 відсотків відхилення між запусками, спричинене недетермінованою аугментацією зображень. Якщо відтворюваність має значення, використовуйте замість цього шлях LeRobot: lerobot-train приймає --seed, а опублікований рецепт GR00T передає --seed=42.

Чи варто використовувати Isaac-GR00T або lerobot-train?

Використовуйте Isaac-GR00T, якщо вам потрібна еталонна реалізація, поключовий контроль над представленням дій, експорт TensorRT або приклади бенчмарків для відтворення, перш ніж довіряти власним даним. Використовуйте lerobot-train, якщо ваш набір даних вже є LeRobot v3.0 і ви не хочете його конвертувати, якщо вам потрібен seed, або якщо решта вашого стеку вже є LeRobot. Обидва тонко налаштовують ті самі ваги nvidia/GR00T-N1.7-3B. Зауважте, що LeRobot повністю відмовився від підтримки GR00T N1.5: контрольні точки N1.5 відхиляються з приміткою про міграцію, і вам доведеться зафіксувати lerobot==0.5.1, щоб продовжувати їх використовувати.

Чи дійсно мені потрібна камера на зап'ясті, а також фронтальна камера?

Постачається конфігурація SO-100 використовує обидві, і modality.json відображає передню камеру та камеру на зап'ясті як окремі відеоключі. Ви можете навчати з однією камерою, і таблиця затримки моделі вимірюється з однією камерою, але вид із зап'ястя дає політиці корисну інформацію про захват у момент контакту. Якщо захват закривається не в той час у ваших прогонах, відсутня або погано націлена камера на зап'ясті є однією з перших речей, які слід перевірити.

Тонке налаштування GR00T N1.7 на вашому SO-100 без попереднього створення середовища

Виберіть модель, набір даних та гіперпараметри у формі. Бекенд орендує A100 80 ГБ або H100 на спотовому ринку, запускає тренера з пакетом 32, швидкістю навчання 1e-4 та 20000 кроків, і записує контрольні точки в об'єктне сховище. Приблизно 4 to 12 USD за запуск.

Відкрити посібник з навчання GR00T N1.7

Ready for high-quality robotics data?

AY-Robots connects your robots to skilled operators worldwide.

Get Started