paper-notes / VLA / π₀ · 2024

π₀: A Vision-Language-Action Flow Model for General Robot Control

Physical Intelligence · Black, Brown, Driess, Finn, Levine et al. · 2024-10 · v4 2026-01

这篇笔记怎么读

π₀ 是第一个把 flow matching 用进机器人动作生成的 VLA 模型, 也是把"LLM 范式(大 pre-train + 小 post-train)"搬到真实机器人上的代表作。 按章节顺序读:先讲为什么要这么做(§1-§2),再讲 基础组件(§3),然后是完整架构(§4), 接着用两节分别走完推理(§5)和训练(§6)流程, 最后是数据(§7)和实验(§8)。

§1 为什么要做 π₀

这一节解决什么

机器人学习的现状是:每个任务/机器人单独采一批数据、训一个小模型—— 能做的事窄、换个新场景就垮。π₀ 想要的是把 NLP/CV 已经跑通的 "大规模预训练 + 少量下游微调"范式移植到机器人上——做出 一个通用机器人基础模型(robot foundation model), 靠语言指令就能驱动它做从叠衣服到打包盒子的多步复杂操作。

读完本节你会知道:π₀ 想解决的三个现实难题(数据、通用性、灵巧度), 以及它的三条技术路线(VLM 初始化、flow matching、action expert) 各自在对应哪个问题。

展开原文 · 核心主张

"Robot learning holds tremendous promise to unlock the full potential of flexible, general, and dexterous robot systems... bringing robot learning to the level of generality required for effective real-world systems faces major obstacles in terms of data, generalization, and robustness."

— Abstract, p.1

1.1 三个现实难题

数据机器人数据远比互联网文本/图像贵——没有"抓取数据的互联网"可用。必须从多种机器人、多种任务里出大语料库。
通用性一个模型要能跨任务(叠衣服 / 收拾桌子 / 装盒子)、跨机器人本体(单臂 / 双臂 / 移动底盘)、跨场景(新物体、新环境)。
灵巧度上面两条还要在复杂灵巧操作上成立——像叠 T 恤、整理零碎物品这种需要精确连续控制的任务,不能只做"推积木"。

1.2 对应的三条技术选择

VLM INIT · PaliGemma 3B
从预训练 VLM 出发
用互联网规模 VLM 的权重当 backbone,直接继承语义理解(认得"衬衫"、"毛巾"、"抽屉")。 不新鲜,但是和下面 flow matching 一起走是头一份
FLOW MATCHING · action head
连续动作生成
抛弃 autoregressive 的动作离散化(精度差、易抖动),用 流匹配 在连续空间建模—— 第一个把 flow matching 用进机器人的工作。
ACTION EXPERT · 300M
动作专用子网络
把处理动作/状态 token 的权重从 VLM 里切出来独立训—— 语义表征和连续控制差异大,共享一套权重效率不高。
ACTION CHUNKING · H=50
一次生成 50 步
一次预测未来 50 个时间步(1 秒)的动作序列,而不是每步单独生成—— 避免机械臂抖动。这是从 ACT/RT-2 一路沿用下来的技巧。
对照 VLA

π₀ 的名字里 V-L-A 三个字母各自对应一个模态处理: V = SigLIP 图像编码 · L = Gemma 文本编码 · A = Action Expert + flow matching 头。 前两者合起来就是 PaliGemma(SigLIP + Gemma)这个现成的 VLM。

1.3 Fig 1 全景:这个系统长什么样

Figure 1: Generalist robot policy overview
Fig 1 · p.1 Our generalist robot policy uses a pre-trained VLM backbone, as well as a diverse cross-embodiment dataset with a variety of dexterous manipulation tasks. The model is adapted to robot control by adding a separate action expert that produces continuous actions via flow matching. π₀ 的全景:左边是数据(π 自采 + OXE 公开),中间是模型(pre-trained VLM + action expert), 右边是三种下游使用模式(零样本 / 针对难任务微调 / 针对新任务微调)。
🧠 理解检查
下列哪一项是 π₀ 真正的技术首创?
本节小结

π₀ 要做的是机器人版的基础模型:数据上靠多本体拼,架构上靠 VLM + action expert 分工,生成上靠 flow matching 保精度。下一节先把 "大 pre-train + 小 post-train"这套范式说清楚——它才是 π₀ 整体 pipeline 的骨架,§3 之后的各个模块都是在填这个骨架。

§2 两阶段范式 · 大 pre-train + 小 post-train

承上 / 这一节解决什么

§1 说 π₀ 的目标是做通用机器人基础模型——但"通用"到底怎么实现? 答案不是"训一个万能的模型一把梭",而是照搬 LLM 的路数: 先在大而杂的数据(7 种机器人 · 68 任务 · 1 万小时)上预训练, 让模型学到"通用的低层技能先验";再在小而精的高质量演示数据上 post-training,把这些先验调成"某个具体任务的解"。

本节把为什么要分两阶段讲清楚——这会直接决定 §4 架构里 "为什么要拆出 action expert"和 §8 实验里"为什么 scratch 打不过 pre-trained"。

展开原文 · 两阶段范式

"Our framework consists of a pre-training stage followed by a post-training stage... The purpose of the pre-training phase is to train a base model that exhibits broad capabilities and generalization, but is not necessarily specialized for high performance on any one task. This base model can follow language commands and perform a variety of tasks at rudimentary proficiency."

— §III Overview, p.3

2.1 两阶段在干什么

① Pre-training · 大杂烩
② Post-training · 小精
③ 为什么非要分两步
数据规模OXE + DROID + Bridge v2 + π 自采 → ~10,000 小时,903M 时间步
机器人形态7 种:UR5e / Bimanual UR5e / Franka / Bimanual Trossen / Bimanual ARX / Mobile Trossen / Mobile Fibocom
任务数68 个 π 自采任务 + OXE 里的子集
目标"广而浅"——能听懂指令、能大致做各种基础操作,但任何单个任务都不顶尖
对应 NLP类比 GPT 的 next-token 预训练:见过什么都懂一点,但没专精
数据规模1–10 小时 演示足矣(部分任务 5 小时就能达 SOTA)
数据质量专人精采、无错误演示、单任务连续成功
目标"窄而深"——把某个具体任务(叠衣服 / 收桌子 / 装盒子)做到高成功率 + 强鲁棒
对应 NLP类比 SFT/RLHF:用小批高质量数据把基础模型调成"听指令"的有用模型
核心理由

如果你只用小而精的数据从零训,模型会过拟合到具体任务, 换场景就垮——这就是传统 behavior cloning 的老问题。如果你只用大而杂的数据, 模型学到的是"平均质量的动作分布"——对任何具体任务都不够精细。 两阶段合起来:pre-train 给你"通用技能先验 + 对物体/语言的广义理解", post-train 把这些先验聚焦到具体任务。§8 实验 A/D 专门验证了这点—— scratch 版本在困难任务上掉分明显。

2.2 一张图看两阶段怎么拼

flowchart LR
    subgraph PRE["① Pre-training(大杂烩 · 10000h)"]
      OXE[Open X-Embodiment
公开数据] PI[π 自采数据
7 机器人 · 68 任务] DROID[DROID / Bridge v2] end PRE --> BASE[π₀ Base Model
3.3B 参数
泛化 · 听指令 · 基础操作] BASE --> POST1 BASE --> POST2 BASE --> POST3 subgraph POST["② Post-training(小而精 · 1-10h/任务)"] POST1[叠衬衫 fine-tune] POST2[清空烘干机 fine-tune] POST3[收拾餐桌 fine-tune] end POST1 --> OUT1[叠衬衫 专家策略] POST2 --> OUT2[清空烘干机 专家策略] POST3 --> OUT3[收拾餐桌 专家策略]
对照 LLM

π₀ BaseGPT-base(预训练后啥都能扯但不听指令)
π₀ task-specificChatGPT(SFT 后听话、专精)
这个对照不是我瞎编——论文里原话讲 "analogous to the recipe used for large language models"。

展开原文 · LLM 范式搬运

"We present a prototype model and learning framework, which we call π₀, that illustrates how each of these bottlenecks could be tackled. ... Our framework broadly resembles the training procedures employed for large language models, which typically consist of pre-training a base model on very large datasets ranged from the web, followed by a post-training recipe that uses higher-quality curated data to induce a desired behavior."

— §I Introduction + §VII Discussion, p.2 / p.12
🧠 理解检查
关于 π₀ 的 post-training 数据规模,下列哪一项描述对?
本节小结 / 启下

搞清楚"大 pre-train + 小 post-train"是外壳后,下一节 §3 打开内核—— 在具体每一步里,模型到底在生成什么?答案是"未来 50 步的动作块",用 flow matching 生成。 这两个词各有一节讲:§3.1 action chunking,§3.2 flow matching。

§3 基础组件 · action chunking 与 flow matching

承上 / 这一节解决什么

§2 把整体范式讲清楚了,但没说"一次前向在输出什么"。π₀ 每次推理输出的不是 1 个动作, 而是未来 H=50 步的动作块(action chunk),而且这 50 步是 用 flow matching 一次性生成(不是 autoregressive 逐步吐)。 这俩组合决定了后面 §4 架构的样子和 §5 推理的 10 步循环,不先搞清它俩别往下走。

3.1 Action Chunking · 为什么一次要生成 50 步

一句话

如果每次推理只输出下 1 个动作,两次推理之间的微小预测差异会让 机械臂产生肉眼可见的抖动(jitter)。一次生成 50 步(= 1 秒,执行频率 50 Hz), 让这段时间内动作之间自然连贯,抖动消失。

H = 50一次生成的动作个数(chunk size / action horizon)
50 Hz执行频率——50 个动作刚好对应 1 秒 的机器人运动
action_dim每步动作维度(随机器人不同:单臂 ~7,双臂 ~14,移动底盘 ~18;统一 pad 到 18 维)
chunk 形状A = [a_t, a_{t+1}, ..., a_{t+49}],shape [50, 18]
类比

像打字预测——你不是一个字母一个字母想,而是脑子里先浮出一整个短语再连贯打出来。 单动作预测 = 每个字母都重新决策 → 卡顿;chunk 预测 = 一整个短语出炉 → 流畅。

代价

一次生成 50 步 → 延迟高(要跑完整个 flow matching 10 步去噪才拿到动作)。 工程上用 receding horizon control 缓解:执行前 N 步(比如前 10 步) 就回到观测阶段重新推理,不用等 50 步执行完——这个后面 §5.4 讲。

3.2 Flow Matching · 从噪声到干净动作的直线路径

最少的 flow matching 知识

Flow matching 是 2023 年 Lipman 等人提出的生成模型范式,直觉非常简单: 在"纯噪声"和"真实样本"之间画一条直线,让模型去学习这条线上每点的"速度向量"。 推理时就沿着预测的速度场一路走,直到走到干净样本。 对比扩散模型(diffusion)的"曲线路径 + 随机游走",flow matching 的直线更省、更稳。

3.2.1 核心三公式

① 线性插值(训练时构造 noisy action)
A_τ = τ · A + (1 − τ) · ε       其中 ε ~ N(0, I),  τ ∈ [0, 1]

τ=0 → 纯噪声;τ=1 → 干净动作;中间值 = 线性混合。 注意 π₀ 的约定和部分 flow matching 原论文方向相反(有些论文 τ=0 是干净), 但只要内部一致就没问题。

② 目标向量场(ground truth 的"速度")
u(A_τ | A) = ε − A

怎么推出来的?对 A_τ = τA + (1−τ)ε 求导得 dA_τ/dτ = A − ε。 论文把方向反过来写 u = ε − A(从"干净指向噪声"反向,作为"去噪方向")—— 这个方向在整条直线上是常数,这正是 flow matching 比 diffusion 漂亮的地方: 目标平稳,模型好学。

③ 训练 loss(MSE 回归速度)
L(θ) = E[ ‖ v_θ(A_τ, o_t) − u(A_τ | A) ‖² ]
      = E[ ‖ v_θ(A_τ, o_t) − (ε − A) ‖² ]

让模型输出的向量场 v_θ(网络输出)尽可能贴近目标 u=ε−A(已知答案)。 期望 E 来自三处随机:数据中采 (o_t, A)、随机采 τ、随机采 ε注意:π₀ 采样 τ 用的是偏小的 β 分布 (不是均匀分布),让模型多学"早期去噪"——早期噪声多,信号弱,更难学。

3.2.2 flow matching 是怎么跑的(训练 vs 推理)

flowchart TB
    subgraph TRAIN["训练 · 一次前向"]
      T1["采真实动作 A (ground truth)"] --> T2["采 τ~β, ε~N(0,I)"]
      T2 --> T3["构造 A_τ = τA + (1-τ)ε"]
      T3 --> T4["网络输出 v_θ(A_τ, o_t)"]
      T4 --> T5["loss = ‖v_θ − (ε−A)‖²"]
    end
    subgraph INFER["推理 · 10 步 Euler 积分"]
      I1["初始化 Â_0 ~ N(0,I), τ=0"] --> I2
      I2["网络输出 v_θ(Â_k, τ_k)"] --> I3
      I3["Â_{k+1} = Â_k + δ · v_θ (δ=0.1)"] --> I4
      I4["τ_{k+1} = τ_k + 0.1"] --> I5{τ=1.0 ?}
      I5 -->|否| I2
      I5 -->|是| I6["输出 Â_10 = 干净动作 chunk"]
    end
        
训练 vs 推理的差别

训练时一次前向就够(随机采一个 τ,算一次 loss 更新)。 推理时没有 ground truth,只能从纯噪声出发一步一步走 10 次—— 每次都是"用当前状态预测速度 → 欧拉积分前进一小步",直到 τ=1.0。 这 10 次前向构成了 §5 里的外层循环;每次前向内部又有 18 层 transformer, 构成内层循环——后面细讲。

🧠 理解检查
flow matching 的目标向量场 u(A_τ|A) 随 τ 变化吗?为什么这点很重要?
本节小结 / 启下

到这里你已经知道:一次要生成 [50, action_dim] 的动作块(§3.1), 生成方式是 flow matching 的 10 步 Euler 积分(§3.2)。 但 v_θ 到底长什么样?它是 PaliGemma 还是独立网络? 和图像、语言、机器人状态怎么融合?——这是 §4 架构要回答的。

§4 架构 · PaliGemma + Action Expert

承上 / 这一节解决什么

§3 告诉你"输入 o_t + 噪声动作 A_τ,输出速度 v_θ"—— 但中间那个 v_θ 的网络体到底长什么样?本节拆开来看。核心答案是 两套权重拼接的 transformer:PaliGemma(3B,处理图像+语言)+ Action Expert(300M,处理机器人状态和动作 token),两边通过块因果注意力交流。 搞懂这个结构,§5 推理流和 §6 训练流才有落点。

4.0 Fig 3 总览

Figure 3: π₀ architecture overview
Fig 3 · p.3 Overview of our framework. We start with a pre-training mixture... The VLM backbone weights are initialized from PaliGemma, providing learned representations from large-scale Internet pre-training. 左:pre-training 数据(π 自采 + Internet + OXE)。中:π₀ 模型——PaliGemma VLM backbone (SigLIP 400M + Gemma 2.6B,蓝色部分)+ Action Expert(300M,橙色部分)。 右:输出连续动作给各种机器人。
展开原文 · 架构核心

"The π₀ model... consists primarily of a language model transformer backbone. Following the standard late fusion VLM recipe, image and text inputs are encoded... We further augment this backbone with robotics-specific inputs and outputs — namely, proprioceptive state and robot actions. π₀ uses conditional flow matching to model the continuous distribution of actions."

— §IV, p.3

4.1 Block-wise Causal Attention · 块因果注意力

一句话

整个 token 序列拆成三个块① 图像+文本(PaliGemma 的 prefix)→ ② 机器人状态 q_t(action expert 的 1 个 token)→ ③ 噪声动作 A_τ(50 个 token)。 注意力规则:块内双向 + 块间只能向前看。这让 pre-trained VLM 部分 不被后来的机器人 token 污染,推理时可以把 ①②的 KV 算一次缓存起来重复用(10 步去噪只有 ③ 变)。

flowchart LR
    B1["① 图像+文本 tokens
(PaliGemma 权重)
块内双向"] B2["② 状态 q_t · 1 token
(action expert 权重)
能看 ①"] B3["③ 噪声动作 A_τ · 50 tokens
(action expert 权重)
能看 ①②,块内双向"] B1 --> B2 B2 --> B3 B1 --> B3
为什么这样分块

① 作为 prefix:观测一步变,前两个块计算一次就够了——10 步去噪可以复用 KV cache,只重新算 50 个 action token,节省 ~90% FLOPs。
② 隔出状态块:状态每步看一次即可,不需要被 50 个 action token 重复 attend,和 ③ 分开建模更干净。
③ 块内双向:action chunk 内的 50 步是"一体成形",互相都要 attend,不像 LLM 那样严格 autoregressive。

展开原文 · attention mask

"We adopt a blockwise causal attention mask with three blocks: image and language prefix (block 1), robot state (block 2), and noisy action chunk (block 3). Tokens in a given block can attend to tokens in the same block and all preceding blocks."

— §IV + Appendix B, p.3

4.2 为什么要独立的 Action Expert

这节回答一个工程直觉问题

既然已经有了 3B 的 PaliGemma,为什么不直接让它处理机器人 token?非要额外塞一个 300M 的 action expert?——答案是模态冲突 + 推理速度

模态冲突VLM 权重是"图像-文本离散 token 分布"的最优解;机器人状态/动作是连续信号,分布规律和语义 token 完全不同。共享一套权重会互相拖累。
推理速度推理时要跑 10 次前向(flow matching 10 步)。前两个块(图像+语言+状态)KV cache 一次即可复用;但 action token 每步都要重算——让这部分走 300M 小网络而不是 3B 大网络,10 步总 FLOPs 几乎不增。
保护预训练机器人数据量远小于 VLM 预训练数据,让机器人梯度全灌进 3B VLM 会导致灾难性遗忘语义知识。Expert 独立,机器人梯度只改 300M。
类比 MoE

可以理解为"模态 MoE":token 根据类型(文本图像 vs 状态动作)被路由到不同专家的权重。 只是这里路由规则是静态的——token 是什么类型从一开始就定了,不是学出来的 gate。

🧠 理解检查
推理时为什么可以把图像+文本的 KV cache 起来重复用 10 次?
本节小结 / 启下

到这你会画 π₀ 的数据流图了:图像+语言进 PaliGemma、状态+动作进 Action Expert、 块因果 mask 把它们串起来、最后 Action Expert 最后一层输出 50 个速度向量。 下一节 §5 把这套架构在推理时的完整 10 步循环跑一遍——把 "我给个指令 → 机械臂动起来" 里每个 tensor 的 shape 都讲清。

§5 推理 · 一次完整的 10 步去噪

承上 / 这一节解决什么

§4 给了架构静态图,本节动起来:从"看到一帧图 + 听到指令""输出 50 个动作执行",中间每个 tensor 怎么流。重点是搞清 什么算 1 次、什么算 10 次、什么可以 KV-cache—— 这是理解 π₀ 为什么能跑到实时频率的关键。

5.0 输入与输出

输入 · 观测 o_t ① 图像 {I¹_t, I²_t, I³_t}(最多 3 路多视角) · ② 语言指令 (例如 "fold the shirt") · ③ 机器人本体状态 q_t(关节角等连续向量)
输出 · 动作 chunk A_t = [a_t, a_{t+1}, ..., a_{t+H-1}]H = 50
flowchart TB
    O[["Stage 1 · 观测编码(只 1 次,KV-cache)
图像 → SigLIP → image tokens
指令 → Gemma → language tokens
→ PaliGemma 跑完所有层 → 保存 KV"]] S[["Stage 2 · State token(只 1 次)
q_t → state_proj(Linear) → 1 个 state token
(走 action expert 权重)"]] INIT["Stage 3 初始化
A^τ_0 ~ N(0, I), shape [50, action_dim]
τ_0 = 0"] LOOP["Stage 3 去噪循环 · for k = 0..9
(a) 构造 action tokens
(b) action expert forward
(c) Euler 积分 A^τ_{k+1} = A^τ_k + 0.1 · v_θ
(d) τ_{k+1} = τ_k + 0.1"] DONE{"τ = 1.0 ?"} EXEC[["Stage 4 · 执行
全部 50 步 or receding horizon"]] O --> S --> INIT --> LOOP --> DONE DONE -->|否| LOOP DONE -->|是| EXEC

5.1 Stage 1 · 观测编码(只做 1 次,可缓存)

  1. 图像编码:每张图过 SigLIP ViT → 一组 image tokens(每 token 768 维),3 路拼接成 [N_img, d]
  2. 语言编码 经 Gemma tokenizer → text embedding → [N_text, d]
  3. VLM 前向:把 [image tokens | language tokens] 送进 PaliGemma backbone(2.6B),跑完所有层,保存每一层的 K、V 缓存
工程重点 · KV cache 的省法

这部分是整个推理里最贵的一步——完整走一遍 3B 的 VLM——但只跑 1 次。 之后的 10 步去噪循环里,观测不变,图像/语言部分的 K、V 直接复用,不再重算。 这是 §4.1 块因果 mask 设计的直接收益,也是 π₀ 能做到推理实时的最关键优化。

5.2 Stage 2 · Robot State token 准备(只做 1 次)

q_t ∈ R^{action_dim} # pad 过的关节角
state_token = state_proj(q_t) # Linear, shape [1, d_model]

注意:state token 走的是 action expert 的权重(和后面的 action token 共享), 不走 VLM。它的 KV 也会被缓存,之后 10 步循环只读不写。

5.3 Stage 3 · Flow Matching 去噪循环(10 次迭代)

① 初始化

A^τ_0 ~ N(0, I) # shape [50, action_dim]
τ_0 = 0

A^τ_0 相当于 flow matching 里的 x_0(纯噪声端); 真实干净动作 A_clean(训练时的 ground truth)对应 x_1。 下面循环要做的事就是 "从 A^τ_0 逐渐走向 A_clean",沿着 flow matching 的那条直线路径,每步走 δ = 0.1。

② for k = 0, 1, ..., 9

(a) Action token 构造
  • A^τ_k(noisy action)过 action_in_proj(Linear)→ 50 个初步 token
  • τ_k(标量 0.0 / 0.1 / ... / 0.9,flow timestep)经正弦位置编码 → 1 个 time embedding
  • 每个 action token 与 time embedding concat → 过 action_time_mlp(Linear → Swish → Linear)→ 50 个最终 action tokens
(b) Action expert forward · 一趟 transformer

输入序列:[Image/Lang tokens (KV cache) | state token | 50 个 action tokens]

每一层应用块因果 attention mask

块 ↓ 看 → Image/Lang State Action
Image/Lang✅ 双向
State
Action✅ 双向
  • Image/Lang 部分不重算,直接用 Stage 1 的 KV cache
  • State + action tokens 走 action expert(300M)每一层

取最后一层的 50 个 action token 输出 → 过 action_out_proj → 得到向量场:

v_θ(A^τ_k, τ_k, o_t) # shape [50, action_dim]
(c) Euler 积分更新(等价于"更新 action token")
A^τ_{k+1} = A^τ_k + δ · v_θ(A^τ_k, τ_k, o_t) # δ = 0.1

新值 = 旧值 + 步长 × 当前位置的"速度"。这就是用 flow matching 预测的向量场 沿直线走一小步。

(d) 推进时间
τ_{k+1} = τ_k + 0.1
为什么写成 (t → t−1) 而不是 (τ → τ+δ)

有些图里标注是 t → t−1——这是从扩散模型借来的写法, t = T 纯噪声、t = 0 干净样本,每次去噪一步 t 减 1。 在 π₀ 约定下 τ 是相反方向(0 噪声 / 1 干净),但含义一致:每轮都更像真实 action clean

5.4 Stage 4 · 输出动作

循环结束后 A^τ_{10} = A^1.0 即为干净动作 chunk A_clean

  • 全部执行:把 50 步动作发给机器人控制器(50 Hz → 1 秒)
  • 部分执行 + 重规划:执行前 k 步(如前 10 步)后,回到 Stage 1 用新观测重新推理——即 滚动时域控制。让策略对突发扰动(物体滑落、机械臂偏移)反应更快,同时保留 chunk 预测的平滑性。
两层嵌套循环 · 总计算量

外层:去噪 10 步(for k)。内层:每步 Action Expert 18 层 transformer。 总计算量 ≈ 10 × 18 = 180 层 forward 量级,但其中图像+语言部分只在 Stage 1 算了 1 次—— 比"全网络每步都重算"便宜 10 倍。

本节小结 / 启下

推理路径讲完了。训练时没有 10 步循环——训练是"一次前向一次反传"。 下一节把训练的完整四步写清,重点在 loss 的物理含义和为什么 u = ε − A 是对的监督目标。

§6 训练 · Flow Matching Loss 的完整四步

承上 / 这一节解决什么

§5 的推理有 10 步循环。训练正好相反:一条真实动作 chunk + 一次前向 + 一次反传就够了。 但"一次前向"里有不少细节决定成败——怎么采 τ 和 ε、怎么构造 noisy action、 监督目标到底是什么ε − A 这个方向从哪来)。 本节按 4 步走完。

6.1 Step 1 · 取真实动作 chunk

从机器人 demonstration 数据集 D 里采一段真实动作序列:

A = [a_t, a_{t+1}, ..., a_{t+49}] # shape [50, action_dim]

这就是 flow matching 里的 x₁(目标分布的样本)。同一个样本还包含 o_t(当时的观测:图像 + 语言 + 状态)。

6.2 Step 2 · 采样 τ、ε,构造 noisy action

随机采两个东西:

  • 噪声 ε ~ N(0, I),shape 和 A 一样 [50, action_dim]
  • 时间 τ ∈ [0, 1](论文里用偏小的 shifted β 分布,让模型多学早期去噪)

然后线性插值得到 noisy action:

A^τ = τ · A + (1 − τ) · ε
一个常见误读

A^τ 不是"第 τ 个时间步的动作"(不是 action sequence 里的某一步), 而是整段 50 步动作的"第 τ 个清洁度版本"—— 可以理解为 A 被部分加噪后的样子。

直观理解这条插值:

τ = 0A^τ = ε → 纯噪声(起点)
τ = 0.5一半噪声一半真实动作
τ = 1A^τ = A → 干净动作(终点)

这里 τ 约定是 τ=1 干净、τ=0 噪声,和推理时方向一致—— 训练和推理 convention 对齐,模型学到的向量场直接拿来用。

6.3 Step 3 · 把 A^τ 当成 action tokens 输入 transformer

整个前向流程和推理时完全一样

  1. A^τaction_in_proj → 拼上 τ 的 sinusoidal embedding → 过 action_time_mlp → 50 个 action tokens
  2. 拼成完整序列 [image | lang | state | action],过整个网络(VLM + action expert)
  3. 取最后一层 50 个 action token 输出 → 过 action_out_proj → 得到向量场预测:
    v_θ(A^τ, o_t) # shape [50, action_dim]
训练 vs 推理的关键差别 · KV cache

训练时不需要 KV cache——每个 batch 样本的观测都是新的, 不存在"反复算同一个 o_t" 的场景,cache 没用武之地。 推理时才靠 KV cache 让 10 次循环里观测只算 1 次。

6.4 Step 4 · Loss · 强制 v_θ 去预测目标向量场

① 目标向量场

u(A^τ | A) = ε − A

这是 flow matching 的核心定义。怎么推出来的:

  • 已知 A^τ = τ · A + (1 − τ) · ε
  • 对 τ 求导:dA^τ / dτ = A − ε
  • 论文把方向反过来写,定义 u = ε − A(去噪方向:从噪声"指向"干净动作的反方向,或等价地"从干净指向噪声"当作梯度方向)
为什么这点漂亮

u = ε − A从噪声端 ε 走到干净端 A 这条直线路径上的速度—— 而这条速度对所有 τ 都是常数(直线路径嘛)。 对比扩散模型的曲线 + 随时间变化的目标,flow matching 目标平稳、模型好学—— 这正是它比 diffusion 漂亮的地方。

② Loss

L(θ) = E_{p(A|o), q(A^τ|A)} [ ‖ v_θ(A^τ, o_t) − u(A^τ | A) ‖² ]
     = E [ ‖ v_θ(A^τ, o_t) − (ε − A) ‖² ]

翻译成人话:

loss 在说什么

让模型预测的向量场 v_θ模型输出)尽可能接近 目标向量场 u = ε − A已知答案),用 MSE 衡量差距。

期望 E 来自三个随机性上取平均:

  1. p(A_t | o_t):从数据集里随机采一条 (观测, 动作) pair
  2. q(A^τ_t | A_t):随机采 τ 和 ε,构造 A^τ
  3. (隐含)batch 内多个样本一起算,反传后更新 θ

6.5 为什么 τ 用偏小的 β 分布

细节 but 关键

均匀采 τ 的问题:τ 接近 1 时(样本快接近干净动作)任务简单—— 大部分网络容量被"浪费"在容易的样本上。π₀ 用偏小的 β 分布让 τ 更多落在 [0, 0.5], 强迫模型多练"从很噪声的起点往回推"的困难情形——这直接对应推理时前几步(τ=0.0, 0.1, 0.2 ...) 最不稳定的阶段。

展开原文 · τ 采样

"We sample the flow matching timestep τ from a shifted beta distribution that emphasizes lower timesteps (noisier). See Appendix B for more details."

— §IV, p.4
🧠 理解检查
为什么 π₀ 训练时 τ 不用均匀分布,而用偏小的 β 分布?

6.6 训练伪代码(一次 batch update)

# 从数据集抽一个样本
(o_t, q_t, A) ← sample from D # A = 真实 50 步动作 chunk

# 采 τ(偏小 β 分布)
τ ← Beta(1.5, 1.0).sample().clip(0, 1 − 0.001)

# 采 ε(各维独立标准高斯)
ε ← N(0, I) # shape [50, action_dim]

# 构造 noisy action
A^τ ← τ · A + (1 − τ) · ε # shape [50, action_dim]

# 前向(和推理完全一样的网络路径,但没有 KV cache)
v_θ ← π₀(o_t, q_t, A^τ, τ) # shape [50, action_dim]

# Loss 和反传
L ← ‖v_θ − (ε − A)‖²
L.backward(); opt.step()
本节小结 / 启下

训练的数学部分到此为止——4 步讲清了 loss 的来源和物理含义。 但论文真正的"秘密"在数据上—— 1 万小时怎么拼出来的、7 种机器人怎么共享一套动作空间?§7 讲数据和本体。

§7 数据与机器人

承上 / 这一节解决什么

π₀ 的泛化能力来自数据多样性。本节两图:Fig 4 看数据由谁组成, Fig 5 看 7 种机器人本体长什么样、动作空间有多大。

7.1 Fig 4 · 数据组成

Figure 4: Dataset overview pie chart
Fig 4 · p.5 Overview of our dataset: pre-training mixture consists of a subset of OXE and π self-collected. π₀ 的 pre-training 数据组成:π 自采占最大比例,OXE/Bridge v2/DROID 补充广度。 单臂 797M + 双臂 106M 步,共 ~903M。

7.2 Fig 5 · 7 种机器人本体

Figure 5: 7 robot platforms
Fig 5 · p.6 The robots used in our experiments. These include single and dual-arm manipulations with 6-DoF and 7-DoF arms, as well as holonomic and nonholonomic mobile manipulators. 7 种本体,动作维度从 7 到 18。π₀ 把所有动作统一 pad 到 18 维, 对应 "取最大公约数" 的多本体策略。
工程 trick · 动作维度统一

不同机器人动作空间维度不同,但 action expert 只有一个输出头——解法是 统一 pad 到 18 维(最大者)。训练时根据机器人类型加 mask, 忽略不存在的维度。这比"每机器人一个头"简单得多,也是 π₀ 能共享一套权重的关键前提。

§8 实验 · 四套评估

承上 / 这一节解决什么

§1–§7 告诉你 π₀ "应该能做什么"。本节用实验验证。作者设计了四套互补评估A 对比 baseline,B 语言遵循能力,C 新任务微调效率, D 5-20 分钟级的复杂多阶段任务。每套都挑出了 π₀ 相对前辈的一个独特优势。

A · 开箱即用对比(Fig 7)

任务5 个:shirt folding / bussing easy / bussing hard / grocery bagging / toast out of toaster
对手OpenVLA(7B VLA,基于 RT-2 系)、Octo(小型 diffusion policy)、π₀-small(π₀ 的无 VLM 版 470M baseline)、π₀-parity(训练步数对齐版)
结论π₀ 全面领先——在 bussing hard / grocery bagging 这类难任务上 baseline 接近全 0,π₀ 保持高成功率。验证 flow matching + VLM 初始化的叠加效果。

B · 语言指令遵循(Fig 8)

评估3 种任务(table setting / grocery bagging / bussing hard)× 3 种指令粒度(flat / human-intermediate / HL-VLM-intermediate)
对照π₀ vs π₀-small
结论π₀ 显著优于 π₀-small,差距主要来自中等粒度指令("pick up the spoon")——VLM pre-training 提供的语义 grounding 正好在这里生效。换成高层指令("set the table")两者都需要外部 HL-VLM 分解。

C · 新任务微调效率

任务pre-training 未见过的 dexterous task(e.g. 放东西进抽屉、换纸巾、stack bowls)
数据量1–5 小时演示
结论π₀ 在 1h 级数据就能上手;scratch / no-pretrain 版本要 5h+ 才接近。pre-training 给的是"通用操作先验"而非"具体任务记忆"——这正是基础模型范式成立的必要条件。

D · 复杂多阶段任务

任务清空洗烘一体机、叠多件衣服、收拾餐桌到洗碗机——单次演示 5–20 分钟级
配合高层 VLM 规划(SayCan 风格)+ π₀ 做底层技能执行
结论π₀ 能在这些时长下保持成功率,是同类 VLA 第一次做到。之前的 RT-2/OpenVLA 停在几秒到分钟级任务。
局限 · 实验里没说的

① 评估主要在 π 自己的机器人上做——跨实验室 zero-shot 迁移没 report; ② 硬件闭源——复现困难(没开源 checkpoint 到 1M+ 步规模); ③ 安全/失败模式没系统性分析(和传统控制论意义上的"可验证"差距还很大)。

🧠 理解检查
四套实验里,哪一套最直接验证"pre-training 本身有价值"?
这一节解决什么

把 π₀ 放进 embodied AI 的地图里——它和 LeCun 的自主智能架构、 和 RT-2 / OpenVLA / Helix 这些兄弟模型到底什么关系?

9.1 对应 LeCun 六模块

Perception↔ PaliGemma · SigLIP 视觉编码 + Gemma 指令理解
World Model缺失——π₀ 是 policy-only,没有预测下一帧观测的模块
Cost隐式在数据里——专家演示的行为分布就是"好"的定义,没有显式 cost
Short-term Memory缺失——每次决策只看当前 1 帧,无历史
Actor↔ Action Expert · 直接输出 50 步动作
Configurator部分存在——语言指令充当任务配置
核心差距

π₀ 是 model-free VLA——不建模世界。这让它数据效率差 (要 1 万小时)、规划能力弱(多步任务靠外部 HL-VLM 分解)。 LeCun 路线(JEPA + MPC)想要的是能在脑内想象未来的模型—— π₀ 没有这块,但胜在工程现在就能跑出来

9.2 和其他 VLA 的比较

RT-2 (2023)VLM + 离散 action token(tokenize 到文本词表)。π₀ 换成 flow matching 的连续 action,精度和平滑度都大提升。
OpenVLA (2024)7B 开源 VLA,依然用离散 action token。π₀ 比它小(3.3B)反而更强——主要得益于 flow matching 和 action expert。
Diffusion Policy (2023)用 diffusion 做动作生成,但没有 VLM 初始化——小模型精细但不泛化。π₀ = Diffusion Policy 思想 + VLM backbone。
Helix / Figure AI类似路线(双塔 VLM + 快慢分层),工程细节不开放,π₀ 是开放的代表作。

9.3 给自己找实习时的 takeaway

启示

① 技术栈:会 PaliGemma / Flow Matching / Block-wise attention 是 VLA 岗位基本面。 ② 工程技巧:multi-embodiment pad、KV cache 跨步复用、receding horizon—— 这些都是面试可以聊的点。 ③ 研究空白:π₀ 缺世界模型/短期记忆/显式 cost——这些恰是下一代模型的 greenfield。 如果你要在硕士阶段做点有辨识度的东西,在这三块做减法实验比盲目 scale 更有价值。

全篇收束

π₀ 不是最"干净"的架构(比起 JEPA 的理论自洽),也不是最大(比起 OpenVLA 7B), 但它是当前最 useable 的 VLA 基础模型——把 LLM 的 pre-train/post-train 范式、VLM 的语义先验、flow matching 的连续动作生成三块拼在一起,跑出了真能叠衣服的机器人。 工程味道浓于理论味道,但这正是 embodied AI 这个阶段最需要的东西。