
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.
| Egenskab | Værdi | Kilde |
|---|---|---|
| Parametre | 3,000,000,000 | Hugging Face modelkort |
| Syns-sprog-backbone | nvidia/Cosmos-Reason2-2B (Qwen3-VL), gated på Hugging Face | repo README |
| Handlingshoved | Flow-matching diffusionstransformer, 16 lag (N1.6 havde 32) | repo README |
| Forudsagt handlingshorisont | 40 trin for basis-checkpointet (N1.6 havde 16) | getting_started/policy.md og repo README |
| Maks. tilstands- og handlingsbredde | 132 (N1.6 havde 29) | repo README |
| Kodelicens | Apache 2.0 | Isaac-GR00T repository |
| Vægtlicens | NVIDIA Open Model License Agreement | modelkort |
| Latens, H100 80 GB, PyTorch eager, 4 denoising trin, 1 kamera | 85.8 ms ende til ende, 11.7 Hz | modelkort tidsmålingstabel |
| Samme hardware, TensorRT fuld pipeline | 27.9 ms ende til ende, 35.9 Hz | modelkort tidsmålingstabel |
| Latens AY-Robots angiver for sin serverede GR00T N1.7 | 152 ms per handlingstrin | AY-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.

Hvad kørslen kræver, før du taster noget
| Krav | Finjustering | Inferens |
|---|---|---|
| VRAM, NVIDIA-vejledning | 40 GB eller mere, H100 eller L40 anbefales | 16 GB eller mere, et RTX 4090 fungerer |
| Python og CUDA på dGPU | 3.12 and CUDA 12.8 | 3.12 and CUDA 12.8 |
| Video-backend | torchcodec 0.8.0, FFmpeg 4 to 7 only | samme |
| Datasætformat | LeRobot v2 plus meta/modality.json | ikke relevant |
| Hugging Face-adgang | approved for nvidia/Cosmos-Reason2-2B | samme |
| Andre værktøjer | git-lfs and uv | uv |
| AY-Robots GPU-tier til groot1.7-træneren | A100 80 GB or H100 80 GB | pod klargøres automatisk |
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.
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=trueLeRobots 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.
# 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_lerobotHvis 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.
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.
{
"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"
}
}
}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.
| Lag | Fil | SO-100-formular brugt i repoet |
|---|---|---|
| Parquet-kolonne | data/chunk-*/episode_*.parquet | annotation.human.task_description |
| modality.json-nøgle | meta/modality.json, under "annotation", without the annotation. prefix | human.task_description |
| modality_keys i datakonfigurationen | your so100_config.py | annotation.human.task_description |
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.
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)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.
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.
- 1Installer 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.
bashsudo apt install git-lfs && git lfs install git clone --recurse-submodules https://github.com/NVIDIA/Isaac-GR00T cd Isaac-GR00T - 2Installer 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.
bashcurl -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')" - 3Autentificer mod Hugging Face
Gør dette før den første træningsstart, ikke efter den fejler otte minutter inde.
bashuv run huggingface-cli login # or: export HF_TOKEN=<your_token> - 4Sanitetskontrol 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.
bashCUDA_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 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.
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| Flag | Standard i FinetuneConfig | Hvad det gør |
|---|---|---|
| --global-batch-size | 64 | Samlet batch på tværs af alle GPU'er før gradientakkumulering. De medfølgende eksempler bruger 32. |
| --learning-rate | 1e-4 | Den samme værdi AY-Robots sender til sin groot1.7 træner. |
| --max-steps | 10000 | Samlede optimeringsskridt. examples/finetune.sh wrapperen er også standard til 10000. |
| --gradient-accumulation-steps | 1 | Multiplicerer den effektive batch. Værdier over 1 udløser en advarsel, der fortæller dig den akkumulerede størrelse. |
| --save-steps and --save-total-limit | 1000 and 5 | Checkpoint-frekvens, og hvor mange der bevares. Ældre slettes. |
| --weight-decay and --warmup-ratio | 1e-5 and 0.05 | Sættes også eksplicit af examples/finetune.sh. |
| --state-dropout-prob | 0.2 in the CLI, 0.8 in the model config | Fjerner tilfældigt proprioceptiv tilstand under træning. Sænk den, hvis din opgave er afhængig af tilstand. |
| --tune-llm and --tune-visual | False and False | Backbonen forbliver frossen som standard. |
| --tune-projector and --tune-diffusion-model | True and True | Projektoren og diffusion action head'en er det, der faktisk trænes. |
| --use-percentiles | True | Normaliser med q01 og q99 i stedet for rå min og max. |
| --dataloader-num-workers | 2 | Loaderen er CPU-baseret af design. Eksemplerne hæver dette til 4. |
| --seed | does not exist | Der 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.
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.
| Model | GPU-niveau | Typisk køretid | Typisk pris | Minimum episoder |
|---|---|---|---|---|
| GR00T N1.7 | A100 80 GB or H100 80 GB | 3 to 6 hours | 4 to 12 USD | 50 |
| GR00T N1.5 | A100 80 GB or H100 80 GB | 3 to 6 hours | 4 to 12 USD | 50 |
| Pi0.5 | A100 80 GB or H100 80 GB | 3 to 6 hours | 4 to 12 USD | 50 |
| SmolVLA | RTX 4090 or any 24 GB card | 2 to 5 hours | 1 to 3 USD | 30 |
| ACT | RTX 4090 or any 24 GB card | 2 to 5 hours | 1 to 3 USD | 50 |
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.

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.
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 gripperRepository'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.
| Kontrolpunkt | Gennemsnitlig MSE på traj 0 | Gennemsnitlig MAE på traj 0 |
|---|---|---|
| 500 | 87.5 | 5.63 |
| 1000 | 25.4 | 3.30 |
| 1500 | 13.2 | 2.18 |
| 2000 | 10.0 | 1.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.
| Symptom | Sandsynlig årsag |
|---|---|
| MSE flad eller stigende over checkpoints | Læringshastigheden er for lav, eller data indlæses slet ikke. Tjek --dataset-path og dataloader-arbejderne. |
| Forudsigelseskurven er flad eller konstant | modality.json-nøgler eller --modality-config-path stemmer ikke overens. Handlingsnøglerne er ikke mappet. |
| MSE enorm, eller NaN-tab under træning | Handlings- og tilstandsnormalisering. Verificer meta/stats, og at handlingsområderne er fysisk plausible. |
| God på bane 0, dårlig på tilbageholdte episoder | Datamangel, 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.
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| Aspekt | Isaac-GR00T launch_finetune.py | lerobot-train --policy.type=groot |
|---|---|---|
| Datasetversion | Kun LeRobot v2, konvertering påkrævet | Native LeRobot datasæt, ingen nedgradering |
| Modalitetsmapping | meta/modality.json plus en Python datakonfiguration | ingen modality.json; adfærd indstilles af --policy.* flags på kommandolinjen |
| Seed | ingen seed flag overhovedet | --seed, LeRobot standard 1000 |
| Relative handlinger | per-nøgle ActionConfig i datakonfigurationen | --policy.use_relative_actions plus --policy.relative_exclude_joints |
| Offentliggjorte referenceresultater | SO-100 open-loop MSE trend på demodata | LIBERO suiter, 96,5 procent gennemsnit over fire suiter |
| Implementeringssti | run_gr00t_server.py plus eval_so100.py over ZMQ | lerobot-rollout, med realtids-chunking (queue_threshold bør forblive på eller under 5) |
- 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.
- 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.
- Optag episoder med lerobot-record på SO-100. Du får et LeRobot v3.0 datasæt.
- Konverter det ned til v2.1 med scripts/lerobot_conversion/convert_v3_to_v2.py i sit eget virtualenv.
- Skriv meta/modality.json og en Python modalitetskonfiguration, registreret under EmbodimentTag.NEW_EMBODIMENT.
- Lej et 80 GB kort, klon med submoduler, uv sync, autentificer mod Hugging Face.
- Kør launch_finetune.py, derefter open_loop_eval.py på flere checkpoints, og sammenlign MSE-trenden, før du rører hardware.
- Træk checkpointet fra maskinen, før du ødelægger instansen, og byg derefter serving-stien til armen.
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.
Det samme job som en formular. Du vælger modellen og datasættet, backend lejer en GPU på spotmarkedet baseret på påkrævet VRAM, kører træneren og skriver checkpoints til objektlager. GR00T N1.7 på SO-100 guiden er præcis denne kombination; træningsmatrixen har alle andre model- og armparringer, inklusive GR00T N1.7 på SO-101.
| Hvad groot1.7 træneren sender | Value |
|---|---|
| Batchstørrelse | 32 |
| Læringshastighed | 1e-4 |
| Maksimale trin | 20000 |
| Gradientakkumulering | 1, and it does take effect for this trainer |
| Ekstra indstilling eksponeret i formularen | saveSteps |
| Basis checkpoint | nvidia/GR00T-N1.7-3B |
| Accepteret datasætformat | LeRobot v2.0 or v2.1 |
Datasættet kan komme fra et Hugging Face repo id, fra din egen maskine eller fra en session, du har optaget med desktopklienten. Inferens er et separat trin: platformen provisionerer en pod, der serverer politikken, og din lokale robotklient taler til dette endepunkt. Pods har en inaktiv watchdog og ødelægger sig selv efter en inaktiv periode, så en glemt browserfane ikke faktureres natten over. Hvis du hellere ikke vil klikke, findes de samme operationer på CLI'en og MCP-serveren.
GR00T N1.7 og Pi0.5 er kun cloud-baserede her; kun SmolVLA og ACT kører også lokalt. V2.1-kravet forsvinder heller ikke, fordi et v3.0-datasæt stadig skal konverteres ned, før GR00T-loaderen accepterer det. Og intet skriver dine modality.json-semantikker for dig: hvis dine kameranøgler eller din sprognøgle er forkerte, er de forkerte på begge ruter. Se træningsdokumentationen for, hvad backend gør og ikke gør på dine vegne.

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.
# 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"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æningsguidenSources
- NVIDIA Isaac-GR00T repository README, N1.7 main branch
- Isaac-GR00T: Fine-tune on Custom Embodiments (NEW_EMBODIMENT)
- Isaac-GR00T: Finetuning Models for the SO100/SO101 Robot
- Isaac-GR00T: Robot Data Preparation Guide, the GR00T LeRobot format
- Isaac-GR00T: modality config and ActionConfig reference
- Isaac-GR00T: Policy API Guide and the embodiment tag list
- Isaac-GR00T: FinetuneConfig dataclass with every CLI default
- Isaac-GR00T: the shared finetune launcher wrapper
- GR00T N1.7 FAQ: data volume, augmentation and deployment
- nvidia/GR00T-N1.7-3B model card, including the inference timing table
- nvidia/Cosmos-Reason2-2B, the gated VLM backbone used by N1.7
- GR00T N1: An Open Foundation Model for Generalist Humanoid Robots
- NVIDIA Isaac GR00T N1.7: Open Reasoning VLA Model for Humanoid Robots
- LeRobot: GR00T Policy, the lerobot-train recipe
- LeRobot: Imitation Learning on Real-World Robots (lerobot-record, lerobot-train)
Ready for high-quality robotics data?
AY-Robots connects your robots to skilled operators worldwide.
Get Started