问题 · §1
机器人策略几乎都只看当前一帧
GR00T、π0、π0.5、OpenVLA 这些主流 VLA 只看当前观测,少数看 2–8 帧。语言模型那边,上下文长度早已是一条重要的扩展方向。论文认为,长时程推理可以交给外部记忆(关键帧、语言),但有些能力离不开长的视觉-运动上下文:
- 看一段人类演示视频,然后照着做(一次模仿);
- 从自己这一回合的执行历史里改进(在线改进);
- 多阶段长任务里分清「现在做到哪一步了」。
直接拼历史帧有两个麻烦:模型容易抓住虚假相关(论文里 GR00T 加一帧历史,在 Pup Go Car 上从 57 降到 39.5);Transformer 带 KV cache 推理,计算随历史线性增长,几分钟的 30 Hz 控制根本跑不动。普通 RNN 状态是向量,容量太小。
方法 · 测试时训练的机制 · §2
状态是一个小网络的权重,用梯度下降来写
对 token 序列做 Q、K、V 投影。快权重 W 参数化一个小网络 fW(线性层或 MLP)。每一步先更新:让 fW 把 Kt 映射到 Vt,做一步梯度下降;再应用:用更新后的权重处理 Qt。
投影矩阵 θQ、θK、θV 和快权重初值 W0 是普通参数(慢权重),用外层任务损失训练;W0 要通过「梯度的梯度」来学。学习率 η 也是学出来的(在固定基础学习率 0.1 之上)。
vs. 全注意力
注意力保留所有历史的 K、V,每步都要对它们做一次注意力,计算随历史线性增长。TTT 把历史压进固定大小的权重,每步的计算量不变。
vs. RNN / 线性注意力
LSTM 的状态是一个向量;Gated DeltaNet(论文里的 GDN 基线)的状态是矩阵,但用线性的关联规则更新。TTT 的状态是一个非线性 MLP 的权重,用真正的梯度下降更新,容量和表达力更强。
vs. 「测试时训练」的其他用法
论文特意区分:EVOLVE-VLA、TTT-Parkour、TT-VLA 等工作也叫测试时训练,但它们是在测试任务上微调整个模型(或 LoRA)。RoboTTT 只更新这一小块快权重,而且更新是模型前向的一部分,训练和推理用的是同一套机制。
方法 · 模型结构 · §3.1 · 附录 A.1
注意力管「这一步」,TTT 层管「跨步」
动作头输入一条 T 步的轨迹 [R1, Φ1, q1, Ã1, …, RT, ΦT, qT, ÃT]:Φ 是 VLM 输出的视觉语言 token,q 是本体状态,Ã 是加噪动作块,R 是每步前面加的 N = 16 个可学习寄存器 token。
- 注意力只在一步之内:R、q、Ã 做自注意力,并交叉注意力读这一步的 Φ。
- TTT 层跨时间:每步注意力的输出 [Rt, qt, Ãt] 沿时间拼起来送进 TTT 层。VL token Φ 太多,不直接进 TTT,由 16 个寄存器 token 携带视觉语言信息跨时间传递。
- 门控:每层学一个向量 α ∈ ℝd,初始化为 0.001,输出 O = tanh(α) ⊙ OTTT + Oattn。训练开始时 TTT 几乎不起作用,保住预训练 GR00T 的能力。
- 规模:原 DiT 538M 参数,16 层各加约 10M,共 690M。快模型是带 GeLU 的两层 MLP,用普通梯度下降(不用 Muon 等更复杂的优化器)。位置编码 RoPE,θ = 10000。
方法 · 长序列训练 · §3.2
两个让长序列训得动的技巧
训练样本是一整条轨迹(或其中连续的一段,最长到最大上下文),在序列里一边更新快权重,一边在每一步算 flow matching 损失,再对时间取平均:
序列动作强制:每个动作块单独采噪声水平
如果整条序列共用一个噪声水平 τ(类似全序列扩散),整段要么都很简单(低噪声)、要么都很难(高噪声),训练不稳定。每一步的 τt 独立采样后才稳定,作者说这和 Diffusion Forcing 的发现一致。消融里去掉这一条,Pup Go Car 只剩约 2 分,几乎无法推进任务。
截断反传(TBPTT):显存只看段长
完整 BPTT 要存每一步的激活,显存随序列长度增长。TBPTT 把序列切成段,梯度只在段内流动;但快权重本身跨段继续传递(只是在段边界处切断梯度),所以 TTT 仍覆盖整条序列。W0 只从第一段拿到梯度。
配方(附录 A.2):预训练混合桌面双臂机器人数据和 EgoScale 第一人称人类视频,挑长轨迹;上下文长度逐步加到目标(如 8K),30K 步,16 张 GB200,只训新加的序列层(TTT 或 GDN),GR00T 其余部分冻结。后训练每个任务 1K 上下文、20K 步、8 张 GB200,全部参数微调。AdamW,权重衰减 1e-5;预训练 WSD 调度峰值 2e-5,后训练余弦调度峰值 5e-5。4K 及以下全局 batch 64,以上为 16。
8K 步有多长?和任务时长、训练窗口放在一起看
30 Hz 控制;平均分来自原文 Figure 8(读自矢量图)
方法 · 从上下文里学 · §3.3
快权重和慢权重的更新可以分开
在某些时间步屏蔽 flow matching 损失,这些步就只更新快权重、不提供模仿目标,变成「纯上下文」。论文用这个机制做了两件事:
从视频里一次模仿
Circuit 任务有约 80 种装配配置。训练时把同一配置的一段人类演示视频(机器人不动,人用手装)和一条机器人轨迹拼成一条序列:视频部分只更新快权重,动作损失只在机器人部分上算。所有配置用同一句提示词「assemble circuit」,目标配置只能从视频里看出来。测试时给一段没见过的配置的人类视频,再让机器人装。
DAgger Distillation
DAgger 式数据:机器人执行时出错,人接管纠正。标准 DAgger 只拿人的纠正动作去微调,扔掉机器人的错误动作。DAgger Distillation 两样都用、但分工不同:整条交互历史(含错误动作)都更新快权重,损失只算在人的纠正上。模型学到的是「看到自己这样失败 → 这样纠正」,而不是孤立地模仿纠正动作。作者称之为 Algorithm Distillation 在机器人上的一个实例。
同一条 DAgger 轨迹,三种用法
示意轨迹;分数来自原文 Figure 10(Pup Go Car,读自矢量图)
实验设置 · §4 · 附录 B
三个双臂装配任务,最长 5 分钟
| 任务 | 数据 | 平均时长 | 试验 | 评分细则(附录 B) |
|---|---|---|---|---|
| Pup Go Car | 8 h | 约 2 min | 20 | 累进里程碑 0.05 → 1.0:拿车顶、放上、对准螺丝、拿电钻、拧紧、交接、翻车、装轮、拧紧、交回;轮子最多尝试两次 |
| Circuit | 6 h | 约 1 min | 20 | 每个元件等分(1/2、1/3 或 1/4),有开关或按钮时打开也算一份;装配顺序错了不给分。约 80 种配置,训练 20 种,测试其余 60 种 |
| Gear Bot | 5 h | 约 5 min | 10 | 每次翻底盘、每个齿轮或轮子、装「机器人头」、用遥控器开动各 +0.1,共十项 |
- 平台:YAM 双臂桌面机器人,四个 RealSense D405(俯视、仰视、左右腕),480p;RTX 5090 推理,控制频率 30 Hz。每种方法从记录下来的同一组初始物体摆放开始。
- 基线:GR00T N1.7(单步上下文);GR00T N1.7 Hist.(多一帧历史);GDN:把 RoboTTT 的 TTT 层换成 Gated DeltaNet,位置、门控、参数量都对齐,用同样的预训练。
- 训练预算:所有方法用同样的任务数据后训练;序列模型 1K 上下文,非序列模型训练到相同的计算量。
- 指标:完整成功次数,以及按细则给分的任务完成分(0–1,报告为百分数)。
主结果 · §4 · 原文 Figure 7、Table 1
平均完成分 79,单步 GR00T 42,GDN 56
三个任务的任务完成分
原图没有数值标注,按矢量图柱高读出,取整(Pup Go Car 的 GR00T 57、Hist. 39.5 和三个平均值与正文一致)。悬停看完整成功次数。
数字(完成分读自 Figure 7,成功次数来自 Table 1)
RoboTTT 在每个任务上的完整成功次数都最多:Pup Go Car 9/20,Circuit 13/20,Gear Bot 2/10(其余方法 Gear Bot 都是 0)。论文从回放里总结了三点:
- 跟踪进度:多阶段装配里很多阶段长得很像,基线会做错动作或跳过阶段;快权重保留了历史里的关键特征,能分清现在是哪一阶段。
- 有策略地恢复:Pup Go Car 拧车顶螺丝时电钻没对准,RoboTTT 会抬手、重新对准再试;基线则直接进入下一阶段,好像刚才成功了。
- 更精确:插元件、卡扣这类细活更准,作者归因于长上下文缓解了部分可观测性:物体当前被挡住时,以前看到过它的画面还在。
疑点Pup Go Car 的主结果已经用了 DAgger 数据
Figure 8 的图注写「本图所有评测早于主结果里 Pup Go Car 用的 DAgger 训练」。把 Figure 7 和 Figure 10 对照:主图里 Pup Go Car 的 RoboTTT 89、GDN 57 正好是两者 DAgger Distillation 之后的分数,GR00T 57、Hist. 39.5 是它们标准 DAgger 之后的分数。不用任何 DAgger 数据时,这一项是 RoboTTT 66、GR00T 53、GDN 44、Hist. 39。也就是说,主图 Pup Go Car 上 32 个点的领先里,有一大半来自 DAgger Distillation 这套训练方法(只有序列模型能用),不只是来自长上下文本身。正文主结果段落没有提这一点。
解读「拼历史帧没用」只在一个任务上成立
论文以 Pup Go Car 为例说明直接拼历史帧会引入虚假相关(Hist. 39.5 对 GR00T 57)。但在 Circuit(54 对 23)和 Gear Bot(54 对 47)上,多一帧历史都是有帮助的,平均分 Hist. 49 也高于 GR00T 42。正文的措辞是「不能稳定带来帮助」,这是准确的,但读者容易记成「历史帧有害」。
一次模仿与扰动恢复(Table 2、3)
一次模仿(Circuit,10 次)与外部扰动(Pup Go Car,各 20 次)
一次模仿只和 GDN 比:GR00T 不读历史,GR00T Hist. 只看得到一帧,装不下一段视频。扰动实验里,人在机器人装好车顶或轮子后把它拆掉,策略要回到之前的阶段重装;所有方法都和 30 分钟的扰动数据一起训练。
一次模仿:RoboTTT 完成分 65%、完整成功 6/10;GDN 33%、0/10,常常拿错元件或装错顺序。作者的解读是:循环记忆能把信息存进去,但不太会用;TTT 是在历史上用梯度下降训练出来的一个小网络,查询时能把演示过的配置取出来。扰动:车顶 15/20(GDN 13,GR00T 10,Hist. 3),轮胎 18/20(GDN 同为 18)。
上下文长度扩展 · 原文 Figure 8
预训练上下文越长,闭环分越高
三个任务的平均完成分 vs 预训练上下文长度
读自矢量图的点位。所有点都在 1K 上下文下后训练,且早于 Pup Go Car 的 DAgger 训练。虚线:单步上下文(GR00T)与短上下文(GR00T Hist.)。
点位数字(读自矢量图)
RoboTTT 从 1K 的 43.9 涨到 8K 的 71.5(+63%),比最强的短上下文基线 45.6 高 57%,曲线还没有饱和。GDN 没有这个趋势,8K 时 44.3。作者的解释:TTT 的快权重用梯度下降更新,初值 W0 和更新动态都由外层损失元学习,更长的训练序列意味着更多步更新来塑造它们;GDN 的线性关联状态没有这种元学习。
1K 以下 RoboTTT 不如更长的版本,作者归因于回合比训练窗口长:1K 步约 34 秒,比最短的任务还短,部署时快权重会被更新到训练中没见过的远处,位置编码也会外推到没见过的位置。
疑点「1K 以下仍优于 GDN」和图不完全一致;曲线每点只有一次运行
正文说 1K 以下 RoboTTT「在相同长度下仍优于 GDN」,但 512 步处 GDN 约 40.2、RoboTTT 约 39.3,几乎相同且 GDN 略高;128 → 256 RoboTTT 还略降(30.8 → 28.9)。每个点是一次预训练 + 一次后训练 + 三个任务共 50 次试验,没有误差棒。另外,图中的单步 / 短上下文参考线(37.6 / 45.6)和用 Figure 10 里「DAgger 之前」分数还原出的平均分(约 40.9 / 49.0)对不上,说明是不同批次的评测。整体趋势(1K → 8K 明显上升)是清楚的,细处不宜过度解读。
解读扩展的是预训练长度,后训练一直是 1K
所有模型的任务后训练都只用 1K 上下文,而三个任务分别持续约 1、2、5 分钟(约 1.8K、3.6K、9K 步)。8K 预训练带来的好处,是让快权重的初值和更新规则见过更长的序列,在部署时被一路更新几千步也不跑偏。这和语言模型「先在长序列上预训练,再在短任务上微调」的做法类似。
DAgger Distillation · 原文 Figure 10–11
错误动作当上下文,纠正动作当目标
同一批 100 条 DAgger 轨迹的四种用法(Pup Go Car)
50 条用 RoboTTT 采、50 条用 GR00T 采,合在一起训练所有方法。实心柱读自矢量图;斜线柱、交叉线柱为填充图案,读自渲染图,约 ±1。
标准 DAgger 平均提升 9%(两个序列模型 13%);DAgger Distillation 提升 33%:RoboTTT +36%(66 → 89),GDN +29%(44 → 57)。对 GR00T,把机器人的错误动作也当模仿目标,和只用人的纠正结果一样(都是 57):错误动作作为目标没有价值,作为上下文才有价值。回放显示 DAgger Distillation 的收益大多来自做错之后的恢复。
解读GDN 也能吃到大部分好处
GDN 用 DAgger Distillation 也提升了 29%,说明这套数据用法对任何序列模型策略都适用,不依赖 TTT。RoboTTT 多出的 7 个百分点,可以算作 TTT 机制本身在这里的贡献。标准 DAgger 在 GR00T Hist. 上几乎没用(39 → 40)。
消融 · 原文 Figure 12
非线性快模型和序列动作强制都关键
Pup Go Car 任务完成分
读自矢量图柱长。上三行是消融,下三行是开发过程中逐步加组件。完整 RoboTTT = 加寄存器 token 这一行(未用 DAgger)。
- 去掉序列动作强制:约 2 分,动作不准,任务几乎无法推进。
- 快模型换成线性层:48,比 MLP 版本(66)低 27%,但仍高于同等 token 数的 GR00T(44)。非线性快模型最重要,和视觉、语言里 TTT 的发现一致。
- 逐步加 token:TTT 只处理本体 token 时 45;再让动作 token 也进 TTT,56(+23%,知道自己之前做了什么,更好地把握环境动态);再加 16 个寄存器 token,66(+18%)。
- 寄存器 token 对 GR00T 没用:同样数量的寄存器加到 GR00T 上只有 44,低于不加的 53(Figure 10 里「DAgger 之前」的分数)。说明它们只有配合 TTT 的跨时间建模才有用。
读懂它
这篇真正说明了什么
关键 insight
1. 「记住多少」可以学出来,不必手工指定
该保留多长、哪些历史,事先很难定。RoboTTT 不手工选关键帧或摘要,而是让快权重在部署时自己决定写入什么、覆盖什么。作者的说法是:有了足够有表达力的序列模型,长上下文的用法可以学,而不用手工设计。
2. 状态的更新规则决定了能不能扩展
GDN 和 RoboTTT 状态大小都固定、位置和参数量都对齐,区别只在更新规则(线性关联 vs 梯度下降更新的非线性 MLP)。上下文从 1K 加到 8K,前者不涨、后者涨 63%;一次模仿 0/10 对 6/10。这是全文最干净的一组对照。
3. 失败也是有用的数据,但要当上下文用
DAgger Distillation 和标准 DAgger 用的是同一批数据,差别只在损失掩码。机器人的错误动作当模仿目标毫无帮助,当上下文能带来 20 多个点。这把「评估与反馈」从部署时挪到了训练时:人的纠正就是评价信号,被蒸馏进了快权重的更新方式里。
4. 训练和推理是同一套机制
和 TT-VLA 在部署时临时加一个 RL 更新不同,RoboTTT 的「测试时更新」本身就是模型前向的一部分,训练时就按同样方式在序列上做了无数次,初值和学习率都是为此元学习出来的。所以它不会像 TT-VLA 那样出现「更新太频繁反而掉分」的问题。
容易误解的地方
- 「测试时训练」不等于在测试任务上微调。慢权重在部署时完全冻结,只有每层那个约 10M 参数的快 MLP 在变,而且每个回合都从学到的 W0 重新开始。
- 8K 是预训练长度。任务后训练只有 1K;部署时快权重一路更新到回合结束(最长约 9K 步),没有上限。
- VLM 看不到历史。VLM 每一步只处理当前图像和语言;跨时间的信息全在动作头里,由 16 个寄存器 token 带着视觉语言信息进入 TTT 层。
- 完成分不等于成功率。79 是按细则给分的平均,完整成功次数是 9/20、13/20、2/10。
FAQ
推理时每一步要做一次反向传播吗?很慢吧?
要对快模型(两层 MLP)做一次梯度更新,16 层每层一个。论文的说法是「推理时延不随上下文增长」,因为每步的计算量固定。但它没有给出每步耗时,也没有和 GR00T N1.7 原版比较,只说在 RTX 5090 上以 30 Hz 控制。动作块长度 H 和去噪步数 k 也没有披露,所以每秒实际要跑多少次推理、每次多长都不清楚。
为什么需要寄存器 token?
每步 VLM 输出的 VL token 很多,直接送进 TTT 层太贵。16 个寄存器 token 在每步的注意力里读取所有 token(包括交叉注意力读 VL token),再把这一步的信息带进 TTT 层。消融里加寄存器提升 18%;同样的寄存器加到不跨时间的 GR00T 上反而降分。
为什么只冻结 GR00T、只训新层来预训练?
附录写明:预训练只调新加的序列层(TTT 或 GDN),其余冻结;后训练才全部微调。配合 tanh 门控(初值 0.001),目的是不破坏 GR00T 已有的能力。这也意味着「上下文扩展」实验里,变的只有序列层看过多长的序列。
一次模仿的「没见过的配置」有多难?
Circuit 约 80 种配置,训练用 20 种(每种 5–20 段人类视频),测试在其余配置上。配置由元件组合和左右两侧的装配顺序决定;顺序错了不给分。GDN 完成分 33% 但没有一次完整成功,主要错在拿错元件或顺序装反。
局限与疑点
作者承认的,和我们读出来的
论文自己提到的
- 训练上下文越长,训练成本越高;可以采用 TNT 等更新的 TTT 训练技巧。
- TTT 层的内层目标沿用通用的键值重建损失,可以探索面向机器人的目标。
- 不能处理部署中遇到的所有失败;下一步可以结合强化学习直接优化任务成功。
- 1K 以下的版本回合比训练窗口长,快权重更新到训练中没见过的远处。
我们读出来的
- 疑点主图 Pup Go Car 已含 DAgger 训练(序列模型用 DAgger Distillation),只在 Figure 8 图注里说明。
- 疑点「推理时延不随上下文增长」没有任何时延数字;动作块长度 H、去噪步数 k、推理时每次更新覆盖几个时间步都未披露。
- 疑点扩展曲线每点一次运行,512 步处 GDN 略高;参考线与其他图还原出的数字对不上。
- 真机每格 20 次(Gear Bot 与一次模仿 10 次),没有方差或显著性。
- 只有一个平台(YAM 双臂)、三个任务,都是装配类。
- 相关工作把 TT-VLA 描述成「在测试任务上收集额外数据微调整个模型」,与 TT-VLA 的实际做法(回合内用进度奖励在线更新 LoRA,不额外收数据)不符。
放到专题里看
反馈写进权重,而且训练时就学会了怎么写
在 Harness for Robotics 专题里,RoboTTT 归入(4)评估与反馈:部署时,执行产生的每一步观测和动作都在更新策略的快权重;训练时,DAgger Distillation 用人的纠正作为评价信号,教会快权重「看到这种失败就这样改」。
解读需要说明它和(4)的定义并不完全吻合:(4)要求「显式评价信号」,而 RoboTTT 在测试时的更新信号是自监督的键值重建损失,没有任何打分;显式的评价(人的纠正)只出现在训练时。从机制看,它同样接近(2)持久状态与记忆:快权重就是一种跨步保存执行历史的状态。我们按「在回合内根据执行结果改变策略参数」这一点,把它和 TT-VLA 放在一起。
| RoboTTT | TT-VLA | τ₀-VLA | MemoryVLA(2) | |
|---|---|---|---|---|
| 测试时变的是什么 | 每层约 10M 的快 MLP 权重 | LoRA 参数 | 执行记忆(文本)与子任务选择 | 特征记忆库(token) |
| 更新信号 | 自监督键值重建损失(每步) | VLAC 进度差分做 PPO 奖励(每 8 步) | 世界模型想象 + 价值打分(执行前) | 门控写入,无损失 |
| 显式评价出现在 | 训练时:人的纠正(DAgger Distillation) | 测试时:进度估计器 | 测试时:价值模型 | 无 |
| 训练与测试是否同一机制 | 是,更新规则和初值都元学习过 | 否,部署时额外加一层 RL | 搜索组件单独训练 | 是 |
| 跨回合 | 每回合从 W0 重来 | 每回合重置 | 记忆随回合清空 | 随回合清空 |
| 动作头 | flow matching DiT(GR00T) | 只支持离散 token | flow matching(MoT) | 扩散 DiT |
- 和 TT-VLA:两篇都在部署时改模型参数,但思路相反。TT-VLA 在一个训练好的 VLA 外面临时加 RL 更新,靠外部进度估计器给奖励,更新太频繁会掉到基座以下;RoboTTT 的更新是模型本身的一部分,训练时就以同样的方式在长序列上做过,不需要外部评价器。TT-VLA 只支持离散 token 的自回归 VLA,RoboTTT 正好建在 flow matching 的 GR00T 上。
- 和 τ₀-VLA:τ₀ 在执行前评价、改的是选哪个子任务;RoboTTT 在执行后吸收结果、改的是动作头的权重。τ₀ 的「记忆滞后 / 超前 / 未察觉失败」扰动样本,和 RoboTTT 的 DAgger Distillation 想解决的是同一类问题:让策略在自己出错之后知道该做什么。
- 和(2)类的 MemoryVLA、OptimusVLA:它们把历史存成 token 库或已执行的动作块,容量有上限或要合并;RoboTTT 把历史压进权重,容量由 MLP 决定,不需要删除或合并的规则。RoboTTT 的消融里「让动作 token 进 TTT」提升 23%,和 OptimusVLA 读已执行动作块的思路相通。
术语表
读这篇会遇到的词
展开术语表
- TTT
- Test-Time Training,测试时训练:一小部分参数(快权重)在训练和推理时都用自监督损失做梯度更新。
- 快权重 / 慢权重
- 快权重在推理时也被更新;慢权重(普通参数)推理时冻结。
- W0
- 快权重的初值,每个回合从它开始,通过「梯度的梯度」元学习。
- 寄存器 token
- 每步前面加的 16 个可学习 token,在注意力里读取本步信息,再带进 TTT 层。
- 序列动作强制
- sequence action forcing:序列训练时每个动作块独立采 flow matching 的噪声水平。
- TBPTT
- 截断反传:梯度只在段内流动,快权重跨段传递。
- DAgger
- 机器人执行、人在出错时接管纠正的数据采集方式;标准做法只用人的纠正微调。
- DAgger Distillation
- 整条交互历史都更新快权重,损失只算在人的纠正上。
- GDN
- Gated DeltaNet,线性复杂度的循环记忆层,状态用门控 delta 规则更新,不做梯度下降。
- Algorithm Distillation
- 把一个学习过程(这里是人纠正机器人的过程)蒸馏进模型的上下文学习能力里。
- YAM
- 本文使用的双臂桌面机器人平台。