一、概述
Ψ₀(Psi-Zero)是南加州大学物理超智能实验室(USC PSI Lab)于2026年3月发布的开源人形机器人视觉-语言-动作(VLA)基础模型,相关论文发表于arXiv:2603.12263,并在RSS 2026会议上发表。12
核心创新点
| 特性 | 描述 |
|---|---|
| 核心洞察 | 正确的数据策略比数据量更重要 |
| 预训练数据 | 800小时人类第一人称视频 + 30小时真实机器人交互 |
| 模型架构 | 2.5B VLM + 700M MM-DiT动作专家 |
| 推理机制 | 实时动作分块(RTC) |
| 训练范式 | 三阶段渐进式训练 |
Ψ₀的核心理念是:与其堆砌海量机器人数据,不如精心设计数据来源和训练策略。这一”less is more”的思想使其在仅使用约830小时数据的情况下,达到了与使用更多数据的竞品相当甚至更好的性能。
二、核心洞察:数据策略优先
2.1 传统方法的困境
过去的人形机器人VLA模型往往追求”数据为王”:
- 收集百万级别的机器人轨迹数据
- 投入大量计算资源进行大规模训练
- 但泛化能力依然有限
2.2 Ψ₀的数据哲学
Ψ₀团队提出了一个关键洞察:数据来源的多样性比数据量更重要。
┌─────────────────────────────────────────────────────────────┐
│ Ψ₀ 数据策略 │
├─────────────────────────────────────────────────────────────┤
│ 800小时 人类第一人称视频 │
│ ├── 包含丰富的日常操作、导航、交互行为 │
│ ├── 涵盖多样化的场景和任务 │
│ └── 学习人类的运动模式和意图理解 │
├─────────────────────────────────────────────────────────────┤
│ + 30小时 真实机器人数据 │
│ └── 关键:建立人类动作到机器人动作的映射 │
└─────────────────────────────────────────────────────────────┘
2.3 为什么这种方法有效?
- 跨具身迁移:人类视频中的操作知识天然具有多样性,可以泛化到不同的机器人形态
- 效率提升:800小时精心挑选的人类视频,胜过数百万条同质化的机器人轨迹
- 成本降低:数据采集成本显著降低,使小团队也能训练基础模型
三、三阶段训练流程
Ψ₀采用三阶段渐进式训练范式,逐步从通用视觉-语言理解过渡到人形机器人控制。
3.1 阶段总览
┌─────────────────────────────────────────────────────────────────────────┐
│ Ψ₀ 三阶段训练流程 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Stage 1 │ │ Stage 2 │ │ Stage 3 │ │
│ │ VLM预训练 │ ──▶ │ 动作专家 │ ──▶ │ 任务微调 │ │
│ │ (人类视频) │ │ 后训练 │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │
│ │ 800h │ │ 800h │ │ 任务相关 │ │
│ │ 人类视频 │ │ + 30h │ │ 少量数据 │ │
│ └─────────┘ │ 机器人 │ └─────────┘ │
│ └─────────┘ │
│ │
│ 输出: 2.5B VLM 输出: +700M MM-DiT 输出: 领域适配 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
3.2 Stage 1: VLM预训练
目标:建立强大的视觉-语言基础理解能力
数据:
- 约800小时的自我中心(egocentric)人类视频
- 来自多种场景:厨房、办公室、仓库、户外等
- 涵盖丰富的操作任务:抓取、放置、推拉、旋转等
方法:
- 使用标准的VLM预训练范式
- 训练视觉编码器与语言模型的联合表示
- 学习图像-文本对齐的通用语义理解
核心价值:
- VLM习得了对人类动作的语义理解
- 理解”做什么”(意图识别)
- 为后续的动作生成奠定基础
3.3 Stage 2: 动作专家后训练
目标:将VLM的语义理解能力转化为动作生成能力
数据:
- Stage 1使用的800小时人类视频(保留语义知识)
- 新增约30小时真实人形机器人交互数据
- 关键桥梁:建立人类动作到机器人动作的映射
架构升级:
┌─────────────────────────────────────────────────────────┐
│ MM-DiT 动作专家 │
│ │
│ VLM语义特征 ──▶ ┌────────────────────┐ │
│ │ Cross-Attention │ ──▶ 动作序列 │
│ 隐变量 z ──▶ │ (7层) │ │
│ └────────────────────┘ │
│ │
│ 使用Flow Matching生成连续动作 │
└─────────────────────────────────────────────────────────┘
技术细节:
- 添加700M参数的MM-DiT(Multi-Modal DiT)作为动作专家
- 使用Flow Matching而非传统扩散模型进行动作生成
- 7层交叉注意力结构,融合VLM特征与隐变量
3.4 Stage 3: 任务微调
目标:适配特定任务场景
方法:
- 使用少量(任务相关的)高质量机器人数据
- 保持模型泛化能力的同时提升任务性能
- 可根据部署需求灵活调整
典型应用:
- 仓库物流任务
- 家庭服务场景
- 工业装配操作
四、MM-DiT架构详解
4.1 架构概述
MM-DiT(Multi-Modal Diffusion Transformer)是Ψ₀的动作生成核心模块。它在VLM的基础上添加了一个轻量级的动作生成头。
┌──────────────────────────────────────────────────────────────────┐
│ MM-DiT 架构 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ 输入表示 │
│ ┌─────────────┐ │
│ │ VLM视觉特征 │ 来自预训练VLM的深层表示 │
│ │ Visual(F) │ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Cross-Attn │ Layer × 7 │
│ │ (Q, K, V) │ Q = 动作查询 │
│ └──────┬──────┘ K,V = VLM特征 │
│ │ │
│ ┌──────┴──────┐ │
│ │ DiT Block │ 隐向量 z 的逐步变换 │
│ │ (标准残差) │ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ 输出层 │ 生成 $a_t$ 动作向量 │
│ │ Linear │ │
│ └─────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
4.2 Flow Matching动作生成
Ψ₀采用Flow Matching进行连续动作的生成,这是一种比传统扩散模型更高效的方法。
核心思想:
- 定义从噪声 到数据 的概率路径
- 学习一个向量场 来驱动这个过程
- 通过ODE求解器从噪声生成动作
数学表述:
其中:
- :初始噪声
- :目标动作序列
- :时间步
- :插值后的隐变量
4.3 与其他扩散方法的对比
| 方法 | 特点 | 优缺点 |
|---|---|---|
| DDPM | 逐步去噪,训练稳定 | 推理慢,需要多步迭代 |
| DDIM | 加速采样 | 质量略有下降 |
| Flow Matching | 直接预测向量场 | 推理效率高,生成质量好 |
| rectified flow | 线性插值 | 简化训练,简单高效 |
五、实时动作分块(RTC)机制
5.1 为什么需要RTC?
人形机器人的控制面临两个挑战:
- 反应速度:需要低延迟的实时响应
- 平滑性:避免动作抖动或不连贯
传统的VLA推理方式:
用户指令 ──▶ VLA推理(慢) ──▶ 执行动作 ──▶ 等待 ──▶ 下一个推理
这种串行方式的问题:
- 推理延迟高(可能数百毫秒)
- 动作之间可能不连贯
- 实时性差
5.2 RTC核心思想
RTC(Real-Time Chunking)通过异步推理+动作分块解决上述问题:
┌─────────────────────────────────────────────────────────────────┐
│ RTC 工作原理 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 时间线 ──▶─────────────────────────────────────────────────────│
│ │
│ 推理线程: ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ P1 │ ──▶ │ P2 │ ──▶ │ P3 │ ... │
│ └─────┘ └─────┘ └─────┘ │
│ │ │ │ │
│ 执行线程: │ ┌─────┘ ┌─────┘ │
│ ▼ ▼ ▼ │
│ 执行: [A1] [A2] [A3] [A4] [A5] [A6] ... │
│ └─────┘ └─────┘ │
│ chunk chunk │
│ │
│ P1: 推理预测动作块 A1-A4 │
│ 执行: 逐个执行已生成的动作 │
│ 并行: 执行时同时推理下一个块 │
│ │
└─────────────────────────────────────────────────────────────────┘
5.3 关键技术细节
动作块结构:
- 每个块包含多个时间步的动作预测(如4-8步)
- 块之间有重叠区域,用于平滑过渡
- 使用”inpainting”机制处理重叠部分
异步流水线:
- 主线程维护执行状态
- 推理线程异步生成下一个动作块
- 通过共享缓冲区传递预测结果
- 执行时跳过已执行的动作
延迟分析:
| 指标 | 传统方法 | RTC |
|---|---|---|
| 感知延迟 | 100ms | 100ms |
| 推理延迟 | 200ms | 200ms(隐藏) |
| 执行频率 | 10Hz | 30Hz |
| 有效延迟 | 300ms | 100ms |
5.4 RTC伪代码
import torch
import threading
from collections import deque
class RealTimeChunking:
"""
实时动作分块推理
- 推理线程异步生成动作块
- 主线程执行已生成的动作
"""
def __init__(self, model, chunk_size=8, overlap=2, device='cuda'):
self.model = model
self.chunk_size = chunk_size # 每个块的动作步数
self.overlap = overlap # 块之间的重叠步数
self.device = device
# 动作缓冲区(双缓冲)
self.action_buffer = deque()
self.lock = threading.Lock()
# 控制信号
self.stop_flag = threading.Event()
self.new_chunk_event = threading.Event()
@torch.no_grad()
def inference_thread(self, obs_queue, command):
"""
推理线程:持续生成动作块
"""
# 初始化:生成第一个块
obs = obs_queue.get()
action_chunk = self._predict_chunk(obs, command, prev_actions=None)
with self.lock:
self.action_buffer.append(action_chunk)
self.new_chunk_event.set()
# 持续推理循环
while not self.stop_flag.is_set():
# 等待需要新推理的信号
self.new_chunk_event.wait()
self.new_chunk_event.clear()
if self.stop_flag.is_set():
break
# 获取当前观察和前一个块的最后几个动作(用于重叠)
obs = obs_queue.get()
with self.lock:
prev_chunk = self.action_buffer[-1]
# 取最后overlap个动作作为条件
prev_actions = prev_chunk[-self.overlap:]
# 生成新块
action_chunk = self._predict_chunk(
obs, command,
prev_actions=prev_actions
)
with self.lock:
self.action_buffer.append(action_chunk)
self.new_chunk_event.set()
def _predict_chunk(self, obs, command, prev_actions=None):
"""
预测一个动作块(Flow Matching推理)
"""
# 将观察编码为特征
visual_feat = self.model.encode_vision(obs['image'])
state_feat = self.model.encode_state(obs['state'])
# 融合特征
fused_feat = self.model.fuse_features(visual_feat, state_feat)
# Flow Matching去噪
if prev_actions is not None:
# Inpainting模式:用已知动作作为条件
noise = torch.randn(
self.chunk_size,
self.model.action_dim,
device=self.device
)
actions = self._flow_matching_denoise(
noise, fused_feat, command,
context_actions=prev_actions
)
else:
# 正常模式:从纯噪声开始
noise = torch.randn(
self.chunk_size,
self.model.action_dim,
device=self.device
)
actions = self._flow_matching_denoise(
noise, fused_feat, command
)
return actions
def _flow_matching_denoise(self, noise, feat, command, context_actions=None):
"""
Flow Matching 去噪过程
"""
T = 1.0 # 起始时间
dt = 0.1 # 时间步长
z = noise
while T > 0:
# 预测向量场
if context_actions is not None and T < 0.3:
# 接近已知区域,使用插值
vec_field = self.model.predict_vector_field(
z, feat, command, T,
context=context_actions
)
else:
vec_field = self.model.predict_vector_field(z, feat, command, T)
# Euler更新
z = z - dt * vec_field
T -= dt
return z
def execute_loop(self, obs_queue, action_executor):
"""
执行主循环
"""
pending_actions = []
while not self.stop_flag.is_set():
# 检查缓冲区
with self.lock:
while len(self.action_buffer) > 0 and len(pending_actions) == 0:
chunk = self.action_buffer.popleft()
# 第一个块完整使用,后续块跳过前overlap个
skip = self.overlap if len(pending_actions) > 0 else 0
pending_actions.extend(chunk[skip:].tolist())
# 执行动作
if len(pending_actions) > 0:
action = pending_actions.pop(0)
action_executor.execute(action)
obs_queue.put(action_executor.get_observation())
self.new_chunk_event.set()
else:
time.sleep(0.001) # 避免CPU busy wait
def run(self, obs_queue, action_executor, command):
"""
启动RTC流水线
"""
# 启动推理线程
self.infer_thread = threading.Thread(
target=self.inference_thread,
args=(obs_queue, command)
)
self.infer_thread.start()
# 主执行循环
self.execute_loop(obs_queue, action_executor)六、与GR00T N1的技术对比
GR00T N1是NVIDIA于2025年3月发布的人形机器人基础模型,两者有相似的目标但架构设计上有显著差异。
6.1 架构对比
| 维度 | Ψ₀ | GR00T N1 |
|---|---|---|
| 基础架构 | VLM + MM-DiT | 双系统(System 1 + System 2) |
| VLM规模 | 2.5B | 未公开 |
| 动作专家 | 700M Flow Matching | 扩散模型 |
| 动作表示 | 连续值(Flow Matching) | 连续值(扩散) |
| 数据策略 | 800h人类视频 + 30h机器人 | 大量机器人数据 |
| 泛化来源 | 人类视频多样性 | 机器人数据规模 |
6.2 设计哲学差异
┌─────────────────────────────────────────────────────────────────┐
│ 设计哲学对比 │
├────────────────────────────┬────────────────────────────────────┤
│ Ψ₀ │ GR00T N1 │
├────────────────────────────┼────────────────────────────────────┤
│ │ │
│ 人类视频 ──▶ 语义理解 │ 机器人数据 ──▶ 动作模式 │
│ │ │ │ │
│ ▼ │ ▼ │
│ 机器人数据 ──▶ 动作映射 │ 规模 + 泛化 │
│ │ │
│ "正确的数据 > 数据量" │ "数据为王" │
│ │ │
│ 优点: 数据成本低 │ 优点: 直接针对机器人优化 │
│ 优点: 泛化能力强 │ 缺点: 数据采集成本高 │
│ 缺点: 需要领域适配 │ 缺点: 依赖大规模数据采集 │
│ │ │
└────────────────────────────┴────────────────────────────────────┘
6.3 技术路线对比
Ψ₀的技术路线:
- 数据来源:优先使用容易获取的人类视频
- 训练策略:三阶段渐进式,从通用到专用
- 泛化方式:通过人类视频的多样性实现跨场景泛化
GR00T N1的技术路线:
- 数据来源:大量真实的机器人轨迹数据
- 训练策略:统一的大规模预训练
- 泛化方式:通过数据规模和多样性实现泛化
6.4 互补性分析
两者代表了两种不同的范式:
| 方面 | Ψ₀ | GR00T N1 |
|---|---|---|
| 数据效率 | ⭐⭐⭐⭐⭐ 高 | ⭐⭐⭐ 中 |
| 直接部署 | ⭐⭐⭐ 中(需适配) | ⭐⭐⭐⭐⭐ 高 |
| 跨具身迁移 | ⭐⭐⭐⭐⭐ 强 | ⭐⭐⭐ 中 |
| 学术贡献 | ⭐⭐⭐⭐⭐ 完整开源 | ⭐⭐ 部分开源 |
七、数据效率分析
7.1 数据量对比
Ψ₀最引人注目的特点是其极高的数据效率:
| 模型 | 数据量 | 核心策略 |
|---|---|---|
| Ψ₀ | ~830小时 | 800h人类视频 + 30h机器人 |
| GR00T N1 | 数万小时(估算) | 大量机器人数据 |
| π0 | 数千小时 | 多种机器人数据混合 |
| OpenVLA | ~100万条轨迹 | 大规模机器人遥操作 |
7.2 为什么Ψ₀能如此高效?
1. 数据来源优化
数据价值密度比较:
1小时人类视频 ──▶ 包含 ~3600秒 × 多种场景 × 多种任务
1小时机器人数据 ──▶ 仅包含特定机器人、特定任务的固定轨迹
价值密度比:人类视频 ≈ 10-50倍于同质机器人数据
2. 跨具身学习的杠杆效应
人类视频中的知识具有天然的泛化性:
- 视觉模式识别:任何场景
- 动作意图理解:任何任务
- 物理规律隐含:重力、摩擦、碰撞
这些知识可以直接迁移到人形机器人上。
3. 三阶段训练的价值
Stage 1: 学习"做什么"(语义)
Stage 2: 学习"怎么做"(动作映射)
Stage 3: 学习"做好"(任务优化)
每一阶段只使用必要的数据,避免信息浪费
7.3 效率提升的量化分析
假设任务性能与数据量的关系为对数关系:
其中:
- :任务性能
- :数据量
- :任务相关常数
则:
| 数据量 | Ψ₀风格策略性能 | 传统策略性能 |
|---|---|---|
| 100h | 80% | 60% |
| 500h | 90% | 75% |
| 1000h | 95% | 82% |
| 10000h | 100% | 95% |
关键发现:在相同数据量下,Ψ₀的数据策略可以实现接近10%的性能提升。
八、完整PyTorch实现框架
8.1 模型定义
import torch
import torch.nn as nn
from torch.nn import TransformerEncoder, TransformerEncoderLayer
import math
class Psi0Model(nn.Module):
"""
Ψ₀: VLM + MM-DiT 人形机器人基础模型
"""
def __init__(
self,
# VLM 配置
vision_hidden_size=1024,
lang_hidden_size=4096,
vision_patch_size=14,
num_vision_tokens=1024,
# MM-DiT 配置
mmdit_hidden_size=1024,
mmdit_num_layers=7,
mmdit_num_heads=16,
# 动作配置
action_dim=38, # 人形机器人自由度
chunk_size=8, # 动作块大小
# Flow Matching 配置
num_denoise_steps=10,
):
super().__init__()
# 1. 视觉编码器
self.vision_encoder = VisionEncoder(
hidden_size=vision_hidden_size,
patch_size=vision_patch_size,
)
# 2. 状态编码器(机器人关节状态)
self.state_encoder = StateEncoder(
input_dim=action_dim,
hidden_size=vision_hidden_size,
)
# 3. 语言编码器
self.lang_encoder = LangEncoder(
hidden_size=lang_hidden_size,
)
# 4. 模态融合层
self.modality_fusion = ModalityFusion(
vision_size=vision_hidden_size,
lang_size=lang_hidden_size,
output_size=mmdit_hidden_size,
)
# 5. MM-DiT 动作专家
self.mmdit = MMDitActionExpert(
hidden_size=mmdit_hidden_size,
num_layers=mmdit_num_layers,
num_heads=mmdit_num_heads,
action_dim=action_dim,
)
# 6. Flow Matching 参数
self.num_denoise_steps = num_denoise_steps
self.chunk_size = chunk_size
self.action_dim = action_dim
def encode_observations(self, images, states):
"""
编码多模态观察
"""
# 视觉特征
visual_feat = self.vision_encoder(images)
# 状态特征
state_feat = self.state_encoder(states)
# 融合视觉和状态
fused = torch.cat([visual_feat, state_feat], dim=1)
return fused
def encode_language(self, input_ids, attention_mask):
"""
编码语言指令
"""
lang_feat = self.lang_encoder(input_ids, attention_mask)
return lang_feat
@torch.no_grad()
def generate_actions(
self,
images,
states,
input_ids,
attention_mask,
num_steps=None,
):
"""
使用Flow Matching生成动作
"""
num_steps = num_steps or self.num_denoise_steps
# 编码观察和语言
obs_feat = self.encode_observations(images, states)
lang_feat = self.encode_language(input_ids, attention_mask)
# 合并为条件
condition = torch.cat([obs_feat, lang_feat], dim=1)
# 从纯噪声开始
batch_size = images.shape[0]
action_chunk = torch.randn(
batch_size,
self.chunk_size,
self.action_dim,
device=images.device,
dtype=images.dtype,
)
# Flow Matching 去噪
dt = 1.0 / num_steps
t = 1.0
while t > 0:
# 预测向量场
vec_field = self.mmdit(action_chunk, condition, t)
# Euler更新
action_chunk = action_chunk - dt * vec_field
t -= dt
return action_chunk
def forward(self, images, states, input_ids, attention_mask, target_actions):
"""
训练时的前向传播
"""
# 编码观察和语言
obs_feat = self.encode_observations(images, states)
lang_feat = self.encode_language(input_ids, attention_mask)
condition = torch.cat([obs_feat, lang_feat], dim=1)
# Flow Matching 训练目标
batch_size = images.shape[0]
T = torch.rand(batch_size, device=images.device)
# 采样插值时间点
t_expanded = T.view(batch_size, 1, 1)
noise = torch.randn_like(target_actions)
interpolated = t_expanded * target_actions + (1 - t_expanded) * noise
# 预测向量场
pred_vec_field = self.mmdit(interpolated, condition, T)
# 真实向量场
true_vec_field = target_actions - noise
# MSE损失
loss = F.mse_loss(pred_vec_field, true_vec_field)
return loss
class VisionEncoder(nn.Module):
"""视觉编码器(简化版ViT)"""
def __init__(self, hidden_size=1024, patch_size=14):
super().__init__()
self.proj = nn.Conv2d(3, hidden_size, kernel_size=patch_size, stride=patch_size)
self.pos_embed = nn.Parameter(torch.randn(1, 1024, hidden_size))
def forward(self, x):
# x: [B, 3, H, W]
x = self.proj(x) # [B, hidden, H', W']
B, C, H, W = x.shape
x = x.flatten(2).transpose(1, 2) # [B, H'*W', C]
x = x + self.pos_embed[:, :x.shape[1]]
return x
class StateEncoder(nn.Module):
"""机器人状态编码器"""
def __init__(self, input_dim=38, hidden_size=1024):
super().__init__()
self.encoder = nn.Sequential(
nn.Linear(input_dim, hidden_size // 4),
nn.GELU(),
nn.Linear(hidden_size // 4, hidden_size),
)
def forward(self, x):
return self.encoder(x).unsqueeze(1)
class MMDitActionExpert(nn.Module):
"""
MM-DiT 动作专家
使用交叉注意力融合VLM特征与隐变量
"""
def __init__(self, hidden_size=1024, num_layers=7, num_heads=16, action_dim=38):
super().__init__()
# 输入投影
self.action_proj = nn.Linear(action_dim, hidden_size)
self.time_embed = nn.Sequential(
nn.Linear(1, hidden_size),
nn.SiLU(),
nn.Linear(hidden_size, hidden_size),
)
# 交叉注意力层
self.cross_attention_layers = nn.ModuleList([
CrossAttentionBlock(hidden_size, num_heads)
for _ in range(num_layers)
])
# 自注意力层(可选,用于动作序列建模)
self.self_attention_layers = nn.ModuleList([
SelfAttentionBlock(hidden_size, num_heads)
for _ in range(num_layers)
])
# 输出投影
self.out_proj = nn.Linear(hidden_size, action_dim)
# LayerNorm
self.norm1 = nn.LayerNorm(hidden_size)
self.norm2 = nn.LayerNorm(hidden_size)
def forward(self, action_seq, condition, t):
"""
action_seq: [B, chunk_size, action_dim]
condition: [B, seq_len, hidden_size] (VLM特征)
t: [B] (时间步,0-1)
"""
B = action_seq.shape[0]
# 投影动作序列
x = self.action_proj(action_seq)
# 时间嵌入
t_emb = self.time_embed(t.unsqueeze(-1)) # [B, hidden]
t_emb = t_emb.unsqueeze(1) # [B, 1, hidden]
x = x + t_emb
# 交替使用交叉注意力和自注意力
for i in range(len(self.cross_attention_layers)):
# 交叉注意力:融合VLM条件
x = self.norm1(x)
x = x + self.cross_attention_layers[i](x, condition)
# 自注意力:建模动作序列
x = self.norm2(x)
x = x + self.self_attention_layers[i](x)
# 输出动作
out = self.out_proj(x)
return out
class CrossAttentionBlock(nn.Module):
"""交叉注意力块"""
def __init__(self, d_model, num_heads):
super().__init__()
self.attn = nn.MultiheadAttention(d_model, num_heads, batch_first=True)
self.norm = nn.LayerNorm(d_model)
def forward(self, x, context):
# x: query, context: key, value
attn_out, _ = self.attn(x, context, context)
return self.norm(attn_out)
class SelfAttentionBlock(nn.Module):
"""自注意力块"""
def __init__(self, d_model, num_heads):
super().__init__()
self.attn = nn.MultiheadAttention(d_model, num_heads, batch_first=True)
self.norm = nn.LayerNorm(d_model)
def forward(self, x):
attn_out, _ = self.attn(x, x, x)
return self.norm(attn_out)8.2 训练循环
def train_psi0(
model: Psi0Model,
train_loader,
optimizer,
device,
num_epochs=100,
log_every=100,
):
"""
Ψ₀训练循环
"""
model.train()
for epoch in range(num_epochs):
total_loss = 0
for batch_idx, batch in enumerate(train_loader):
images = batch['images'].to(device)
states = batch['states'].to(device)
input_ids = batch['input_ids'].to(device)
attention_mask = batch['attention_mask'].to(device)
target_actions = batch['actions'].to(device)
# 前向传播
optimizer.zero_grad()
loss = model(
images, states,
input_ids, attention_mask,
target_actions
)
# 反向传播
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()
total_loss += loss.item()
if batch_idx % log_every == 0:
print(f"Epoch {epoch} | Batch {batch_idx} | Loss: {loss.item():.4f}")
avg_loss = total_loss / len(train_loader)
print(f"Epoch {epoch} Average Loss: {avg_loss:.4f}")九、实验结果
9.1 基线对比
Ψ₀在多个基准测试上展现出色的性能:
| 任务 | Ψ₀ | GR00T N1 | π0 |
|---|---|---|---|
| 物体抓取 | 92% | 90% | 88% |
| 抽屉操作 | 87% | 85% | 82% |
| 移动导航 | 95% | 93% | 90% |
| 全身协调 | 89% | 88% | 85% |
9.2 泛化能力
Ψ₀展现出优秀的跨场景泛化能力:
- 未见过的场景:在新环境中保持80%以上的成功率
- 新物体:对未训练过物体的泛化达75%
- 新指令:理解并执行训练集外语言指令
十、总结与展望
10.1 主要贡献
- 数据策略创新:证明正确的数据选择比单纯追求数据量更重要
- 三阶段训练范式:为通用人形机器人控制提供了可复用的训练框架
- MM-DiT架构:高效融合视觉-语言表示与动作生成
- RTC推理机制:实现低延迟、流畅的人形机器人控制
10.2 局限性
- Stage 2需要少量高质量机器人数据
- 对于极端精细操作任务可能需要额外微调
- 目前主要针对特定人形机器人平台
10.3 未来方向
- 扩展到更多人形机器人形态
- 结合强化学习进行在线适应
- 探索视频预训练的更大规模数据
参考资料
Footnotes
-
Wei, S., Jing, H., Li, B., et al. (2026). Ψ₀: An Open Foundation Model Towards Universal Humanoid Loco-Manipulation. arXiv:2603.12263. USC Physical Superintelligence (PSI) Lab. ↩
-
Ψ₀ Project Page. https://psi-lab.ai/Psi0 ↩