VLA 中的动作 token 化,讲清楚
解析 vision-language-action 模型如何把连续的机器人动作变成 transformer 能预测的离散 token,以及这一选择为何决定了策略的分辨率上限。
RT-2 让一个语言模型学会了操控机械臂,用的正是它处理文字的那套机制。每一个动作维度,夹爪位置的变化、旋转、以及张开或闭合的指令,都被归一化并切分成 256 个区间(bin)。这些 bin 被映射到模型词表里借用的 256 个 token ID 上。机械臂之所以动起来,是因为 transformer 在预测下一个 token,就和它续写一个句子时一模一样。
这个手法支撑着今天大多数 vision-language-action(VLA)模型。transformer 说的是取自固定词表的离散 token;机器人说的却是连续的数值:关节角度、末端执行器速度、夹爪力,每秒钟到来几十甚至上百次。必须有东西在两者之间做翻译,这个东西就是动作 tokenizer。人们很容易把它当成管道一样的基础设施,其实不然。
tokenizer 决定了它下游一切环节的分辨率上限。它决定了一段演示进入模型、再输出回电机的过程中能保留多少信息,也决定了模型究竟能不能表示某类任务。一套在慢速桌面抓放上运行良好的方案,可能在快速、富接触的操作上悄悄失效。真正有意思的工程问题,在于为什么。
tokenizer 是一份有损契约
撇开各种名号,每一个动作 tokenizer 要回答的都是同样四个问题。连续的数值如何变成离散的符号?多个自由度如何打包在一起?一条以 50 Hz 到来的数据流,如何变成 transformer 能接受的 token 序列?又如何把这一切反解回平滑的运动?
默认答案是均匀分箱(uniform binning)。取每一个动作维度,裁剪到合理范围,再量化成 N 个 bin,常用 256,正好一个 bin 占一个字节。RT-2,以及后来的开源模型 OpenVLA,复用了语言模型自身 token 表里那些极少使用的条目来承载这些 bin,从而无需扩充词表就能微调一个预训练好的 VLM。一个 7-DoF 机械臂的单个时间步会变成 7 个 token,一小段轨迹变成几十个。模型仍用它一贯的下一个 token 交叉熵损失来训练。
这套做法优雅,而且是有意为之的有损。量化会丢掉低于一个 bin 的精度。复用语言 token 意味着动作空间的几何结构,也就是 bin 128 处在 127 和 129 之间这个事实,并没有被编码在模型看得见的任何地方,它只能从数据里重新学出顺序。对于粗糙、慢速的任务,这些都无伤大雅。一旦把控制频率提上去,问题就来了。
tokenizer 是连续物理与离散模型之间的一份有损契约。凡是它在采集环节丢掉的,策略就永远学不会复现。
为什么手一快,分箱就失灵
下面这个失效模式让很多人意外。把一段灵巧操作演示以高频率采样,相邻两帧的动作看起来几乎一模一样,因为在十毫秒里手几乎没动。逐时间步的分箱会把这变成一长串近乎重复的 token。在这种数据上训练的自回归模型会发现最省力的策略:预测下一个 token 等于上一个。每个 token 携带的边际信息极小,损失看着还行,而策略学会的却是原地卡住。
Physical Intelligence 在训练高频策略时正撞上了这堵墙,并用 FAST 这个频域 tokenizer 作答。FAST 不对原始采样分箱,而是取一段动作 chunk,做离散余弦变换(DCT),保留真正携带信号的系数,再对结果做字节对编码(BPE)。一段平滑的 chunk 会被压成一串短而密的 token,冗余被挤了出去。这让一个自回归 VLA,也就是他们的 pi0-FAST 系列,能在普通分箱塞不进去的灵巧数据上完成训练。这里的启示可以推广:正确的 token 不是一个原始采样,而是对一段运动的压缩描述。
另一条路,连续动作头
并非所有 VLA 都对动作做 token 化。第二类做法跳过离散化,直接在 transformer 的输出上接一个连续的生成头。Physical Intelligence 的 pi0 用的是 flow-matching 动作专家;NVIDIA 的 GR00T N1 把一个视觉语言骨干与一个 diffusion-transformer 动作头配在一起;Google DeepMind 的 Gemini Robotics 则跑着一个直接输出连续底层指令的 VLA。这三者里,transformer 都产生一个隐向量,再由一个小头据此采样出一段连续动作。
好处是没有量化误差,且在高控制频率下输出平滑。代价是你放弃了那套干净的、单一词表的自回归损失,而且采样一个 diffusion 或 flow 头是迭代式的,会带来推理时延,你得再想办法把它补回来。这正是当下 VLA 里活生生的设计分岔:要么把运动压成 transformer 直接预测的离散 token,要么保持连续、为一个独立的采样器买单。两条路都用在了严肃的系统里,而这个选择和你的数据的关系,比和你的模型的关系更大。
四种方案对照
把这些选项并排放在一起更容易权衡。下表勾勒出每种表示在什么地方物有所值,又要付出什么。
| 方案 | 运动如何变成输出 | 优势 | 主要代价 |
|---|---|---|---|
| 逐维均匀分箱(RT-2、OpenVLA) | 每个维度量化到约 256 个 bin,映射到复用的语言 token ID | 简单,复用预训练词表与损失 | 量化误差;高控制频率下退化 |
| 频域 token 化(pi0-FAST) | 对一段动作 chunk 做 DCT,再对保留的系数做 BPE | 能在快速、灵巧的数据上自回归训练 | 多一步编码与解码;压缩需调参 |
| 学习式向量量化码本 | 动作片段映射到一个学出来的离散码本条目 | 紧凑、随数据自适应的词表 | 码本坍缩;需要有代表性的数据 |
| 连续 diffusion 或 flow 头(pi0、GR00T N1) | 一个小头从 transformer 隐向量采样出连续动作 chunk | 无量化误差;高频输出平滑 | 迭代式采样;没有单一自回归损失 |
tokenizer 会在哪里漏
有两个实际的坑,决定了上面这一切能否经受住真实机队的考验。第一个是归一化。bin 的边界是根据训练数据的统计量定下的,因此在某台机器人的动作范围上训练出的策略,换到另一台臂展或夹爪行程不同的机器人上,就会悄无声息地失准。像 Open X-Embodiment 这样汇集了众多机器人本体演示的数据集,以及 DROID 这类大型遥操作数据集,其存在的部分意义就是逼着 tokenizer 去跨这些范围泛化,而不是过拟合某一条臂。
第二个是分块(chunking)。一次只预测一步会让误差累积,还会让序列充满那种拖垮分箱的冗余。当下多数系统会一次预测未来的一小段动作,这既削减了累积漂移,也给了 tokenizer 一段值得压缩的片段。像 Hugging Face 的 LeRobot 这类开源工具箱如今已经把这些 tokenizer 和分块动作头直接打包了进来,把过去的一个研究抉择变成了一个配置项。这有利于迭代速度,也略微危险:那些默认值里编码着关于频率和本体的假设,未必和你的机器人相符。
那个被忽略的变量
每当一个新的 VLA 面世,动作 token 化很少成为头条,而它本该被看见。正是在这一层,模型的野心撞上了它数据的分辨率;也正是在这里,一个系统开始有能力去做它此前根本无法表示的事。下次某个实验室报告在灵巧任务上取得跃升时,不妨留意一下:那个新招数往往不是更大的脑子,而是一种更好的、把手做了什么记录下来的方式。