引言

GR00T N1 是 NVIDIA 于 2025 年 3 月发布的开源人形机器人基础模型,首次将视觉-语言-动作(Vision-Language-Action, VLA)架构应用于通用人形机器人领域1。该模型的核心创新在于双系统架构:一个慢速推理系统(VLM,10Hz)负责高层语义理解和任务规划,一个快速动作生成系统(Diffusion Transformer,120Hz)负责低层运动控制。这种设计分离了”思考”与”执行”,使机器人能够同时具备强大的泛化能力和实时控制能力。

核心架构:双系统设计

┌─────────────────────────────────────────────────────────────────────┐
│                        GR00T N1 整体架构                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌──────────────┐     ┌──────────────┐     ┌──────────────────────┐ │
│  │   视觉输入    │     │   语言指令   │     │    本体感受          │ │
│  │ (多视角RGB)  │     │   (文本)     │     │  (关节状态/力矩)    │ │
│  └──────┬───────┘     └──────┬───────┘     └──────────┬───────────┘ │
│         │                    │                        │            │
│         └────────────────────┼────────────────────────┘            │
│                              ▼                                     │
│                    ┌─────────────────┐                              │
│                    │   Eagle-2 VLM   │   System 1: 慢速推理 (10Hz) │
│                    │  (视觉-语言模型) │                              │
│                    └────────┬────────┘                              │
│                             │                                        │
│                    ┌────────▼────────┐                              │
│                    │   隐式动作嵌入    │   Latent Action Embedding  │
│                    │   (Latent z)    │                              │
│                    └────────┬────────┘                              │
│                             │                                        │
│                             ▼                                        │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │              Diffusion Transformer Action Head               │   │
│  │              System 2: 快速动作生成 (120Hz)                  │   │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────────────┐ │   │
│  │  │噪声预测 │──│Temporal │──│FiLM     │──│  隐式动作解码    │ │   │
│  │  │网络     │  │Attention│  │调制     │  │  → 关节动作     │ │   │
│  │  └─────────┘  └─────────┘  └─────────┘  └─────────────────┘ │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                             │                                        │
│                             ▼                                        │
│                    ┌─────────────────┐                              │
│                    │    机器人执行     │                              │
│                    │   (关节控制信号)  │                              │
│                    └─────────────────┘                              │
└─────────────────────────────────────────────────────────────────────┘

系统 1:Eagle-2 VLM 推理模块(10Hz)

System 1 是基于 NVIDIA Eagle-2 视觉语言模型的推理引擎,运行频率为 10Hz,负责:

  • 视觉感知:处理来自机器人头部/手部的多视角 RGB 图像,提取场景特征
  • 语言理解:解析自然语言指令,提取任务目标、约束条件
  • 隐式动作预测:基于视觉和语言输入,预测下一时刻的隐式动作嵌入
  • 任务状态跟踪:维护任务进度,支持长程任务规划

VLM 模块的核心作用是将高维感知信息压缩为紧凑的语义表示,为动作生成提供高层意图指导。

系统 2:Diffusion Transformer 动作生成模块(120Hz)

System 2 是基于 Diffusion Transformer 的高速动作生成器,运行频率为 120Hz,负责:

  • 动作去噪:从高斯噪声 开始,通过 步迭代去噪,生成隐式动作
  • 时序建模:利用 Temporal Attention 机制捕捉动作序列的时间依赖关系
  • 条件调制:接收 VLM 输出的隐式动作嵌入 作为条件信号,通过 FiLM(Feature-wise Linear Modulation)层进行特征调制

120Hz 的高频输出确保了动作的平滑性和响应速度,能够满足人形机器人实时控制的需求。

流匹配动作生成

问题定义

GR00T N1 采用流匹配(Flow Matching) 作为动作生成的核心算法。给定条件 (视觉、语言、隐式动作嵌入),目标是学习一个从噪声分布到数据分布的映射。

定义数据分布为 ,噪声分布为 。流匹配旨在学习一个向量场 ,使得概率路径 演化到

线性插值路径

采用最简单的线性插值路径

其中:

  • 是噪声样本
  • 是目标动作
  • 是时间步

对应的目标向量场为:

损失函数

训练目标是让神经网络 预测目标向量场:

推理过程:常微分方程求解

推理时,从噪声 开始,通过求解 ODE:

使用 Euler 方法或更高阶的 ODE 求解器进行离散化:

通常采用 步迭代即可获得高质量动作。

隐式动作学习(Latent Actions)

为什么需要隐式动作?

传统 VLA 模型直接预测高维关节动作空间 (例如 30~50 维),面临以下挑战:

  1. 数据异构性:不同机器人具有不同的关节数量和配置,直接预测面临跨具身泛化难题
  2. 时序一致性:短时动作序列需要保持平滑性和物理一致性
  3. 语义对齐:低层动作与高层语义意图之间存在语义鸿沟

隐式动作的定义

GR00T N1 引入隐式动作(Latent Actions) 的概念:

  • 将高维关节动作 编码到低维隐式空间 (通常
  • 隐式动作 捕捉的是”运动意图”而非具体关节位移
  • 通过 VQ-VAE 或对比学习学习隐式动作表示

隐式动作的优势

方面显式动作隐式动作
跨具身泛化困难(需重映射)优秀(语义级别对齐)
动作平滑性需额外后处理隐式建模
表征能力完整但冗余紧凑但有信息损失
与 VLM 对齐语义鸿沟大自然对齐

学习方法

隐式动作通过以下两阶段学习:

阶段 1:预训练隐式动作编码器

从大规模机器人轨迹数据中学习编码器

或使用对比学习直接学习判别性隐式表示。

阶段 2:VLM + Diffusion 联合训练

VLM 模块预测隐式动作嵌入 ,Diffusion Transformer 在隐式空间中进行去噪,最后解码为具体动作:

数据金字塔策略

GR00T N1 的训练数据呈现明显的金字塔结构,体现了异构数据混合的策略:

                        ┌─────────────────┐
                        │   模拟数据        │  ← 金字塔顶层
                        │  (Synthetic)    │     数千万条轨迹
                        │  Physics Sim    │
                        └────────┬────────┘
                                 │
┌────────────────────────────────┼────────────────────────────────┐
│                        异构数据混合层                            │
├────────────────────────────────┼────────────────────────────────┤
│                                │                                │
│  ┌─────────────┐  ┌─────────────┴─────────────┐  ┌─────────────┐│
│  │ 人类视频数据 │  │    机器人演示数据           │  │ 运动捕捉数据 ││
│  │ (HumanVid)  │  │    (Robot Demonstrations) │  │ (MoCap)    ││
│  │  ARKitPose  │  │   真实机器人 + 遥操作      │  │            ││
│  │  EgoMotion  │  │                            │  │            ││
│  └─────────────┘  └────────────────────────────┘  └─────────────┘│
│                                │                                │
└────────────────────────────────┼────────────────────────────────┘
                                 │
                        ┌────────▼────────┐
                        │ 真实世界机器人数据 │  ← 金字塔底层
                        │  (Real Robot)   │     高质量但数量有限
                        │ 精细标注 + 反馈  │
                        └─────────────────┘

各层数据特点

数据层来源数量级质量成本标注难度
真实机器人遥操作收集10K~100K 条★★★★★极高
运动捕捉MoCap 系统100K~1M 条★★★★☆
人类视频Ego4D, etc.1M~10M 条★★★☆☆高(需Pose提取)
合成数据物理引擎10M+ 条★★☆☆☆极低

数据混合策略

GR00T N1 的关键洞察是合成数据与真实数据的协同效应

在模拟轨迹和神经轨迹(真实数据)同时使用时,相比仅用真实数据,性能提升 40%1

这说明合成数据不仅是真实数据的补充,更能提供互补的学习信号。

LAPA:人类视频动作标注

NVIDIA 提出的 LAPA(Large-scale Action Parsing from Videos) 管道可以从人类视频中自动生成动作标签:

  • 利用预训练的姿态估计模型(e.g., ARKit, MediaPipe)提取人体姿态
  • 通过逆运动学(IK)映射到机器人关节空间
  • 在 11 小时内自动生成 780K 条轨迹

这一管道极大缓解了机器人数据稀缺的瓶颈。

与 GR00T N1.5 的区别

特性GR00T N1GR00T N1.5
发布时间2025年3月2025年6月
模型规模2B 参数约 2B~7B 参数
架构改进基础双系统架构优化 VLM + Action Head 耦合
训练数据初期数据混合大规模数据重筛选
推理频率10Hz (VLM) / 120Hz (Action)保持相同
跨具身能力初步验证显著增强
Sim-to-Real基础方案改进域随机化
Benchmark 表现基线水平显著提升

主要改进方向

GR00T N1.5 的改进集中在:

  1. 数据质量筛选:更精细的数据过滤和质量评估
  2. 架构微调:VLM 与 Diffusion Transformer 之间的信息流优化
  3. 训练稳定性:改进课程学习策略,平衡不同数据源的分布
  4. 长程任务:增强任务状态跟踪和子目标分解能力

PyTorch 伪代码实现

流匹配 Diffusion Transformer

import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Dict, Optional
 
class FlowMatchingTransformer(nn.Module):
    """
    GR00T N1 的 Diffusion Transformer 动作生成模块
    实现流匹配算法进行动作去噪
    """
    
    def __init__(
        self,
        latent_dim: int = 32,      # 隐式动作维度
        action_dim: int = 39,       # 实际关节动作维度
        hidden_dim: int = 512,
        num_heads: int = 8,
        num_layers: int = 6,
        noise_steps: int = 50,      # 去噪步数
        context_dim: int = 768,     # VLM 上下文维度
    ):
        super().__init__()
        self.latent_dim = latent_dim
        self.action_dim = action_dim
        self.noise_steps = noise_steps
        
        # 隐式动作解码器:z -> a
        self.latent_to_action = nn.Sequential(
            nn.Linear(latent_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, action_dim)
        )
        
        # 时间步嵌入
        self.time_emb = nn.Sequential(
            nn.Linear(1, hidden_dim),
            nn.SiLU(),
            nn.Linear(hidden_dim, hidden_dim)
        )
        
        # 条件调制 (FiLM)
        self.film_scale = nn.Linear(context_dim, hidden_dim)
        self.film_shift = nn.Linear(context_dim, hidden_dim)
        
        # Transformer 去噪网络
        self.input_proj = nn.Linear(latent_dim + 1, hidden_dim)  # +1 for time
        encoder_layer = nn.TransformerEncoderLayer(
            d_model=hidden_dim,
            nhead=num_heads,
            dim_feedforward=hidden_dim * 4,
            dropout=0.1,
            batch_first=True
        )
        self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
        
        # 输出预测网络
        self.output_net = nn.Sequential(
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, latent_dim)
        )
    
    def vector_field(self, x: torch.Tensor, t: torch.Tensor, context: torch.Tensor) -> torch.Tensor:
        """
        预测向量场 v(x, t, c)
        
        Args:
            x: 当前隐式动作 [B, T, latent_dim] T=时序长度
            t: 时间步 [B, T, 1] 范围 [0, 1]
            context: 条件上下文(VLM输出)[B, context_dim]
        
        Returns:
            预测的向量场 [B, T, latent_dim]
        """
        B, T, D = x.shape
        
        # 时间步嵌入
        t_emb = self.time_emb(t)  # [B, T, hidden_dim]
        
        # FiLM 条件调制
        scale = self.film_scale(context).unsqueeze(1)  # [B, 1, hidden_dim]
        shift = self.film_shift(context).unsqueeze(1)   # [B, 1, hidden_dim]
        
        # 输入投影 + 条件调制
        h = self.input_proj(torch.cat([x, t], dim=-1))  # [B, T, hidden_dim]
        h = h * (1 + scale) + shift
        
        # Transformer 处理
        h = self.transformer(h)  # [B, T, hidden_dim]
        
        # 输出向量场(预测目标值 a1 - a0)
        v = self.output_net(h)  # [B, T, latent_dim]
        
        return v
    
    def forward(self, batch: Dict[str, torch.Tensor]) -> Dict[str, torch.Tensor]:
        """
        训练时的前向传播
        
        Args:
            batch: 包含以下键的字典
                - 'latent_action': 目标隐式动作 [B, T, latent_dim]
                - 'context': VLM 上下文 [B, context_dim]
                - 'noise_level': 可选,固定的噪声水平
        """
        latent_action = batch['latent_action']  # a_1
        context = batch['context']
        B, T, D = latent_action.shape
        
        # 采样时间步 t ~ Uniform(0, 1)
        t = torch.rand(B, 1, 1, device=latent_action.device)
        
        # 采样噪声
        noise = torch.randn_like(latent_action)  # a_0
        
        # 线性插值:a_t = (1-t)*a_0 + t*a_1
        x_t = (1 - t) * noise + t * latent_action
        
        # 预测向量场
        v_pred = self.vector_field(x_t, t * torch.ones(B, T, 1, device=x_t.device), context)
        
        # 目标向量场:v_target = a_1 - a_0
        v_target = latent_action - noise
        
        # MSE 损失
        loss = F.mse_loss(v_pred, v_target)
        
        return {'loss': loss}
    
    @torch.no_grad()
    def sample(
        self,
        context: torch.Tensor,
        num_steps: Optional[int] = None,
        ode_method: str = 'euler',
        step_size: float = 0.1
    ) -> torch.Tensor:
        """
        推理时的动作采样(ODE 求解)
        
        Args:
            context: VLM 上下文 [B, context_dim]
            num_steps: 去噪步数(None 则用连续 ODE)
            ode_method: ODE 求解方法 ('euler', 'midpoint')
            step_size: 步长
        
        Returns:
            生成的隐式动作 [B, T, latent_dim]
        """
        num_steps = num_steps or self.noise_steps
        B = context.shape[0]
        T = 1  # 单步生成
        
        # 从噪声开始
        x = torch.randn(B, T, self.latent_dim, device=context.device)
        
        # 离散时间步
        dt = 1.0 / num_steps
        
        for i in range(num_steps):
            t = torch.full((B, T, 1), i * dt, device=context.device)
            
            # 预测向量场
            v = self.vector_field(x, t, context)
            
            # Euler 更新
            x = x + dt * v
        
        # 转换为实际动作
        action = self.latent_to_action(x)
        
        return action
 
 
class GR00T_N1(nn.Module):
    """
    GR00T N1 完整模型
    包含 VLM backbone 和 Diffusion Transformer action head
    """
    
    def __init__(self, config: dict):
        super().__init__()
        
        # VLM backbone (Eagle-2)
        self.vlm = self._build_vlm(config)
        
        # Diffusion action head
        self.action_head = FlowMatchingTransformer(
            latent_dim=config.get('latent_dim', 32),
            action_dim=config.get('action_dim', 39),
            hidden_dim=config.get('hidden_dim', 512),
            num_heads=config.get('num_heads', 8),
            num_layers=config.get('num_layers', 6),
            noise_steps=config.get('noise_steps', 50),
            context_dim=config.get('context_dim', 768),
        )
        
        # 隐式动作编码器
        self.latent_encoder = nn.Sequential(
            nn.Linear(config.get('action_dim', 39), 256),
            nn.ReLU(),
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, config.get('latent_dim', 32))
        )
    
    def _build_vlm(self, config: dict):
        # 这里使用简化的 VLM 接口
        # 实际使用 NVIDIA Eagle-2 或类似模型
        from transformers import AutoModel
        
        model = AutoModel.from_pretrained(config.get('vlm_ckpt', 'Eagle-2'))
        return model
    
    def forward(self, observations: Dict[str, torch.Tensor]) -> Dict[str, torch.Tensor]:
        """
        完整前向传播
        
        Args:
            observations: 观测数据
                - 'image': RGB 图像 [B, C, H, W]
                - 'language': 语言指令 token IDs [B, L]
                - 'proprio': 本体感受 [B, D_proprio]
        
        Returns:
            预测的动作 [B, action_dim]
        """
        # Step 1: VLM 推理 (10Hz) - 提取高层语义
        vlm_output = self.vlm(
            pixel_values=observations['image'],
            input_ids=observations['language'],
            return_dict=True
        )
        
        # 提取隐式动作嵌入和上下文
        latent_hint = vlm_output['latent_action']      # 隐式动作提示
        context = vlm_output['multimodal_embedding']   # 多模态上下文
        
        # Step 2: Diffusion 动作生成 (120Hz)
        action_latent = self.action_head.sample(
            context=context,
            num_steps=20  # 可根据延迟要求调整
        )
        
        # Step 3: 隐式动作解码为实际动作
        action = self.action_head.latent_to_action(action_latent)
        
        return {'action': action, 'latent': latent_hint}
 
 
# 训练循环示例
def train_step(model: GR00T_N1, batch: dict, optimizer: torch.optim.Optimizer):
    model.train()
    
    # 前向传播
    outputs = model(observations={
        'image': batch['image'],
        'language': batch['language'],
        'proprio': batch['proprio']
    })
    
    # 计算流匹配损失
    loss_dict = model.action_head({'latent_action': batch['latent_action'], 'context': outputs['context']})
    loss = loss_dict['loss']
    
    # 反向传播
    optimizer.zero_grad()
    loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
    optimizer.step()
    
    return {'loss': loss.item()}

隐式动作编码器训练

class LatentActionVAE(nn.Module):
    """
    隐式动作的 VQ-VAE 编码器
    用于将高维关节动作压缩到低维隐式空间
    """
    
    def __init__(self, action_dim: int = 39, latent_dim: int = 32, hidden_dim: int = 256):
        super().__init__()
        
        # 编码器
        self.encoder = nn.Sequential(
            nn.Linear(action_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, latent_dim * 2)  # 预测均值和方差
        )
        
        # 解码器
        self.decoder = nn.Sequential(
            nn.Linear(latent_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, action_dim)
        )
        
        # VQ 层(可选)
        self.codebook = nn.Embedding(num_embeddings=256, embedding_dim=latent_dim)
    
    def reparameterize(self, mu: torch.Tensor, logvar: torch.Tensor) -> torch.Tensor:
        std = torch.exp(0.5 * logvar)
        eps = torch.randn_like(std)
        return mu + eps * std
    
    def forward(self, action: torch.Tensor) -> tuple:
        """
        Args:
            action: 原始关节动作 [B, action_dim]
        
        Returns:
            recon_action: 重构动作 [B, action_dim]
            latent: 采样得到的隐式动作 [B, latent_dim]
            mu, logvar: 分布参数
        """
        # 编码
        h = self.encoder(action)
        mu, logvar = h.chunk(2, dim=-1)
        
        # 重参数化
        latent = self.reparameterize(mu, logvar)
        
        # 解码
        recon_action = self.decoder(latent)
        
        return recon_action, latent, mu, logvar
 
 
def vae_loss(recon_action: torch.Tensor, action: torch.Tensor, 
             mu: torch.Tensor, logvar: torch.Tensor, beta: float = 0.01):
    """
    VAE 损失函数
    
    Args:
        recon_action: 重构动作
        action: 原始动作
        mu, logvar: 潜在分布参数
        beta: KL 散度权重
    """
    # 重构损失
    recon_loss = F.mse_loss(recon_action, action)
    
    # KL 散度
    kl_loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
    
    return recon_loss + beta * kl_loss

实验结果与消融分析

基准测试表现

GR00T N1 在多个标准基准上进行了评估:

基准任务类型GR00T N1最佳 Baseline提升
LIBERO长期任务72.3%65.1%+7.2%
CALVIN长程操作81.5%76.8%+4.7%
Sim-to-Real域迁移68.2%54.3%+13.9%

消融实验关键发现

  1. 双系统频率分离

    • 固定频率(如 30Hz) vs 分离设计(10Hz VLM + 120Hz Action)
    • 结果:分离设计在保持响应速度的同时,任务成功率提升 12%
  2. 隐式动作的作用

    • 直接预测关节动作 vs 隐式动作 + 解码
    • 结果:隐式动作使跨具身泛化能力提升 18%
  3. 数据金字塔的效果

    • 仅真实数据 vs 混合合成数据
    • 结果:混合训练使性能提升 40%
  4. 流匹配 vs DDPM

    • 使用 DDPM(100步去噪)vs 流匹配(20步去噪)
    • 结果:流匹配在 5倍推理加速 的同时,保持相近的动作质量

架构总结

GR00T N1 的核心设计哲学可以概括为:

“慢思考,快执行” —— 将复杂的语义推理(10Hz)与实时的动作控制(120Hz)解耦,实现既有泛化能力又有实时性的通用人形机器人控制。

这种双系统架构借鉴了人类认知的快慢系统理论:

  • 系统 1(VLM):类似人类的直觉和经验判断,负责”理解要做什么”
  • 系统 2(Diffusion):类似人类的精确运动控制,负责”怎么做”

通过隐式动作作为两个系统之间的桥梁,实现了语义层与执行层的有效连接。

参考资料


本文档基于 GR00T N1 论文(arXiv:2503.14734)撰写,内容持续更新中。

Footnotes

  1. Bjorck, J., et al. (2025). GR00T N1: An Open Foundation Model for Generalist Humanoid Robots. arXiv:2503.14734. NVIDIA Research. 2