AY-Robots vejledningsside for træning af GR00T N1.7 på en SO-100 arm, der viser det krævede GPU-niveau, datasætformat og trænerstandardindstillinger
GR00T N1.7SO-100FinjusteringLeRobotVLA

Sådan træner du GR00T N1.7 på dit eget SO-100 datasæt

AY-Robots ResearchAugust 23, 202628 min læsning

En gennemtestet vejledning til finjustering af NVIDIA GR00T N1.7 på et SO-100 LeRobot datasæt: faktiske flags, modality.json, v2.1-kravet, hvad en kørsel koster, og faldgruberne.

NVIDIA leverer et finjusteringseksempel for præcis den arm, du sandsynligvis ejer. Inde i Isaac-GR00T-repositoryet findes der en mappe kaldet demo_data/cube_to_bowl_5: fem episoder, 4.148 billeder ved 30 fps, allerede skrevet som LeRobot v2.1, med en matchende modalitetskonfiguration under examples/SO100/. Dens meta/info.json rapporterer robot_type: so101_follower, som i LeRobot er den samme konfigurationsklasse som so100_follower. Det er virkelig nyttigt, fordi det betyder, at referencevejen for GR00T N1.7 på en seks-frihedsgraders hobbyarm vedligeholdes af de folk, der skrev modellen. Det er ikke en nedskaleret humanoid demo, det er den samme arm.

Den dårlige nyhed er afstanden mellem I recorded 60 episodes og the arm does the task. Der er omkring seks steder, hvor denne pipeline fejler stille snarere end højlydt, og fire af dem findes i filer, de fleste aldrig åbner: meta/modality.json, Python-datakonfigurationen, meta/relative_stats.json, og datasættets egen versionsstreng. Denne guide gennemgår den manuelle rute fra start til slut med de rigtige kommandoer og viser derefter det samme job som en formular på AY-Robots. Alt nedenfor blev kontrolleret mod Isaac-GR00T main-grenen pr. 20. august 2026 (n1.7-release-linjen) og lerobot 0.6.1, udgivet på PyPI den 3. august 2026. Upstream bevæger sig hurtigt, og hvor et flag blev omdøbt, nævner denne artikel det.

Hvad du skal vide, før du starter

  • GR00T N1.7 finjustering kræver 40 GB eller mere VRAM. NVIDIA anbefaler H100- eller L40-noder. Et 24 GB RTX 4090 vil ikke kunne udføre dette job, selvom det kan træne SmolVLA og ACT.
  • Datasættet skal være LeRobot v2 (v2.0 eller v2.1) plus en GR00T-specifik meta/modality.json. Et LeRobot v3.0 datasæt indlæses ikke og skal konverteres ned.
  • Indgangspunktet er gr00t/experiment/launch_finetune.py, en tyro CLI. Den har intet --seed flag, så kørsler er ikke bit-for-bit reproducerbare.
  • For en brugerdefineret arm er embodiment-tagget NEW_EMBODIMENT, og det tag gør --modality-config-path obligatorisk.
  • Den medfølgende SO-100 opskrift forudsiger armled som RELATIVE deltaer og griberen som et ABSOLUT mål. At få den parring baglæns er en stille fejl, ikke en egentlig fejl.
  • På AY-Robots er det samme job en formular: 20000 trin, batch 32, læringshastighed 1e-4, cirka 4 til 12 USD på A100 80 GB eller H100-niveauet.

Hvad GR00T N1.7 egentlig er

GR00T N1.7 er en syns-sprog-handlingsmodel med det dobbeltsystemlayout, der er beskrevet i den originale GR00T N1-artikel: et syns-sprog-modul, der læser kameraerne og instruktionen, og en diffusionstransformer, der omdanner dette til en blok af kontinuerlige motoriske kommandoer. N1.7 erstattede den første halvdel. Eagle-backbonen fra N1.6 er væk, udskiftet med nvidia/Cosmos-Reason2-2B på en Qwen3-VL-arkitektur, og modellen blev fortrænet på cirka 20.000 timers egocentrisk menneskevideo ud over robotdataene. NVIDIAs egen rapport angiver tallet til 20.854 timer og rapporterer, at en stigning fra 1k til 20k timer mere end fordobler den gennemsnitlige opgavefuldførelse.

Den anden halvdel ændrede sig også, på måder der er relevante for din kørsel. Handlingshovedet faldt fra 32 diffusionslag til 16, den forudsagte handlingsklump voksede fra 16 trin til 40, og den maksimale tilstands- og handlingsbredde gik fra 29 til 132. Disse tre tal kommer fra ændringsloggen i repositoryets README; NVIDIAs egen lanceringspost beskriver stadig System 1 som en 32-lags DiT, så hvor de to er uenige, skal du stole på det repo, du er ved at klone. Handlinger udtrykkes som standard i et relativt end-effector-rum, deltaer fra den nuværende position snarere end absolutte mål, hvilket er det, der overhovedet tillader manipulation priors lært fra menneskevideo at overføres til robotkontrol. Selve hovedet er en flow-matching diffusionstransformer, den samme familie som Pi0.5, men med en anden backbone foran den. Hvis du stadig er på den tidligere generation, N1.7 mod N1.5 dækker, om opgraderingen retfærdiggør at gentage din pipeline.

EgenskabVærdiKilde
Parametre3,000,000,000Hugging Face modelkort
Syns-sprog-backbonenvidia/Cosmos-Reason2-2B (Qwen3-VL), gated på Hugging Facerepo README
HandlingshovedFlow-matching diffusionstransformer, 16 lag (N1.6 havde 32)repo README
Forudsagt handlingshorisont40 trin for basis-checkpointet (N1.6 havde 16)getting_started/policy.md og repo README
Maks. tilstands- og handlingsbredde132 (N1.6 havde 29)repo README
KodelicensApache 2.0Isaac-GR00T repository
VægtlicensNVIDIA Open Model License Agreementmodelkort
Latens, H100 80 GB, PyTorch eager, 4 denoising trin, 1 kamera85.8 ms ende til ende, 11.7 Hzmodelkort tidsmålingstabel
Samme hardware, TensorRT fuld pipeline27.9 ms ende til ende, 35.9 Hzmodelkort tidsmålingstabel
Latens AY-Robots angiver for sin serverede GR00T N1.7152 ms per handlingstrinAY-Robots policykatalog

De sidste tre rækker forklarer det meste af den skuffelse, folk rapporterer. Overskriften på 27.9 ms er en TensorRT-motor på en H100 med ét kamera og fire denoising-trin. Ren PyTorch på det samme kort er 85.8 ms, og modelkortet angiver forskellen til 3.08x. Ingen af tallene inkluderer et serving-lag, et andet kamera eller et netværkshop. De 152 ms per handlingstrin, AY-Robots angiver for sin serverede GR00T N1.7, er tallet med serving i loopet, og en offentlig internet-roundtrip kommer oveni. Mere om dette til sidst. For tallene ved siden af andre modeller, GR00T N1.7 mod Pi0.5 og GR00T N1.7 mod SmolVLA præsenterer dem side om side.

AY-Robots modelsiden for GR00T N1.7 viser parameterantal, GPU-tier, inferensforsinkelse og modellens angivne styrker og begrænsninger
Siden /policies/groot-n1-7 indeholder den samme specifikationsstribe, som du ellers ville samle manuelt fra modelkortet og repoets README.

Hvad kørslen kræver, før du taster noget

KravFinjusteringInferens
VRAM, NVIDIA-vejledning40 GB eller mere, H100 eller L40 anbefales16 GB eller mere, et RTX 4090 fungerer
Python og CUDA på dGPU3.12 and CUDA 12.83.12 and CUDA 12.8
Video-backendtorchcodec 0.8.0, FFmpeg 4 to 7 onlysamme
DatasætformatLeRobot v2 plus meta/modality.jsonikke relevant
Hugging Face-adgangapproved for nvidia/Cosmos-Reason2-2Bsamme
Andre værktøjergit-lfs and uvuv
AY-Robots GPU-tier til groot1.7-trænerenA100 80 GB or H100 80 GBpod klargøres automatisk
Den gatede backbone vil stoppe dig ved første kørsel

Hvert GR00T-checkpoint, inklusive basis nvidia/GR00T-N1.7-3B, indlæser nvidia/Cosmos-Reason2-2B ved første brug, og det repository er gated. README'en angiver fejlen præcist: modelindlæsning mislykkes med en GatedRepoError / 401 Client Error. Hvad den ikke nævner, er hvornår det sker, hvilket er efter du har lejet kortet, og kørslen er startet. Anmod om adgang på modelsiden, kør derefter uv run huggingface-cli login eller eksporter HF_TOKEN, før du lejer noget.

Trin 0: episoderne selv

Alt nedenfor forudsætter, at du allerede har optaget episoder. Hvis ikke, er det det virkelige første skridt, og det er det, der afgør, hvor godt resultatet kan blive, fordi imitationslæring ikke kan gendanne information, der ikke er i dataene. Kalibrer begge arme først, og kør derefter følgeren med en lederarm mens lerobot-record skriver parquet-filerne og kamerastrømmene. Hvis kalibrering er forkert, beskriver ledværdierne i dit datasæt en lidt anden robot end den, der senere vil udføre politikken, og ingen mængde træning kan rette op på det.

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 på en nuværende LeRobot. Episodelængden er som standard 60 s, og nulstillingstiden er 60 s. so100_follower og so101_follower er begge registreret mod den samme LeRobot-konfigurationsklasse, hvilket er grunden til, at Isaac-GR00T SO100-eksemplet bruger so101-navnene; begge fungerer på en SO-100. Kameranavnene, du vælger her (front, wrist), er de navne, der skal genbruges i modality.json.

LeRobots eget råd er at optage mindst 50 episoder med omkring 10 pr. objektplacering, holde kameraerne faste og holde gribeadfærden konsekvent. Tilføj variation senere, ikke i starten. Tommelfingerreglen, der er værd at huske: hvis du ikke selv kunne udføre opgaven ud fra kamerabillederne alene, kan politikken heller ikke. For den armspecifikke opsætning dækker SO-100 igangsætning og SO-100 LeRobot-siden porte, kalibrering og kamera-indekser. På AY-Robots kan du også gøre dette over internettet fra browseren ved hjælp af fjernbetjening og optage direkte fra sessionen.

Trin 1: datasættet skal være LeRobot v2.1

Dette er den mest almindelige forhindring. LeRobots nuværende CODEBASE_VERSION på main er v3.0, så alt, hvad du optager i dag med en nuværende værktøjskæde, kommer ud som v3.0. GR00Ts loader forventer v2. Repository'et er eksplicit omkring hvorfor: mange upstream datasæt som DROID, LIBERO og Bridge er udgivet i v2, og indbygget understøttelse for begge er planlagt, men ikke leveret. Konverteringen er derfor dit ansvar, og den kører i sit eget virtualenv af en konkret årsag: scripts/lerobot_conversion medbringer sit eget pyproject, der kræver Python 3.10 eller 3.11 og fastlåser lerobot til én git commit, mens Isaac-GR00T selv kræver Python 3.12. Installer konverteren fra repository-roden, og du får gr00t-pakken i stedet, hvilket er den fejl, dens README advarer om. Hvis du er ny til formatet, forklarer LeRobot-datasæt ordlisteindgangen, hvad der faktisk er inde i et.

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
Konverteren tager --repo-id, en valgfri --root og --force-conversion, som sletter enhver eksisterende lokal snapshot og gen-downloader den. Den skriver codebase_version: v2.1 ind i meta/info.json.
Konverteringen overskriver på stedet

Hvis v3.0-datasættet allerede eksisterer lokalt, bygger scriptet v2.1-layoutet ved siden af det og bytter derefter om: originalen flyttes til en søskendemappe med versionen tilføjet, <name>_v3.0, og den konverterede kopi overtager den originale sti. (Scriptets egen docstring kalder den mappe _v30; koden tilføjer versionsstrengen, så det, du faktisk får, er _v3.0.) Anden overraskelse: outputtet lander altid under <root>/<repo-id>, så --root examples/SO100/my_dataset_lerobot giver dig examples/SO100/my_dataset_lerobot/<your-hf-user>/<your-dataset>, og den længere sti er den, som --dataset-path ønsker senere. Når et træningsjob afviser dit datasæt på grund af versionsårsager, siden om datasæt afvist som v3 lister de præcise symptomer.

Strukturen GR00T ønsker efter konvertering er det klassiske v2-layout: meta/info.json, meta/episodes.jsonl, meta/tasks.jsonl, parquet-filer under data/chunk-000/, MP4-filer under videos/chunk-000/observation.images./, og én ekstra fil, som standard LeRobot ikke har. Denne ekstra fil er der, hvor de fleste af de resterende fejl findes.

Trin 2: modality.json, de seks tal der afgør alt

I et LeRobot datasæt gemmes robotstatus og handling som flade float32-arrays. For en SO-100 har begge formen [6]: fem armled og en gribeklo. Demo-datasættet navngiver dem shoulder_pan.pos, shoulder_lift.pos, elbow_flex.pos, wrist_flex.pos, wrist_roll.pos, gripper.pos, men disse navne findes i info.json og intet i parquet-filen angiver, hvilket indeks der er hvad. meta/modality.json leverer denne mapping, og GR00T vil ikke træne uden den. Her er den, som repository'et leverer til SO-100, ordret.

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. Indekser er nulbaserede og følger Python-slicing, så single_arm er [0:5] og gripper er [5:6].

Kopiér den til dit konverterede datasæt på meta/modality.json og omdøb videonøglerne til det, dine kameraer faktisk hedder. Hvis du optog med et enkelt overliggende kamera kaldet top, så er original_key observation.images.top, og det venlige navn er det, din datakonfiguration vil referere til. De to skal stemme overens, og ingen af dem kontrollerer den anden for dig. Sprogannoteringen er værre, fordi den samme nøgle skal optræde tre steder.

LagFilSO-100-formular brugt i repoet
Parquet-kolonnedata/chunk-*/episode_*.parquetannotation.human.task_description
modality.json-nøglemeta/modality.json, under "annotation", without the annotation. prefixhuman.task_description
modality_keys i datakonfigurationenyour so100_config.pyannotation.human.task_description
Hvorfor sprognøglen volder problemer

Segmenterne efter annotation. vælges af den, der har oprettet datasættet. SO-100 demo-data bruger annotation.human.task_description; LIBERO og SimplerEnv bruger annotation.human.action.task_description. Begge er gyldige. Hvis du kopierede en konfiguration fra et LIBERO-eksempel og pegede den på din egen SO-100-optagelse, resulterer sprogkanalen i intet, og modellen træner på en tom instruktion. Tab falder stadig. Politikken gør stadig noget. Den ignorerer bare, hvad du bad den om at gøre.

Trin 3: datakonfigurationen, relativ arm og absolut griber

Modalitetskonfigurationen er en Python-fil snarere end JSON, fordi den også bestemmer, hvordan hver handlingsgruppe repræsenteres. Dette er den del af N1.7-workflowet, der ikke eksisterede i samme form i N1.5, og den del, der er værd at læse to gange. Den medfølgende SO-100-konfiguration forudsiger de fem armled som RELATIVE deltaer fra den nuværende tilstand og gribekloen som en ABSOLUTE målposition, fordi et binært åben-eller-lukket signal fungerer bedre som et mål end som et delta.

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, beskåret til det væsentlige. NON_EEF betyder ledrum; EEF ville forvente en ni-dimensionel vektor af x, y, z plus en 6D rotation.

To detaljer her vil koste dig en dag, hvis du ikke kender dem. For det første, action_configs er positionel: dokumentationen kræver samme længde og samme rækkefølge som modality_keys, og de er meget tydelige omkring konsekvensen af at gøre det forkert, hvilket er, at den forkerte repræsentation anvendes lydløst. Din gribeklo trænes som et delta, og din arm som et absolut mål, og der er ingen fejlmeddelelse. For det andet, register_modality_config bekræfter, at tagget ikke allerede er registreret, så en anden NEW_EMBODIMENT-konfiguration i samme Python-proces dør med Embodiment tag ... already registered. Du kan ikke importere to af disse i ét script. En tredje regel håndhæves senere, ved implementering: handlingen delta_indices skal være det sammenhængende område, der starter ved nul. Et spredt vindue som [0, 4, 8] afvises, fordi alt downstream indekserer den forudsagte chunk lineært og ellers ville udføre de forkerte rækker.

Ændr delta_indices, og du skal regenerere statistikkerne

Normaliseringsstatistikker, især meta/relative_stats.json, beregnes for den horisontlængde, du havde, da du genererede dem. Forkort handlingshorisonten fra 16 til 8 uden at regenerere, og træningen dør med IndexError: boolean index did not match indexed array ... dimension is 8 but corresponding boolean dimension is 16. Løsningen er én kommando: python gr00t/data/stats.py --dataset-path <path> --embodiment-tag NEW_EMBODIMENT --modality-config-path examples/SO100/so100_config.py. Kør den efter enhver ændring af delta_indices.

Trin 4: miljøet

N1.7 flyttede repository'et til og Python 3.12. Den gamle conda plus pip install -e . sti eksisterer stadig i en sammenklappet sektion af README, men den advarer om, at GPU-afhængigheder, herunder flash-attn og TensorRT, muligvis kræver manuel installation. Brug uv, medmindre du har en specifik grund til ikke at gøre det. Hvad angår flash-attn, sparer én detalje forvirring: du vil se Installing flash-attn udskrevet ved hver uv run. Den genopbygges ikke. uv genvaliderer et URL-fastgjort wheel, der allerede er cachet, og det tager to eller tre sekunder.

  1. 1
    Installer git-lfs, klon derefter med submoduler

    git-lfs er påkrævet, ikke valgfrit. Uden det downloades parquet-filerne i demo_data/ som pointer-stubs, og demo-kørslen mislykkes på et datasæt, der ser ud til at være til stede i filoversigten.

    bash
    sudo apt install git-lfs && git lfs install
    git clone --recurse-submodules https://github.com/NVIDIA/Isaac-GR00T
    cd Isaac-GR00T
  2. 2
    Installer uv og synkroniser miljøet

    Standardinstallationen trækker GPU-afhængighederne, herunder flash-attn og TensorRT. På et nyt A100- eller H100-image er dette det længste enkelttrin, så gør det, før du begynder at være opmærksom på noget andet.

    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
    Autentificer mod Hugging Face

    Gør dette før den første træningsstart, ikke efter den fejler otte minutter inde.

    bash
    uv run huggingface-cli login   # or: export HF_TOKEN=<your_token>
  4. 4
    Sanitetskontrol på de medfølgende SO-100 demo-data

    Før du rører ved din egen optagelse, kør 2000 trin på demo_data/cube_to_bowl_5. Det er fem episoder, det afsluttes hurtigt, og det beviser miljøet snarere end dine data. Hvis denne kørsel mislykkes, vil intet, du gør med dit datasæt, hjælpe.

    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
To miljøfælder, der ligner modelbugs

FFmpeg 8. torchcodec 0.8.0 understøtter kun FFmpeg 4 til 7, og Ubuntu 25.10 og nyere leveres med version 8. Fejlen er Could not load libtorchcodec, hvilket lyder som en ødelagt installation snarere end en versionskonflikt. Installer en ældre runtime, for eksempel conda install -c conda-forge 'ffmpeg<8', og placer dens biblioteker på LD_LIBRARY_PATH. CUDA_HOME er ikke indstillet. Finjustering mislykkes fuldstændigt. Kør bash scripts/deployment/dgpu/install_deps.sh én gang, eller bare export CUDA_HOME=/usr/local/cuda.

Trin 5: fine-tune kommandoen og hvad dens flags reelt er standard for

Udskift demo-datasættet med dit eget og tilføj de indstillinger, du faktisk ønsker. Nedenfor er den fulde form, som repository'et bruger i sin egen new-embodiment tutorial, inklusive de augmentering- og checkpointing-flags, som det korte README-eksempel udelader. Dette er i snæver forstand: sprog-backbonen og den visuelle encoder forbliver frosne, og det, der trænes, er projektoren og diffusion action head'en.

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
Enkelt GPU. For otte kort, erstat launcher'en med uv run torchrun --nproc_per_node=8 --master_port=29500 og sæt --num-gpus 8. Brug uv run torchrun, ikke bare torchrun, ellers får du det forkerte miljø.
FlagStandard i FinetuneConfigHvad det gør
--global-batch-size64Samlet batch på tværs af alle GPU'er før gradientakkumulering. De medfølgende eksempler bruger 32.
--learning-rate1e-4Den samme værdi AY-Robots sender til sin groot1.7 træner.
--max-steps10000Samlede optimeringsskridt. examples/finetune.sh wrapperen er også standard til 10000.
--gradient-accumulation-steps1Multiplicerer den effektive batch. Værdier over 1 udløser en advarsel, der fortæller dig den akkumulerede størrelse.
--save-steps and --save-total-limit1000 and 5Checkpoint-frekvens, og hvor mange der bevares. Ældre slettes.
--weight-decay and --warmup-ratio1e-5 and 0.05Sættes også eksplicit af examples/finetune.sh.
--state-dropout-prob0.2 in the CLI, 0.8 in the model configFjerner tilfældigt proprioceptiv tilstand under træning. Sænk den, hvis din opgave er afhængig af tilstand.
--tune-llm and --tune-visualFalse and FalseBackbonen forbliver frossen som standard.
--tune-projector and --tune-diffusion-modelTrue and TrueProjektoren og diffusion action head'en er det, der faktisk trænes.
--use-percentilesTrueNormaliser med q01 og q99 i stedet for rå min og max.
--dataloader-num-workers2Loaderen er CPU-baseret af design. Eksemplerne hæver dette til 4.
--seeddoes not existDer er ingen seed-flag på denne CLI.

Den sidste række er ikke en slåfejl. launch_finetune.py er en tyro CLI genereret fra en dataclass, og den dataclass har intet seed-felt. README bemærker separat en varians på 5 til 6 procent mellem kørsler forårsaget af ikke-deterministisk billedaugmentation. To kørsler med identiske flag vil ikke producere identiske checkpoints, hvilket betyder meget, når man forsøger at afgøre, om en hyperparameterændring hjalp, eller om man var heldig. Til sammenligning bruger lerobots egen træner standardværdien seed 1000, og LeRobot GR00T-opskriften sender --seed=42 eksplicit.

Validering er slået fra som standard, og det dokumenterede flag findes ikke på denne CLI

Finjustering kører med eval_strategy="no", så der er ingen valideringstabskurve overhovedet. Du får træningstab og intet andet. Den nye embodiment-guide fortæller dig at slå det til med --eval-strategy steps --eval-steps 500, men det flag findes ikke på launch_finetune.py: CLI'en genereres af tyro fra FinetuneConfig dataclassen, og eval_strategy, eval_steps og eval_batch_size er felter i TrainingConfig i stedet. Deres standardværdier der er "no", 500 og 2. For at nå dem, brug det fulde indgangspunkt gr00t/experiment/launch_train.py, hvor det indlejrede flag er --training.eval-strategy. Uanset hvad fortæller et faldende træningstab i sig selv meget lidt om generalisering, hvilket er præcis den situation, der er beskrevet på tabet falder, men politikken gør intet.

Hvad en 20000-trins kørsel koster

GR00T N1.7 kræver et 80 GB kort, så omkostningsspørgsmålet har et snævert svar. På AY-Robots kører groot1.7-træneren på A100 80 GB eller H100 80 GB-niveauet, hvor en kørsel tager 3 til 6 timer til 1.20 til 2.00 USD per time på spotmarkedet. Det er cirka 4 til 12 USD for standard 20000-trins jobbet. Den samme opgave på SmolVLA eller ACT lander på et 24 GB kort til 0.30 til 0.60 USD per time og 1 til 3 USD per kørsel. Det er den virkelige afvejning: GR00T koster omkring fire gange så meget per forsøg, og du kan ikke køre det på 4090'eren under dit skrivebord.

ModelGPU-niveauTypisk køretidTypisk prisMinimum episoder
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

De 50-episode minimum er et gulv, ikke et mål. NVIDIAs egen FAQ er mere krævende: cirka 100 trajektorier for en simpel pick-and-place med fast placering, 500 eller mere for komplekse eller flertrins-scener, og 100 til 500 for fin manipulation. Hvis du sidder med 20 episoder, så brug eftermiddagen på at optage i stedet for aftenen på at finjustere. vejledning til dataindsamling dækker, hvad der adskiller en nyttig episode fra en spildt, optag dit første datasæt er den korte version, og SO-100 dataindsamling er den armspecifikke.

AY-Robots træningsvejledning for GR00T N1.7 på SO-100, der viser specifikationslisten med GPU-niveau, påkrævet datasætformat og trænerens standardindstillinger
Vejledningen /train/groot-n1-7-on-so-100 præsenterer de fakta, du ellers ville skulle rekonstruere manuelt: GPU-niveau, datasætformat og de præcise standardindstillinger, træneren sender.

Trin 6: open-loop evaluering før du rører armen

Sæt ikke en frisk kontrolpunkt på en fysisk arm for at finde ud af, om træningen virkede. Kør open-loop evalueringen først. Den afspiller en optaget episode, beder modellen om handlinger ved hvert trin og plotter forudsigelse mod sandhed med MSE og MAE. Det koster intet, og det fanger mapping-fejlene fra trin 2 og 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
Plots lander i /tmp/open_loop_eval/traj_<id>.jpeg medmindre du angiver --save-plot-path. Standardværdier: --execution-horizon 16, --steps 200, --denoising-steps 4, --traj-ids 0.

Repository'et nægter bevidst at offentliggøre en mål-MSE for brugerdefinerede data, og det er den rigtige beslutning: tallet afhænger af dine handlingsenheder, din opgave og din datasætstørrelse, så en tærskel kopieret fra en andens arm betyder intet. Hvad der er meningsfuldt, er tendensen. Her er referencekørslen, som repo'et dokumenterer på en enkelt H100 med det fem-episode demo-datasæt og 2000 trin.

KontrolpunktGennemsnitlig MSE på traj 0Gennemsnitlig MAE på traj 0
50087.55.63
100025.43.30
150013.22.18
200010.01.76

Formen er signalet, ikke de absolutte værdier. Fejlen bør falde støt, efterhånden som akkumuleres. Gennemsnitligt over alle fem træningsepisoder i stedet for kun bane 0, scorede repoets endelige checkpoint cirka 7.5 MSE og 1.5 MAE, så selv referencekørslen læses forskelligt afhængigt af hvilke episoder du gennemsnitliggør. Optag din egen baseline med den umodificerede demo-kommando, før du ændrer noget ved dine egne data: hvis du ikke kan reproducere en kendt-god kørsel, kan du ikke skelne en opsætningsfejl fra et dataproblem. Repositoryet kortlægger også de almindelige symptomer til årsager, og hver af dem er operationel snarere end en modelbug.

SymptomSandsynlig årsag
MSE flad eller stigende over checkpointsLæringshastigheden er for lav, eller data indlæses slet ikke. Tjek --dataset-path og dataloader-arbejderne.
Forudsigelseskurven er flad eller konstantmodality.json-nøgler eller --modality-config-path stemmer ikke overens. Handlingsnøglerne er ikke mappet.
MSE enorm, eller NaN-tab under træningHandlings- og tilstandsnormalisering. Verificer meta/stats, og at handlingsområderne er fysisk plausible.
God på bane 0, dårlig på tilbageholdte episoderDatamangel, ikke en fejl. Fem demo-episoder kan ikke generalisere.

Den anden vej: lerobot-train i stedet for Isaac-GR00T

Den nuværende LeRobot-udgivelse, 0.6.1 på PyPI siden 3. august 2026, tilbyder en anden og ret forskellig måde at finjustere de samme basisvægte på. LeRobot eksponerer GR00T N1.7 som en policy type og træner den via sit eget lerobot-train indgangspunkt. To ting er vigtige her. LeRobot CLI er et sæt konsolscripts, så alt hvad du læser, der siger python lerobot/scripts/train.py er forældet og vil ikke køre. Og LeRobot fjernede GR00T N1.5-understøttelse fuldstændigt, idet den afviste N1.5 checkpoints og configs med en migrationsnote, så hvis du har brug for N1.5 via LeRobot, skal du fastlåse lerobot==0.5.1, den sidste udgivelse, der understøtter det, udgivet 7. april 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
Den LeRobot-native GR00T N1.7 opskrift. Bemærk relative_exclude_joints: griberen er udelukket fra relative handlinger, hvilket er den samme beslutning som so100_config.py træffer med ActionRepresentation.ABSOLUTE.
AspektIsaac-GR00T launch_finetune.pylerobot-train --policy.type=groot
DatasetversionKun LeRobot v2, konvertering påkrævetNative LeRobot datasæt, ingen nedgradering
Modalitetsmappingmeta/modality.json plus en Python datakonfigurationingen modality.json; adfærd indstilles af --policy.* flags på kommandolinjen
Seedingen seed flag overhovedet--seed, LeRobot standard 1000
Relative handlingerper-nøgle ActionConfig i datakonfigurationen--policy.use_relative_actions plus --policy.relative_exclude_joints
Offentliggjorte referenceresultaterSO-100 open-loop MSE trend på demodataLIBERO suiter, 96,5 procent gennemsnit over fire suiter
Implementeringsstirun_gr00t_server.py plus eval_so100.py over ZMQlerobot-rollout, med realtids-chunking (queue_threshold bør forblive på eller under 5)
Kør finjusteringen selv
Fordele
  • Hvert flag er synligt og kan ændres. Du kan frigøre den visuelle encoder, flytte state_dropout_prob eller forkorte handlingshorisonten.
  • Open-loop plots er lokale filer. At diff'e checkpoint-5000 mod checkpoint-20000 er en shell-kommando.
  • Du er ikke afhængig af, at nogen platform forbliver online, og checkpointet ligger på din disk i et standardformat.
  • Repoets benchmark-eksempler for LIBERO, SimplerEnv og DROID giver dig kendte, gode kørsler at reproducere, før du stoler på dine egne data.
Kompromiser
  • Miljøet er det meste af arbejdet. FFmpeg version, CUDA_HOME, git-lfs, den gated backbone, torchcodec: ingen af disse er modelproblemer, og hver eneste af dem stopper kørslen.
  • Konverteringen fra v3.0 til v2.1 kræver et separat virtualenv med sit eget installationstrin, og det overskriver din datasætmappe på stedet.
  • GPU-leje begynder at fakturere, når du starter fejlfinding, ikke når træningen starter, og intet stopper instansen, når kørslen er færdig.
  • Intet seed betyder ingen bit-for-bit reproducerbarhed, ud over 5 til 6 procent variation fra kørsel til kørsel alene fra augmentation.

To måder at opnå det samme checkpoint på

Du lejer GPU'en, og du ejer hvert skridt. Realistisk set tager det en eftermiddag første gang og tyve minutter hver gang derefter.

  1. Optag episoder med lerobot-record på SO-100. Du får et LeRobot v3.0 datasæt.
  2. Konverter det ned til v2.1 med scripts/lerobot_conversion/convert_v3_to_v2.py i sit eget virtualenv.
  3. Skriv meta/modality.json og en Python modalitetskonfiguration, registreret under EmbodimentTag.NEW_EMBODIMENT.
  4. Lej et 80 GB kort, klon med submoduler, uv sync, autentificer mod Hugging Face.
  5. Kør launch_finetune.py, derefter open_loop_eval.py på flere checkpoints, og sammenlign MSE-trenden, før du rører hardware.
  6. Træk checkpointet fra maskinen, før du ødelægger instansen, og byg derefter serving-stien til armen.
Trinnet alle glemmer

Kopier checkpointet fra den lejede instans, før du lukker den ned. --save-total-limit 5 betyder også, at ældre checkpoints slettes, efterhånden som træningen skrider frem, så det checkpoint, du ønskede ved trin 5000, eksisterer muligvis ikke længere ved trin 20000.

AY-Robots træningsmatrixen med fem politikmodeller som rækker og fire robotarme som kolonner, hvor hver celle linker til en specifik træningsguide
The /train matrix: fem modeller mod fire arme. GR00T N1.7-rækken dækker også SO-101, Koch v1.1 og LeKiwi.

Få checkpointet tilbage på armen

Isaac-GR00T anvender en server-klient-opdeling over ZMQ. Politikken kører på GPU'en, og en tynd klient på robotmaskinen sender observationer og modtager handlingssegmenter. SO-100-eksemplet er tilstrækkeligt komplet til at kopiere: start run_gr00t_server.py med dit checkpoint og --embodiment-tag NEW_EMBODIMENT, kør derefter eval_so100.py på robotsiden med serielporten, robot-ID'et, kamera-indekserne og sproginstruktionen. Kameranavnene i den kommando skal matche de venlige navne fra din modality.json, ikke OS-enhedsnumrene.

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 styrer, hvor mange af de forudsagte trin der udføres, før der genplanlægges. Det skal højst være policyens action_horizon, og det tal er længden af action delta_indices i din modalitetskonfiguration, ikke basemodellens. Den medfølgende SO-100-konfiguration forudsiger 16, så 16 er dit loft; den grundlæggende nvidia/GR00T-N1.7-3B checkpoint er konfigureret til 40, og policy.md siger tydeligt, at finjusterede checkpoints kan afvige. Overskrider du det, får du en ValueError, der nævner begge tal. 8 er den værdi, dokumentationen foreslår til realtidsimplementering. Det gamle flagnavn --action-horizon virker stadig, men advarer.
7.4 V, ikke 12 V

Mens du forbinder armen igen: SO-100 kører Feetech STS3215 bus-servoer på en 7.4 V skinne. At forsyne dem med 12 V ødelægger dem, og det er en nem fejl, hvis du også ejer en LeKiwi, hvis base kører på 12 V, mens dens arm ikke gør. Kontroller strømforsyningen før den første opstart, ikke efter røgen. Se SO-100 hardware-siden og SO-100 mod LeKiwi. Hvis armen tænder, men intet bevæger sig, er servo reagerer ikke stedet at starte.

Nu den ærlige del om, hvor policyen kører, for træning og serving har forskellige hardwarehistorier. Finjustering kræver 40 GB eller mere. Inferens gør ikke: README'en angiver det til 16 GB eller mere og nævner RTX 4090 eksplicit, så et kort, du allerede ejer, kan serve et checkpoint, det aldrig kunne have produceret. Hvad der afgør, om policyen føles responsiv, er ikke VRAM, det er, hvor serveren sidder. På AY-Robots er GR00T N1.7 kun i skyen, så kontrolsløjfen betaler en offentlig internet-tur-retur ud over de 152 ms pr. handlingstrin, og kun SmolVLA og ACT kører også lokalt. Til langsom pick and place er en fjern pod overlevelig. Til noget reaktivt er det ikke: policyen bliver tøvende på en måde, der ligner en træningsfejl, men ikke er det. ACT med 20 ms pr. handlingstrin er den model, der tolererer den strammeste sløjfe, SmolVLA ligger på 245 ms, og ingen mængde af latency-justering køber en tur-retur, der allerede er brugt, tilbage. Kør din første policy gennemgår serving-siden fra ende til anden.

Hvad der faktisk går galt

  • GatedRepoError ved første kørsel. Du har ikke fået adgang til nvidia/Cosmos-Reason2-2B, eller du har ikke godkendt dig. Dette sker, efter at GPU-uret allerede er startet.
  • Datasæt afvist ved indlæsning. Næsten altid et v3.0-datasæt. Konverter det ned. Se datasæt afvist som v3.
  • IndexError vedrørende uoverensstemmende boolske dimensioner. Du ændrede delta_indices og regenererede ikke statistikken.
  • Mangel på hukommelse ved batch 32. Reducer --global-batch-size og øg --gradient-accumulation-steps, eller reducer --num-shards-per-epoch, hvilket konfigurationen eksplicit foreslår, når VRAM er begrænset. Se mangel på hukommelse under træning.
  • Tab falder, politik gør intet. Der er ingen valideringsopdeling som standard, så en ren træningskurve beviser meget lidt. Denne side dækker diagnosen.
  • Virker i dit setup og ingen andre steder. Forventeligt med et lille datasæt filmet under én lysforhold. NVIDIA anbefaler farve-jitter-augmentation plus 20 til 50 episoder under forskellige lysforhold. Mere her.
  • Gribeklo lukker aldrig ordentligt. Kontroller, at gribekloens handling er ABSOLUT og armleddene RELATIVE, i den rækkefølge i action_configs. Gribeklo lukker ikke lister de andre årsager.
  • Et kamera falder lydløst ud midt under optagelsen. Episoden gemmes stadig, og videonøglen eksisterer stadig, hvilket er grunden til, at denne er ubehagelig. Kamera ikke fundet dækker det.

Hele indekset over fejltyper findes på rettelsessiderne. Hvis du vælger mellem modeller frem for at fejlfinde en, har politiksammenligningen og arena-indgangen for GR00T N1.7 benchmark-tal med kilder vedhæftet, og ACT mod GR00T N1.7 er den sammenligning de fleste faktisk har brug for, fordi det er valget mellem en model, du kan træne på kortet under dit skrivebord, og en, du skal leje en 80 GB node for at finjustere. For baggrund om, hvorfor disse modeller opfører sig, som de gør, er VLA-oversigten og SO-100 den komplette guide værd at læse først. Og hvis du endnu ikke ejer en arm, streamer den levende arm en fysisk SO-100 uden tilmelding.

Hvor mange episoder har jeg brug for, før det er umagen værd at finjustere GR00T N1.7?

AY-Robots sætter et minimum på 50 episoder for groot1.7-træneren. NVIDIAs egen FAQ er mere krævende: cirka 100 trajektorier for en simpel pick and place på en fast placering, 500 eller mere for komplekse eller flertrins-scener, og 100 til 500 for fin manipulation. Under 50 er du næsten altid bedre stillet ved at optage mere data end at justere hyperparametre. Hvis succes stagnerer derefter, anbefaler NVIDIA HG-DAgger: kør politikken, grib ind når den fejler, og tilføj disse korrektioner til datasættet.

Hvorfor indlæses mit datasæt ikke, og hvordan finder jeg ud af, hvilken version det er?

Åbn meta/info.json og læs codebase_version. LeRobots nuværende CODEBASE_VERSION på main er v3.0, så alt optaget med en nyere værktøjskæde er v3.0, og GR00T-loaderen forventer v2. Konverter med scripts/lerobot_conversion/convert_v3_to_v2.py fra Isaac-GR00T-repoet, som skriver codebase_version: v2.1 ind i det konverterede datasæt. Scriptet kører i sit eget virtualenv, fordi det kræver en anden lerobot-version end den GR00T bruger.

Kan jeg finjustere GR00T N1.7 på et RTX 4090?

Nej. NVIDIA anbefaler 40 GB eller mere VRAM til finjustering og nævner H100- eller L40-noder; andre kort fungerer, men tager meget længere tid. Et 4090 har 24 GB. AY-Robots tilbyder kun GR00T N1.7 på A100 80 GB og H100 80 GB niveauet af samme grund. Inferens er en anden historie: 16 GB er nok til at køre modellen, så et 4090 kan køre en politik, det ikke kan træne. Hvis du ønsker en VLA, du kan træne på 24 GB, er det SmolVLA med omkring 450 M parametre eller ACT med omkring 80 M.

Hvorfor giver to kørsler med identiske flag forskellige checkpoints?

Fordi launch_finetune.py ikke har et seed. Det er en tyro CLI genereret fra en dataclass, der ikke indeholder et seed-felt, så intet fastlåser RNG'en. Repoet bemærker separat 5 til 6 procent variation mellem kørsler forårsaget af ikke-deterministisk billedaugmentation. Hvis reproducerbarhed er vigtig, brug LeRobot-ruten i stedet: lerobot-train tager --seed, og den publicerede GR00T-opskrift sender --seed=42.

Skal jeg bruge Isaac-GR00T eller lerobot-train?

Brug Isaac-GR00T, hvis du ønsker referenceimplementeringen, per-nøgle kontrol over handlingsrepræsentation, TensorRT-eksport eller benchmark-eksemplerne til at reproducere, før du stoler på dine egne data. Brug lerobot-train, hvis dit datasæt allerede er LeRobot v3.0, og du hellere vil undgå at konvertere det, hvis du ønsker et seed, eller hvis resten af din stack allerede er LeRobot. Begge finjusterer de samme nvidia/GR00T-N1.7-3B vægte. Bemærk, at LeRobot helt har droppet GR00T N1.5-understøttelse: N1.5-checkpoints afvises med en migrationsnote, og du skal fastlåse lerobot==0.5.1 for at fortsætte med at bruge dem.

Har jeg virkelig brug for et håndledskamera udover et frontkamera?

Den leverede SO-100-konfiguration bruger begge, og modality.json mapper front og håndled som separate videonøgler. Du kan træne med ét kamera, og modelkortets latenstabel er målt med ét kamera, men håndledsvisningen er det, der giver politikken brugbar information om gribekloen i kontaktøjeblikket. Hvis gribekloen lukker på det forkerte tidspunkt i dine rollouts, er et manglende eller dårligt rettet håndledskamera en af de første ting at kontrollere.

Finjuster GR00T N1.7 på din SO-100 uden først at bygge miljøet

Vælg model, datasæt og hyperparametre i en formular. Backend lejer en A100 80 GB eller H100 på spotmarkedet, kører træneren med batch 32, læringshastighed 1e-4 og 20000 trin, og skriver checkpoints til objektlager. Cirka 4 til 12 USD per kørsel.

Åbn GR00T N1.7 træningsguiden

Ready for high-quality robotics data?

AY-Robots connects your robots to skilled operators worldwide.

Get Started