Pular para o conteúdo principal

Estágio 4 · Capítulo 21 · Prática

21. Ajuste fino do reBot Arm com Isaac GR00T

Capítulo 21 do Curso para Iniciantes em IA Física da Seeed — configuração do ambiente, download do modelo base, caminho do conjunto de dados, ajuste fino com GPU única e múltiplas GPUs, monitoramento de VRAM e loss, salvamento de checkpoints, inferência em robô real, solução de problemas e dicas de treinamento.

Este capítulo é baseado em LeRobot + GR00T N1.7 (nvidia/GR00T-N1.7-3B). Certifique-se de que o conjunto de dados do Capítulo 20 esteja pronto.

Ajuste fino com Isaac GR00T

21.1 Configuração do ambiente​

Ambiente

21.1 Configuração do ambiente

Configuração do ambiente

Hardware recomendado​

ConfiguraçãoMínimo para inferênciaRecomendado para ajuste fino
GPU16 GB+ (RTX 4090 pode executar inferência)40 GB+ (L40 / A100 80GB / H100); o ajuste fino oficial em simulação requer ≥ 48 GB
SistemaLinux (Ubuntu 22.04+)Linux nativo ou WSL2
Armazenamento50 GB de espaço livre100 GB+ (incluindo cache de modelo)
atenção

GR00T requer uma GPU CUDA; treinamento apenas em CPU não é suportado. O ajuste fino padrão (projector + cabeça DiT) atinge um pico de cerca de 35 GB. RTX 4090 / 24 GB não consegue fazer ajuste fino completo e é adequada apenas para inferência; se você precisar treinar em 24 GB, use LoRA / PEFT (pip install "lerobot[peft]"), cujos resultados não são diretamente comparáveis ao ajuste fino completo oficial.

Instalando LeRobot e dependências do GR00T​

Após criar um ambiente Python 3.12 conforme a documentação de instalação do LeRobot:

conda create -y -n lerobot python=3.12
conda activate lerobot

# Install ffmpeg (video decoding, Linux + TorchCodec)
conda install ffmpeg -c conda-forge

# Install LeRobot + GR00T + training tools
pip install "lerobot[groot,training]"

Flash Attention (Importante)​

GR00T N1.7 depende de Flash Attention para aceleração. Recomenda-se instalar primeiro o PyTorch compatível com sua versão de CUDA e, em seguida, instalar o flash-attn:

# Example: CUDA 12.8 + PyTorch 2.7 (RTX 50 series can reference this combo)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128

pip install ninja "packaging>=24.2,<26.0"
pip install "flash-attn>=2.5.9,<3.0.0" --no-build-isolation

python -c "import flash_attn; print(f'Flash Attention {flash_attn.__version__} OK')"

Se a compilação do flash-attn falhar, causas comuns:

  1. Versões de PyTorch e CUDA incompatíveis -> reinstale o wheel correspondente.
  2. Ferramentas de compilação ausentes -> sudo apt install build-essential.
  3. VRAM/memória insuficiente -> feche outros processos de GPU e tente novamente.

Fazendo login no Hugging Face e W&B​

huggingface-cli login
wandb login # optional, for training curve visualization

21.2 Download do modelo base​

Modelo

21.2 Download do modelo base

Download do modelo base

O modelo base está hospedado no Hugging Face:

nvidia/GR00T-N1.7-3B

No primeiro treinamento, o LeRobot faz o download automático para ~/.cache/huggingface/hub/. O backbone VLM do N1.7, nvidia/Cosmos-Reason2-2B, é um modelo restrito; você deve aceitar os termos no Hugging Face antes de executar huggingface-cli login. Você também pode fazer o pré-download manualmente:

huggingface-cli download nvidia/GR00T-N1.7-3B --local-dir ./models/GR00T-N1.7-3B
huggingface-cli download nvidia/Cosmos-Reason2-2B

Especifique nos argumentos de treinamento:

--policy.base_model_path=nvidia/GR00T-N1.7-3B
nota

O LeRobot atual só oferece suporte ao GR00T N1.7. N1.5 requer fixar a versão antiga lerobot==0.5.1, o que não é abordado neste tutorial.

21.3 Configurando o caminho do conjunto de dados​

Caminho do conjunto de dados

21.3 Configurando o caminho do conjunto de dados

Configurando o caminho do conjunto de dados

Conjunto de dados local​

Se os dados estiverem no cache local (não enviados para o Hub), repo_id deve corresponder ao usado durante a gravação:

export DATASET_REPO_ID="seeed_rebot_b601_rs/pick_cube"   # for DM: seeed_rebot_b601_dm/pick_cube

O LeRobot carrega automaticamente de ~/.cache/huggingface/lerobot/.

Conjunto de dados no Hub​

export HF_USER="your_hf_username"
export DATASET_REPO_ID="${HF_USER}/rebot_vla_pick_cube"

Certifique-se de que o conjunto de dados no Hub inclua meta/modality.json (criado no Capítulo 20).

21.4 Iniciando o ajuste fino com GPU única​

Ajuste fino

21.4 Iniciando o ajuste fino com GPU única

Ajuste fino com GPU única

O comando a seguir tem como alvo o reBot Arm braço único, new_embodiment (substitua o repo_id do conjunto de dados para RS/DM). chunk_size=40 está alinhado com o action_horizon oficial do N1.7; o código-fonte groot do LeRobot usa 50 por padrão, ambos bem maiores que 16 do N1.5/N1.6 — não use 16.

export HF_USER="your_hf_username"
export DATASET_REPO_ID="seeed_rebot_b601_rs/pick_cube" # local or Hub; for DM use b601_dm
export REPO_ID="${HF_USER}/rebot_groot17_pick_cube" # uploaded model name after fine-tuning
export OUTPUT_DIR="outputs/train/${REPO_ID}"

lerobot-train \
--dataset.repo_id=${DATASET_REPO_ID} \
--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=40 \
--policy.n_action_steps=40 \
--policy.use_relative_actions=true \
--policy.relative_exclude_joints='["gripper"]' \
--policy.use_bf16=true \
--policy.push_to_hub=true \
--policy.repo_id=${REPO_ID} \
--seed=42 \
--batch_size=32 \
--steps=20000 \
--save_checkpoint=true \
--save_freq=5000 \
--use_policy_training_preset=true \
--env_eval_freq=0 \
--eval_steps=0 \
--log_freq=10 \
--output_dir=${OUTPUT_DIR} \
--job_name=rebot_groot_finetune \
--wandb.enable=true \
--wandb.disable_artifact=true

Parâmetros principais​

ParâmetroValorDescrição
--policy.typegrootUsar a política GR00T
--policy.embodiment_tagnew_embodimentEmbodiment personalizado do reBot
--policy.chunk_size40Alinhado com N1.7 action_horizon=40 (não use 16)
--policy.n_action_steps40Normalmente corresponde ao chunk durante o treinamento; pode ser reduzido na inferência
--policy.use_relative_actionstruePré-processamento relativo de juntas do LeRobot, não EEF relativo
--policy.relative_exclude_joints["gripper"]Manter o gripper em controle absoluto
--policy.use_bf16truePrecisão mista, economiza VRAM
--batch_size32 (ajustável)32 em uma placa de 40 GB; reduza para 8 ou 16 se ocorrer OOM
--steps20000Passos de ajuste fino; pode ser reduzido para 10000 com poucos dados
--save_freq5000Salvar um checkpoint a cada 5000 passos

Para salvar apenas localmente sem enviar para o Hub:

--policy.push_to_hub=false

21.5 Iniciando o ajuste fino com múltiplas GPUs​

Múltiplas GPUs

21.5 Iniciando o ajuste fino com múltiplas GPUs

Ajuste fino com múltiplas GPUs

Para ambientes com múltiplas GPUs, use accelerate:

export NUM_GPUS=2
export BATCH_SIZE=16 # per-GPU batch; total batch = 16 x num GPUs
export NUM_STEPS=20000
export SAVE_FREQ=5000
export LOG_FREQ=10
export DATASET_REPO_ID="seeed_rebot_b601_rs/pick_cube"
export REPO_ID="${HF_USER}/rebot_groot17_pick_cube"
export OUTPUT_DIR="outputs/train/${REPO_ID}"

accelerate launch \
--multi_gpu \
--num_processes=${NUM_GPUS} \
$(which lerobot-train) \
--dataset.repo_id=${DATASET_REPO_ID} \
--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=40 \
--policy.n_action_steps=40 \
--policy.use_relative_actions=true \
--policy.relative_exclude_joints='["gripper"]' \
--policy.use_bf16=true \
--policy.push_to_hub=true \
--policy.repo_id=${REPO_ID} \
--output_dir=${OUTPUT_DIR} \
--save_checkpoint=true \
--batch_size=${BATCH_SIZE} \
--steps=${NUM_STEPS} \
--save_freq=${SAVE_FREQ} \
--log_freq=${LOG_FREQ} \
--use_policy_training_preset=true \
--wandb.enable=true \
--wandb.disable_artifact=true \
--job_name=rebot_groot_multi_gpu

21.6 Monitorando VRAM, Loss e Logs de Treinamento​

Monitoramento

21.6 Monitorando VRAM, Loss e Logs de Treinamento

Monitorando VRAM, loss e logs de treinamento

Monitor de VRAM​

Em um terminal separado:

watch -n 1 nvidia-smi
SintomaAção
OOM (out of memory)Primeiro confirme GPU ≥ 40 GB; depois reduza --batch_size e mantenha --policy.use_bf16=true. Em 24 GB, use LoRA/PEFT em vez de forçar um batch menor para fine-tuning completo
Folga de VRAM disponívelAumente batch_size de forma apropriada para acelerar o treinamento
Baixa utilizaçãoVerifique num_workers; confirme que os dados estão em um SSD local

Curva de Loss​

Após habilitar o W&B, observe na web a tendência de queda de train/loss. Um fine-tuning saudável:

  • A loss cai rapidamente nos primeiros 1000 passos.
  • Entra em platô após 5000 passos.
  • Se a loss não diminuir: verifique modality.json, dimensões dos dados e anotações de linguagem.

Logs Locais​

tail -f ${OUTPUT_DIR}/logs/*.log

Ou visualize o dashboard offline/online do W&B.

21.7 Salvando Checkpoints​

Checkpoints

21.7 Salvando Checkpoints

Salvando checkpoints

Durante o treinamento, os checkpoints são salvos em:

outputs/train/<REPO_ID>/
├── checkpoints/
│ ├── 005000/
│ │ └── pretrained_model/
│ ├── 010000/
│ ├── 015000/
│ ├── 020000/
│ └── last/
│ └── pretrained_model/ ← latest weights, use this for inference
└── logs/

Inferência com um checkpoint específico​

--policy.path=outputs/train/${REPO_ID}/checkpoints/010000/pretrained_model

Enviando para o Hub​

Se --policy.push_to_hub=true, o envio acontece automaticamente ao final do treinamento. Upload manual:

huggingface-cli upload ${REPO_ID} \
outputs/train/${REPO_ID}/checkpoints/last/pretrained_model

21.8 Inferência e Avaliação em Robô Real​

Inferência

21.8 Inferência e Avaliação em Robô Real

Inferência e avaliação em robô real

Método A: lerobot-record com gravação de política (recomendado para iniciantes)​

Igual ao fluxo de avaliação ACT, apenas troque pelo checkpoint GR00T. Abaixo usamos B601-RS como exemplo; DM substitui type / port / can_adapter.

export HF_USER="your_hf_username"
export MODEL_PATH="${HF_USER}/rebot_groot17_pick_cube" # Hub or local path

# RS CAN
sudo ip link set can0 down 2>/dev/null
sudo ip link set can0 type can bitrate 1000000
sudo ip link set can0 up

lerobot-record \
--robot.type=seeed_b601_rs_follower \
--robot.port=can0 \
--robot.id=follower1 \
--robot.can_adapter=socketcan \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--display_data=true \
--dataset.repo_id=${HF_USER}/eval_groot_rebot \
--dataset.num_episodes=10 \
--dataset.single_task="put the black cube on the blue tray" \
--dataset.episode_time_s=30 \
--dataset.reset_time_s=15 \
--policy.path=${MODEL_PATH} \
--policy.base_model_path=nvidia/GR00T-N1.7-3B \
--policy.embodiment_tag=new_embodiment
atenção

Os front e side em --robot.cameras devem corresponder aos nomes de chave do conjunto de dados de treinamento.

Método B: implantação em tempo real com lerobot-rollout (avançado)​

Adequado para controle em malha fechada de baixa latência; oferece suporte a RTC (Real-Time Chunking):

export MODEL_PATH="${HF_USER}/rebot_groot17_pick_cube"

lerobot-rollout \
--strategy.type=base \
--policy.path=${MODEL_PATH} \
--policy.base_model_path=nvidia/GR00T-N1.7-3B \
--policy.embodiment_tag=new_embodiment \
--policy.chunk_size=40 \
--policy.n_action_steps=20 \
--policy.use_relative_actions=true \
--policy.relative_exclude_joints='["gripper"]' \
--robot.type=seeed_b601_rs_follower \
--robot.port=can0 \
--robot.id=follower1 \
--robot.can_adapter=socketcan \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30, fourcc: "MJPG"}, side: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30, fourcc: "MJPG"}}" \
--task="put the black cube on the blue tray" \
--duration=60 \
--device=cuda \
--display_data=true \
--inference.type=rtc \
--inference.rtc.enabled=true \
--inference.rtc.execution_horizon=20 \
--inference.queue_threshold=2

Se o RTC causar jitter, defina --inference.rtc.enabled=false. queue_threshold é recomendado em 2-5 (definir como 0 dispara reinferência com muita frequência e tende a causar jitter).

21.9 FAQ de Solução de Problemas​

Solução de Problemas

21.9 FAQ de Solução de Problemas

FAQ de solução de problemas

Falha no download do modelo​

# Set mirror or proxy and retry
export HF_ENDPOINT=https://hf-mirror.com # optional
huggingface-cli download nvidia/GR00T-N1.7-3B
huggingface-cli download nvidia/Cosmos-Reason2-2B # gated; accept terms on HF first

Incompatibilidade de versão CUDA / PyTorch​

python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.version.cuda)"
nvidia-smi

Garanta que a versão do driver atenda aos requisitos de CUDA do PyTorch.

Falha na instalação do Flash Attention​

  1. Confirme que nvcc --version corresponde ao CUDA do PyTorch.
  2. Tente um wheel pré-compilado: pip install flash-attn --no-build-isolation.
  3. A série RTX 50 pode tentar: pip install flash_attn==2.8.0.post2 torch==2.7.1 --no-build-isolation.
  4. Se ainda falhar, consulte a documentação oficial do Isaac GR00T.

A loss de treinamento é normal, mas o robô real se move de forma errática​

Possível causaInvestigação
Ordem de juntas inconsistenteCompare os metadados do conjunto de dados com --robot.cameras / driver
Unidade de ângulo incorretaConfirme se deg/rad é consistente entre treinamento e inferência
Incompatibilidade no nome da chave da câmerafront/side alinhados com os dados de treinamento
embodiment_tag incorretoDeve ser new_embodiment
Incompatibilidade na instrução de linguagemO padrão de frase de --task corresponde aos dados de treinamento
Ações relativas não restauradas corretamenteConfirme se use_relative_actions corresponde entre treinamento e inferência; isto é relativo à junta, não ao EEF relativo

Erro mean is infinity​

Geralmente causado por nomes de chave de câmera no momento da avaliação que não correspondem aos do treinamento. Verifique os nomes de chave em --robot.cameras.

21.10 Sugestões de Melhoria de Treinamento​

Melhorias

21.10 Sugestões de Melhoria de Treinamento

Sugestões de melhoria de treinamento
DireçãoSugestão
Volume de dadosComece com 50 episódios para uma única tarefa, depois expanda para 100+
Diversidade de dadosVarie posições de objetos, iluminação e poses iniciais
Aumento de dadosMantenha --dataset.image_transforms.enable=true
Passos10k-15k com poucos dados; 20k-30k com mais dados
InferênciaPrimeiro tente n_action_steps=20 (deve ser ≤ chunk_size=40 de treinamento), depois ajuste o RTC
IteraçãoColetar dados para casos de falha -> mesclar conjuntos de dados -> continuar o fine-tuning

21.11 Resumo do Capítulo​

Resumo

21.11 Resumo do Capítulo

  • Ambiente: pip install "lerobot[groot,training]" + Flash Attention + GPU de 40 GB+ para fine-tuning (16 GB apenas para inferência).
  • Modelo base: nvidia/GR00T-N1.7-3B (backbone Cosmos-Reason2-2B).
  • Treinamento: lerobot-train --policy.type=groot --policy.embodiment_tag=new_embodiment.
  • Configuração-chave do reBot: espaço de juntas + ações relativas às juntas opcionais do LeRobot (gripper absoluto) + chunk_size=40 (alinhado com N1.7).
  • Variante de modelo: RS usa seeed_b601_rs_follower + can0 + socketcan; DM usa seeed_b601_dm_follower + /dev/ttyACM0 + damiao.
  • Avaliação: lerobot-record ou lerobot-rollout; câmeras e linguagem devem estar alinhadas com o treinamento.
  • O checkpoint está em outputs/train/<REPO_ID>/checkpoints/last/pretrained_model.

Após concluir este capítulo, você deverá ser capaz de acionar a política VLA no reBot Arm com instruções em linguagem natural. Se os resultados não forem satisfatórios, primeiro volte ao Capítulo 20 para verificar a qualidade dos dados, depois aumente a quantidade de demonstrações e itere o fine-tuning.

Loading Comments...