【pi05_fast_tokenizer】将连续动作变成离散的token

从连续轨迹到动作 Token:读懂 π0.5 中的 FAST Tokenizer

FAST 的全称是 Frequency-space Action Sequence Tokenization 。

目的:把一段连续的机器人动作轨迹压缩成离散 token,使视觉-语言模型能够像预测文字一样预测动作。

为什么要变成离散 token? 因为VLM就是prefix token 预测下一句话,前人有很多相关经验。所以把动作输出VLA变成类似预测文字一样预测动作能更快,准确输出。

1. FAST 要解决什么问题?

VLA(Vision-Language-Action)模型接收图像和语言指令,并输出机器人动作。为了复用大语言模型成熟的"预测下一个 token"训练范式,一种自然做法是把连续动作离散化。

早期方法通常逐时刻、逐维度分桶。例如,长度为 H H H、动作维数为 D D D 的动作块

A = a 1 , a 2 , ... , a H , a t ∈ R D A = a_1,a_2,\\ldots,a_H, \qquad a_t\in\mathbb{R}^D A=a1,a2,...,aH,at∈RD

会被转换成 H × D H\times D H×D 个 token。若双臂机器人有 14 个动作维度,以 50 Hz 预测未来 1 秒,模型一次就要自回归预测

50 × 14 = 700 50\times 14=700 50×14=700

个动作 token。

这不只是"序列太长"的问题。机器人轨迹通常很平滑,控制频率越高,相邻动作越相似。于是模型只要复制上一个 token,往往就能得到很低的 next-token loss。换句话说,每个新 token 所携带的边际信息量越来越小:

  • 训练信号弱,收敛慢;
  • 模型容易学成"重复上一动作",而不是理解完整轨迹;
  • token 数随控制频率线性增长,训练和自回归推理都很昂贵;
  • 高速、灵巧操作尤其难学。

FAST 论文中的实验很直观:同样是 1 秒动作,逐时刻分桶在 BridgeV2(7 维、5 Hz)需要 35 个 token,在 14 维、50 Hz 的衬衫折叠任务中则需要 700 个;FAST 分别只需约 20 和 53 个,后者压缩了约 13.2 倍。

因此,FAST 的核心目标不是单纯把连续数值"变成整数",而是:

把高频轨迹中大量重复、低信息的时域采样,变成更短、信息密度更高的频域 token 序列。

2. FAST 如何解决?

FAST 把动作序列当作多维时间信号,流水线可以概括为:

text 复制代码
动作块
  -> 分位数归一化
  -> 逐动作维度做 DCT (类似傅里叶变换,核心)
  -> 缩放并取整
  -> 按频率优先展平
  -> BPE 压缩
  -> 动作 token

2.1 分位数归一化

对每个动作维度,使用训练集的第 1 和第 99 百分位数,将数值大致映射到 − 1 , 1 -1,1 −1,1,并裁剪超出范围的值:

a ~ = 2 ⋅ clip ⁡ ( a , q 0.01 , q 0.99 ) − q 0.01 q 0.99 − q 0.01 − 1 \tilde a = 2\cdot \frac{\operatorname{clip}(a,q_{0.01},q_{0.99})-q_{0.01}} {q_{0.99}-q_{0.01}}-1 a~=2⋅q0.99−q0.01clip(a,q0.01,q0.99)−q0.01−1

相比使用最小值和最大值,分位数对偶发异常值更稳健;统一尺度也方便混合不同机器人、不同控制空间的数据。

2.2 用 DCT 从时域转到频域

FAST 对每个动作维度沿时间轴做离散余弦变换(DCT):

C k , d = DCT ⁡ ( A ~ : , d ) C_{k,d}=\operatorname{DCT}(\tilde A_{:,d}) Ck,d=DCT(A~:,d)

低频系数描述轨迹的整体位置和缓慢变化,高频系数描述快速抖动或突变。真实机器人动作通常是平滑的,因此能量集中在少量低频系数中,许多高频系数接近零。

这里的思想类似 JPEG:不要逐点记录一个平滑信号,而是记录"它由哪些频率成分组成"。

2.3 缩放、取整,让系数变稀疏

对 DCT 系数乘以尺度 γ \gamma γ 后取整:

C ˉ k , d = round ⁡ ( γ C k , d ) \bar C_{k,d}=\operatorname{round}(\gamma C_{k,d}) Cˉk,d=round(γCk,d)

较小的系数变成 0,矩阵因而非常稀疏。 γ \gamma γ 控制重建精度与压缩率的权衡:

  • γ \gamma γ 较大:保留更多细节,误差更小,但 token 更多;
  • γ \gamma γ 较小:压缩更强,但会丢失更多动作细节。

FAST 论文的单数据集实验使用 γ = 10 \gamma=10 γ=10、BPE 词表大小 1024。它们是论文设置,不是所有机器人都必须照搬的常数。

需要注意:DCT 可以逆变换,BPE 也可以无损解码,但取整会产生量化误差,所以完整 FAST 流程是有损压缩。

2.4 频率优先展平

量化矩阵的形状是 H × D H\times D H×D。FAST 不按"先放完关节 1 的所有频率"排列,而是按频率优先:

text 复制代码
[所有维度的 0 频系数,
 所有维度的 1 频系数,
 所有维度的 2 频系数, ...]

这样,自回归模型首先预测决定轨迹整体形状的低频信息,再补充高频细节。论文发现这种顺序能让策略 rollout 更稳定。

2.5 用 BPE 合并常见模式(相邻token合并)

展平后的整数序列仍包含大量 0 和重复局部模式。FAST 再训练一个 BPE(Byte-Pair Encoding)词表,反复把常见的相邻符号组合成一个新 token。

BPE 在这里不理解词义,只负责压缩。例如,训练数据中如果 [0, 0] 和 [12, 0, 0] 经常出现,它们可以被合并成单个词表项。最终得到长度可变、词表大小固定的动作 token 序列,可以直接并入 VLM 的离散词表。

FAST 的 DCT 部分不需要学习;需要从数据中学习的只有 BPE 词表。FAST+ 则是在约 100 万段、每段 1 秒的跨机器人动作块上训练出的通用词表,可直接用于多种机器人和控制频率。

eg:我->10, 们->20 ,我们要两个token表示,但是实际时候我 们,通常一起出现,所以直接合并为 我们->23

DCT 系数的选择与噪声对 FAST 的影响

详细见:Ilia 的 π0.5 视频

用两个一维动作序列直观展示了 DCT 的作用:一条平滑的 30 点轨迹只用大约 6 个低频分量,就能恢复整体形状;保留约 20 个分量时,重建结果与使用全部 30 个分量已经很难用肉眼区分。可是,当轨迹中加入逐时刻振荡后,高频系数不再接近零,必须保留接近全部分量才能精确重建。

加入噪声时:

这个对比揭示了 FAST 能否有效压缩动作的关键:轨迹的信息是否集中在少量低频 DCT 系数中。

1. 不同 DCT 系数分别表达什么?

对于长度为 H H H 的单维动作序列 x 0 , ... , x H − 1 x_0,\ldots,x_{H-1} x0,...,xH−1,DCT 将它表示为一组不同频率的余弦基:

x n = ∑ k = 0 H − 1 α k X k cos ⁡ π H ( n + 1 2 ) k x_n=\sum_{k=0}^{H-1}\alpha_k X_k \cos\left\\frac{\\pi}{H}\\left(n+\\frac12\\right)k\\right xn=k=0∑H−1αkXkcosHπ(n+21)k

其中 X k X_k Xk 是第 k k k 个 DCT 系数。 k k k 越大,对应的时间变化越快:

保留的系数 能表达的动作信息 重建结果
仅 X 0 X_0 X0 动作块的平均值,也称 DC 分量 一条常数轨迹
少量低频系数 整体方向、幅度和缓慢转弯 平滑,但细节不足
更多中频系数 加减速、局部弯曲和纠偏 更贴近原轨迹
高频系数 尖锐变化、接触冲击、快速振动,也可能是噪声 细节更多,但可能重现抖动
全部系数 原始离散序列的全部信息 未量化时可精确重建

如果只保留前 K K K 个系数,重建为

x ^ n ( K ) = ∑ k = 0 K − 1 α k X k cos ⁡ π H ( n + 1 2 ) k . \hat x_n^{(K)}=\sum_{k=0}^{K-1}\alpha_k X_k \cos\left\\frac{\\pi}{H}\\left(n+\\frac12\\right)k\\right. x^n(K)=k=0∑K−1αkXkcosHπ(n+21)k.

随着 K K K 增大,重建误差通常下降,但轨迹会经历"常数 → 大致趋势 → 局部变化 → 完整细节"的过程。这与渐进式 JPEG 先出现轮廓、后出现纹理的现象相似。

需要注意,FAST 并没有直接规定固定保留前 K K K 个系数。它对全部系数进行缩放和取整:

X ˉ k = round ⁡ ( γ X k ) . \bar X_k=\operatorname{round}(\gamma X_k). Xˉk=round(γXk).

因此,满足

∣ X k ∣ < 1 2 γ |X_k|<\frac{1}{2\gamma} ∣Xk∣<2γ1

的系数通常会量化为 0。平滑轨迹的高频系数往往很小,于是效果看起来像"自动丢弃高频",但实际保留多少系数由轨迹本身和量化尺度 γ \gamma γ 共同决定,而不是一个固定的 K K K。

2. 保留太少或太多系数会怎样?

较强压缩 ⟷ 更短、更平滑,但细节更少 \text{较强压缩} \quad\longleftrightarrow\quad \text{更短、更平滑,但细节更少} 较强压缩⟷更短、更平滑,但细节更少

较弱压缩 ⟷ 更精确、token 更多,也更容易保留噪声 \text{较弱压缩} \quad\longleftrightarrow\quad \text{更精确、token 更多,也更容易保留噪声} 较弱压缩⟷更精确、token 更多,也更容易保留噪声

总结:FAST 对平滑动作具有很高的压缩效率,但如果有高频的噪声会让压缩效率大打折扣。
(傅里叶变换去噪声原理相同)

2.6 如何还原动作?

解码按相反方向执行:

text 复制代码
动作 token
  -> BPE 解码为整数序列
  -> 还原频率系数矩阵
  -> 除以 gamma
  -> 逆 DCT
  -> 反归一化
  -> 连续动作块

3. π0.5 中是如何使用 FAST 的?

理解 π0.5 的关键,是不要把"训练表示"和"最终控制输出"混为一谈。π0.5 采用两阶段训练,把 FAST 和 flow matching 的长处组合起来。

3.1 预训练:用 FAST 学动作语言

π0.5 从 PaliGemma VLM 初始化。在预训练阶段,机器人动作块先经 FAST 编成离散 token,模型和预测文字一样,通过交叉熵学习 next-token prediction:

L FAST = − ∑ i log ⁡ p θ ( z i ∣ z < i , o , ℓ ) \mathcal{L}{\text{FAST}}= -\sum_i \log p\theta(z_i\mid z_{<i},o,\ell) LFAST=−i∑logpθ(zi∣z<i,o,ℓ)

其中 o o o 是图像和本体状态, ℓ \ell ℓ 是语言指令, z i z_i zi 是 FAST 动作 token。图像、文本、本体状态和动作由同一个 Transformer 上下文联系起来。

这样做有三个直接收益:

  1. 机器人数据、视觉问答、目标定位等任务都可放进统一的离散 token 训练框架;
  2. FAST 压缩后的动作序列更短、信息密度更高,适合大规模预训练;
  3. 离散动作训练有助于模型保持较好的语言理解和指令遵循能力。

论文中这一阶段训练 280k 步。各数据集动作先按每维的 1%/99% 分位数归一化到 − 1 , 1 -1,1 −1,1;不同机器人的动作维数不一致时,会补零到统一维度。

3.2 后训练:增加连续动作专家

离散动作适合训练,却不适合实时控制:自回归解码必须一个 token 接一个 token 地生成。为此,π0.5 在后训练阶段加入一个约 300M 参数的 action expert,用 flow matching 直接生成连续动作块。

此时模型联合优化两类目标:

L = L token + α L flow \mathcal{L}= \mathcal{L}{\text{token}} +\alpha\mathcal{L}{\text{flow}} L=Ltoken+αLflow

  • L token \mathcal{L}_{\text{token}} Ltoken 包含文本以及 FAST 动作 token 的交叉熵(预训练loss);
  • L flow \mathcal{L}_{\text{flow}} Lflow 训练动作专家预测连续动作的向量场;
  • 论文后训练 80k 步,取 α = 10 \alpha=10 α=10。

两种动作表示之间通过 attention mask 隔离,避免相互泄漏答案:FAST token 可以看图像、语言和本体状态,并因果地看此前的 FAST token;动作专家可以看公共前缀以及自己的 noisy action token,但不能看 FAST 动作 token。

3.3 推理:FAST 不在实时动作生成主路径上

π0.5 推理分为两层:

  1. VLM 自回归生成高层子任务,例如把"收拾厨房"分解为"拿起盘子";
  2. 动作专家以该子任务、视觉和状态为条件,经过 10 个去噪/积分步骤生成连续动作块。

论文中的 action horizon 为 50(从 t t t 到 t + 49 t+49 t+49),机器人以 50 Hz 执行控制。也就是说,FAST 主要在预训练及联合训练中提供高质量的离散学习信号;部署时的低层连续动作主要由 flow-matching action expert 产生。将 π0.5 简化成"用 FAST 解码动作的自回归 VLA"是不准确的。

4. 一个直观例子

假设单个关节未来 8 个时刻的归一化动作是:

text 复制代码
[0.00, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70]

这是一条平滑上升的轨迹。逐时刻分桶需要 8 个离散值。DCT 后,大部分信息会集中在表示平均值和整体斜率的前几个低频系数,高频项接近 0。示意结果如下:

text 复制代码
DCT:       [0.99, -0.64, 0.00, -0.07, 0.00, -0.02, 0.00, -0.01]
乘以 10:  [9.90, -6.40, 0.00, -0.70, 0.00, -0.20, 0.00, -0.10]
取整:      [10,   -6,    0,   -1,    0,    0,    0,    0]

数值会随 DCT 归一化约定而变化,这里只展示结构。可以看到,8 个时域采样变成了"少数显著系数 + 大量 0"。多关节情况下按低频优先交错展平,再由 BPE 把常见的零串及系数组合合并成更少的 token。

例如,量化后的序列是:

text 复制代码
[10, -6, 0, -1, 0, 0, 0, 0]

若 BPE 词表中已有如下合并:

text 复制代码
Z2 = [0, 0]
Z4 = [Z2, Z2]

那么它可以编码成类似:

text 复制代码
[10, -6, 0, -1, Z4]

真实 FAST 的整数还会先映射到基础符号,BPE 合并规则也由整个训练集统计得到;上例只是解释压缩机制。

5. 用官方 FAST+ 接口编码动作

FAST 论文发布了 Hugging Face AutoProcessor 形式的通用 FAST+ tokenizer。下面是论文给出的最小用法:

python 复制代码
import numpy as np
from transformers import AutoProcessor

tokenizer = AutoProcessor.from_pretrained(
    "physical-intelligence/fast",
    trust_remote_code=True,
)

# 推荐输入约 1 秒动作,并事先按训练集分位数归一化到 [-1, 1]。
# 例:50 Hz、7 个动作维度,形状为 [time, action_dim]。
action_chunk = np.random.uniform(-1, 1, size=(50, 7)).astype(np.float32)
tokens = tokenizer(action_chunk)

print(tokens)

如果要针对自己的机器人数据训练 BPE 词表,论文接口为:

python 复制代码
new_tokenizer = tokenizer.fit(action_dataset)

其中 action_dataset 应包含许多形状为 [H, D] 的动作块。实践中还需注意:

  • 用训练集统计每个动作维度的 1%/99% 分位数,并在训练、验证和部署时复用同一组统计量;
  • 以约 1 秒为动作块通常能获得较好的压缩效果;
  • 必须记录动作维度含义、单位、顺序以及 absolute/delta action 定义;
  • 用"解码后的轨迹误差"选择 γ \gamma γ,不能只追求 token 越少越好;
  • trust_remote_code=True 会执行模型仓库中的代码,应固定版本并审查来源后再用于生产环境。

6. 用伪代码串起完整过程

下面的代码省略了 BPE 的基础符号映射等工程细节,但准确表达了算法骨架:

python 复制代码
import numpy as np
from scipy.fft import dct, idct

def fast_pre_bpe_encode(actions, q01, q99, gamma=10):
    """actions: [H, D],返回频率优先的量化整数序列。"""
    normalized = 2 * (actions - q01) / (q99 - q01) - 1
    normalized = np.clip(normalized, -1, 1)

    # 沿时间轴对每个动作维度做 DCT。
    coeff = dct(normalized, axis=0, norm="ortho")       # [H, D]
    quantized = np.rint(gamma * coeff).astype(np.int32) # [H, D]

    # NumPy 的 C-order 正好按每个频率依次放入所有动作维度。
    return quantized.reshape(-1)

def fast_pre_bpe_decode(integer_sequence, horizon, action_dim,
                        q01, q99, gamma=10):
    quantized = integer_sequence.reshape(horizon, action_dim)
    coeff = quantized.astype(np.float32) / gamma
    normalized = idct(coeff, axis=0, norm="ortho")
    return (normalized + 1) * 0.5 * (q99 - q01) + q01

# 真实 FAST:
# integer_sequence -> BPE.encode(...) -> action tokens
# action tokens -> BPE.decode(...) -> integer_sequence -> 上面的逆过程

这段代码适合帮助理解或检查数据管线,不应被当作官方 FAST tokenizer 的等价替代:正式实现还包括整数到 BPE 符号的编码、词表训练、padding、批处理和元数据管理。

7. 总结

FAST 抓住了高频机器人动作的本质:采样点很多,不等于有效信息很多。逐时刻分桶把平滑轨迹变成长而重复的序列;FAST 则通过 DCT 把信息集中到频域、通过量化制造稀疏性,再用 BPE 压缩重复模式,从而得到短而高信息密度的动作 token。

π0.5 对 FAST 的使用体现了一个很实用的系统设计:

  • 用 FAST 离散 token 获得稳定、统一、可扩展的预训练;
  • 用 flow matching 动作专家获得细粒度、低延迟的连续控制;
  • 用联合损失和 attention mask 让两种动作表示共享视觉语言能力,同时避免标签泄漏。

一句话概括:FAST 让 π0.5 更容易"学会动作",flow matching 让它更快地"做出动作"。

参考资料

  1. Pertsch et al., FAST: Efficient Action Tokenization for Vision-Language-Action Models, 2025.
  2. Physical Intelligence et al., π0.5: a Vision-Language-Action Model with Open-World Generalization, 2025.
  3. Physical Intelligence, FAST+ tokenizer on Hugging Face.
  4. Physical Intelligence, OpenPI repository.
相关推荐
feasibility.2 天前
把城市压缩成 2067 个盒子:CosFly 无人机跟踪数据管线论文解剖
人工智能·大模型·嵌入式·无人机·vla
技术狂人1683 天前
OmniBot-System多任务机器人:任务调度器路由设计与Jetson Thor端侧部署实践
具身智能·vla·任务调度器·jetson thor·多任务机器人
一直在努力的小宁5 天前
【阅读笔记】具身操作的数采方案概览
后端·json·restful·具身智能·vla·vlm
做cv的小昊6 天前
【World Model】π0.5:a Vision-Language-Action Model with Open-World Generalization
人工智能·算法·机器学习·大模型·多模态·vla·世界模型
风合星语13 天前
2026 具身智能技术实战(一):VLA 到底怎么控制机器人?——用 LeRobot 跑通 SmolVLA 推理
pytorch·机器人·具身智能·vla·lerobot·smolvla
深蓝学院13 天前
六大具身路线详解:模块化、技能编排、IL、RL、VLA、世界模型,到底在“吵”什么。。。
机器人·具身智能·vla·世界模型
一颗小树x15 天前
《VLA 系列》五篇 VLA 轻量化与实时化 | 开源
机器人·实时·轻量化·vla
音视频牛哥15 天前
从 LLM、VLA、LLA、SLIM 到实时音视频感知底座:具身智能真正需要的不只是大模型
人工智能·llm·机器人视觉·slam·vla·多模态感知·机器人音视频
Robot_Nav19 天前
前沿 | VLA 演进:从动作 Token 到分层具身智能体
具身智能·vla·vlm