一台机械臂学擦桌子。人握着它的手,从桌角擦到桌心,来回五十遍,每帧画面和对应的关节动作都存了下来,训练一个网络:看到当前画面,就输出下一时刻该往哪儿动。

训练完,演示回放很漂亮,放到真桌上第一次也漂亮。第二次手肘碰了一下桌沿,整条手臂偏了两厘米——然后它没有拐回来,反而越擦越歪,最后把抹布摁进了桌缝。它的每一步预测都不算离谱,人眼几乎看不出错,可整条轨迹就是散了。这篇要说清的是:为什么一执行就会偏出去,以及现在的办法到底修好了哪一段。

一条“示教”长什么样

机器人抄不了人类的动作,只能抄自己身上的数:摄像头画面、关节角、夹爪开合,加上人在那一刻给出的目标动作。所以标准做法是 遥操作:人握住一组小机械臂(叫“主手”),主手怎么动,机器人的手臂就怎么动,等于把自己的手借给了机器人。每一帧记下来,就得到成对的样本——此刻看到什么,此刻该做什么。

收数据的成本很不友好:给机器人一小时数据,至少要花熟练操作员一小时,算上布景、复位、失手重录,实际净产出还低于这个比例 4。规模感受一下:公开数据集 DROID 由 13 家机构、50 名采集员跑了 12 个月,攒下 7.6 万条轨迹、约 350 小时数据、564 个场景 5。350 小时差不多是一个人连续操作一个半月;而语言模型预训练用的文本是几十万亿 token 的量级。

但关键不在量,在这句话:每条样本都是“专家在专家没出错的状态下”做出的动作。 训练时喂给网络的世界,全是一帆风顺的世界。

行为克隆:朴素到容易忽略后果

照这个思路训练,形式和图像分类没有区别:输入画面和关节状态,输出动作,拿示范的动作当标签,算误差、反向传播。这方法叫 行为克隆,字面意思就是照抄行为。

它像照着视频学做菜。视频里的人把洋葱切成丝,你跟着切丝;他下锅,你下锅。只要进度一致,每一帧都对得上。麻烦出在进度不一致的时候:你切得粗一点,抬头看时视频里那个人正面对一碗切好的洋葱丝,而你手里是一堆切歪的洋葱块。这个画面,视频里从没出现过。

机器人处境一样,只是它不会觉得奇怪。它不会停下来说“这个画面我没见过”,它会照常输出一个动作——基于一个训练时从未见过的输入。

偏 2 毫米怎么变成偏 20 厘米

训练数据的分布,是示范者走过的那些状态;策略执行时遇到的状态,是它自己走出来的那些状态。两者不是一回事,差多远取决于它错多少。这种“输入分布在测试时变了”的情况叫 协变量偏移。

偏移会自我放大:

绘制中

这就是 复合误差。它不是“模型精度不够”,而是第一次的小错改变了后续所有判断的前提。

量级可以算。设任务走 TT 步,策略在专家状态上每步出错概率为 ε\varepsilon,并先做最乐观的假设:每次犯错互相独立,错一次这条任务就算失败。那么成功率是 (1−ε)T(1-\varepsilon)^T。取 ε=1%\varepsilon=1\%、T=100T=100,0.99100≈0.370.99^{100}\approx 0.37——一百步的任务只有三成多能走完,尽管每一步正确率有 99%。

真实情况比这个估计更糟,因为这个假设里的失败是“运气不好”,而实际是错误主动把机器人推到训练数据之外:一旦出了分布,后续每一步都在猜,不再有 99%。理论分析给出的最坏情况是,行为克隆的累计代价按 T2εT^2\varepsilon 增长,与任务长度的平方成正比 1。任务长度翻倍,误差最坏变四倍。这也解释了为什么实验室里能演示的机器人任务,绝大多数只有几秒。

三种补救,各修一段

病因是“训练时见的状态和执行时见的状态不重合”,所以办法只有两条路:把训练分布扩展到机器人真正会走到的地方,或者减少它走到未知状态的机会。

第一条路:让专家去看机器人自己走到的状态。 这就是 DAgger:先训一个初版策略,让它跑,跑歪了就在那个歪掉的状态上请专家给出“此刻应该怎么做”,把新样本加进数据集重训,反复迭代。理论上这类做法能把最坏代价压回与任务长度成线性的 TεT\varepsilon 1。代价是专家得一直盯着、随时接管,比单纯遥操作更贵。

第二条路:减少犯错的机会次数。 这是动作分块在做的事。标准行为克隆每一步预测一个动作,TT 步就有 TT 次跑偏的机会;动作分块一次预测接下来 kk 步的一整段动作,连着执行完再重新看。ACT(Action Chunking with Transformers)把 kk 取到 100 步 2。

它压住的是哪一部分误差,值得说清楚:它没让每次预测更准,减少的是“独立做决定”的次数,有效步数从 TT 变成 T/kT/k,按上面的估计,误差累积的机会少一个数量级。但光靠“次数变少”还不够,因为块内是开环执行的,中间没人纠错。ACT 的第二个设计补上了这点:不等一块执行完再问,而是每一步都重新问一次策略,此时手上有若干条重叠的预测,再按指数权重平均(temporal ensembling)。看起来是“一执行就一整块”,实际新观测每一步都在进来,只是被平滑地融合了 2。

效果具体到什么程度:在开调料盒、插电池这类毫米级精度的双臂任务上,50 条示教(约 10 分钟数据)能到 80–90% 的成功率 2。换成标准行为克隆,这类任务基本做不出来——很小的预测误差会被接触放大成很大的状态差异。

第三条路:喂更多不同场景的数据。 Mobile ALOHA 给了个干净的对照:移动加双臂做家务,每项任务只采 50 条示教,单用这些数据训出的策略在“按电梯”上整条成功率为 0;加上 825 条场景完全不同的静止双臂数据一起训练,整条成功率升到 95%,七个任务里五个明显提升,平均绝对提升 34% 3。

注意它修的不是同一件事。前两条对付“执行中越走越偏”,共训对付“这条示教覆盖的变化太少”:换个杯子、光变暗、视角偏一点,策略就没见过。它提供的是“怎么靠近物体、怎么下手”这类先验,让策略在样本很少时不至于死记这 50 条轨迹。

边界在哪

动作分块没解决“演示里根本不存在的状态”,它只是让机器人少走到那里;走到了照样输出一个自信的错动作。

它还有自己的新代价。块内那一小段是开环的:如果执行到一半时环境变了(有人推了一下桌上的东西),这个变化要等块执行完、或靠 temporal ensembling 慢慢渗进来才被响应。块越长,抗突发变化越差;块越短,误差累积的机会越多。这是按任务要调的量,不是一个能一路调大的旋钮。

最后,示范全是成功的。只学好动作的策略不知道自己错了长什么样,所以它不会纠错——这也是现在要专门收集失败与恢复数据的原因。DROID 就另外记录了约 1.6 万条标记为不成功的轨迹 5。

一句话收束

示教数据教的不是“这个任务怎么做”,而是“在我见过的这些状态下该做什么”。一旦执行把机器人带出这个范围,它就在没有参考答案的地方继续作答,而它的错误又把它推得更远。三种补救各修一段:DAgger 把机器人自己走到的状态补进训练集,动作分块减少独立决策的次数,大规模多场景数据让“没见过”晚一点发生。没有一种取消了这个前提,它们只是把它往外推。