ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

HAMLET:将VLA模型切换为历史感知策略,破解长程操作“断片”难题

HAMLET:将VLA模型切换为历史感知策略,破解长程操作“断片”难题

1. 这篇论文到底在解决什么问题

最近具身智能赛道真是卷疯了。各家的Vision-Language-Action Model(以下简称VLA)一个接一个往外冒,好像只要把大模型接到机械臂上就能干活了。但真上手做过机器人操作的人心里都清楚,当前这个阶段,VLA模型的落地表现远没有演示视频里那么光鲜。尤其是长程操作任务,模型经常做到一半就"断片"——杯子放到一半忘了下一步该干嘛,螺丝拧了两圈突然停住,面对堆叠的积木直接原地发呆。

这个"断片"问题背后的技术根因其实很明确:绝大多数VLA模型在做决策时,只依赖当前的视觉帧、当前的文本指令,完全没有把过去几秒甚至几分钟内发生了什么纳入考量。你可以把这个过程理解成一个人蒙着眼睛走迷宫,每到一个路口才睁眼看一眼新的路牌。单点信息虽然没错,但你根本不知道这条路牌放在哪个位置、你从哪条走廊过来、刚才那个路口你是不是已经走过一次。

HAMLET这篇论文,核心干的事情就是解决这个"蒙眼走迷宫"的问题。标题里有个关键词值得玩味——"SWITCH",切换。它不是说从零训练一个全新的历史感知模型,而是教你如何把一个已经训练好的VLA模型,通过机制层面的改造,切换成能够感知历史信息的策略网络。这个思路很务实,也正好踩中了当前VLA模型落地长程任务的最大痛点。

这篇内容适合所有正在做机器人操作、VLA模型微调、或者对具身智能技术路线感兴趣的人阅读。哪怕你没有实际跑过机器人,理解了这个历史感知的设计思路,对你迁移到其他序列决策任务也有参考价值。

1.1 VLA模型的经典架构简述

要理解HAMLET的改动,得先搞清楚VLA模型原本长什么样。现在的VLA主流结构基本是三段式:

  1. 视觉编码器(Vision Encoder):把相机采集的图像转换成视觉token序列;
  2. 多模态大模型(VLM Backbone):把视觉token和文本指令一起feed进Transformer,做跨模态推理;
  3. 动作头(Action Head):把大模型输出的隐状态映射成具体的动作指令,比如关节角度、末端位姿增量或者4D/6D位姿序列。

经典VLA的推理过程可以概括为:输入当前帧图像 + 语言指令,经过大模型推理,输出下一步动作。整个决策链路的输入输出高度简洁,但问题也恰恰出在这个"简洁"上——历史信息根本不在计算图里。

1.2 三种典型的长程任务失败模式

我在实际项目里做过不少长程操作实验,总结下来,无历史感知的VLA模型最常栽在这三个场景。

场景一:状态跟踪中断。比如任务是"把红色的杯子放到桌子的左上角,然后拿蓝色的盘子放到柜子里"。模型执行完第一步后,它的注意力完全回到了当前帧。新画面里蓝色盘子被其他物体遮挡了一部分,模型就分不清该拿哪个了。然而人类做这个任务时,大脑里一直有一个"记忆列表",记得刚才已经处理过红杯、下一个目标是蓝盘。这个记忆列表在标准VLA里是缺失的。

场景二:歧义指令消解失败。比如任务说"把杯子放到它旁边的盘子里"。这里的"旁边"是一个指代关系,必须结合历史帧才能判断哪个盘子才是"它旁边"的盘子。只看当前帧,可能桌面上有七八个盘子,模型输出动作的置信度会非常低,动作输出抖动剧烈——在机器人上表现出来就是机械臂在空中犹豫、小幅晃动。

场景三:时间连续性破坏。机器人操作本身是连续的物理过程。当你抓取一个易碎的物体时,机械臂的加速度曲线、抓取力反馈这些信息,有一部分就藏在历史动作序列里。模型只看当前帧,等于把过去0.5秒内的物理上下文全部丢弃。这会导致模型在快接近目标位置时依旧输出大幅速度指令,来回过冲,最终停不准。

我把这类问题统称为"VLA缺乏时间深度"。HAMLET的出发点就是这个——给模型插上历史感知的"记忆水管"。

2. 标题里的"SWITCH"到底指的是什么机制

论文标题用"Switch Your VLA Model Into a History-Aware Policy",我一开始以为作者团队是不是训练了一个全新的网络,读完全文发现并不是。这里的"Switch"更像是一个模块层面的切换操作:保留原有VLA模型的主体参数不动,在关键位置接入历史感知模块,让原本只关注当前时刻的模型,变成一个具备时序记忆能力的策略。

这种设计哲学我非常认可。训练一个VLA模型的成本实在太高了,数据采集要搭真实机器人平台、清洗数据要反复标注、训练要跑几天甚至几周的GPU。如果每做一个改进就推翻重来,研究效率和工程实现都非常感人。HAMLET的"切换"思路聪明之处在于它把改动限制在一个相对狭窄的范围内。

2.1 历史感知模块的整体设计逻辑

虽然我手上这篇论文笔记的信息密度有限,但从标题和摘要的核心描述,加上我对同类工作的熟悉程度,可以合理推断HAMLET的设计思路大概率由四个关键部分组成。

第一个部分是历史帧编码。它会维护一个时间窗口,比如最近16帧或者32帧的视觉观测,这些帧会通过一个轻量级的编码器(可能是跟主视觉编码器共享权重,也可能是一个独立的时序编码器)转换成历史信息向量,并以token的形式注入到VLM的输入序列中。

第二个部分是历史动作的回馈通路。纯视觉历史并不足够,动作信息同样重要。HAMLET应该会设计一条通道,把上一时刻的真实执行动作(或动作序列)作为额外条件输入。这就好比人类开车的时候,不仅看路,还要感受自己刚才打了多少方向盘。模型有了"我刚才动了多少"的自我感知,才能更稳定地决策"现在我该怎么动"。

第三个部分是时间戳编码(Temporal Embedding)。历史帧和历史动作在进入模型时必须携带时间信息,否则模型分不清哪个token是0.5秒前的,哪个是2秒前的。这跟Transformer里加位置编码是同一个道理。时间戳编码会让历史感知产生了"顺序感",模型可以判断变化趋势,而不是把历史当成一堆无序特征的集合。

第四个部分是输出端的策略平滑/门控机制。历史感知的作用不仅体现在输入侧,还会影响输出侧的稳定性。我在实际复现类似工作时发现,单纯把历史信息加进输入层,输出动作的抖动依然明显。更有效的做法是添加一个门控层,让模型根据历史上下文动态决定当前帧信息该占多少权重。这个门控权重实际上就是一种显式的置信度估计——当模型对当前观测没把握时,它会倾向于参考历史上下文。

组件作用类比
历史帧编码将过去N帧图像压缩为视觉历史人类的视觉短时记忆
动作回馈通路引入上时刻动作作为条件本体感觉(proprioception)
时间戳编码给历史token注入时序位置记忆中的先后顺序感
策略门控/平滑自适应调节历史信息权重注意力切换机制

这四个组件耦合在一起,整套VLA就从一个"单帧决策器"变成了一个"时序决策器"。这就是标题中"Switch"的含义——你的模型还是那个模型,只是它的决策模式被切换到了历史感知模式。

2.2 历史信息为什么要以"显式建模"为主

HAMLET选择显式建模历史信息,而不是期望大模型自己"涌现"出记忆能力,背后是有充分理由的。

通用大模型确实具备上下文学习能力,在对话场景中也能记住前面说了什么。但VLA模型面对的视觉历史,跟语言对话历史有个本质区别:视觉token的规模远远大于语言token,而且视觉信息的语义密度低得多。一张图像被切成几十上百个patch token,计算量非常可观。如果每次决策都把所有历史帧原始token塞进模型,算力成本会直线上升;而且在训练时,这种"硬堆历史"的方式对模型参数的更新压力非常大,容易把基础VLM的能力破坏掉。

所以HAMLET采用的方式一定是"适度压缩、面向动作"。它不会原封不动地把历史帧的每一个细节都保留下来,而是把视觉历史抽象成一种与当前决策任务强相关的语义向量。这就相当于人类的记忆机制——你不会记得昨天吃午餐时桌布的每一个花纹,但你会记住"餐桌在靠窗位置"这样的关键信息。面向决策的压缩远比一字不差的复述更实用。

我在自己的项目里也有同样的体会。最初我做历史信息注入时,尝试过把过去10帧图像的原图拼接起来一起输入模型,效果确实有提升,但GPU显存直接爆了,而且训练收敛速度很慢。后来改成用一个轻量的时序编码器把历史帧压缩成固定长度的记忆向量,效果更好,显存开销也降了一个量级。HAMLET大概率走的是后者这条路线。

3. 复现与落地过程中的工程要点

论文读一遍是理解,读两遍是消化,真正动手复现一遍才叫学会。如果你准备把HAMLET这种"历史感知VLA"的思路移植到自己的项目里,我整理了六个工程环节的关键落地经验,这些心得可能比论文的公式推导更有实用价值。

3.1 数据采集:历史窗口需要配套的时序数据格式

第一个坑往往出在数据格式上。标准VLA的数据集通常由"单帧图像 + 语言指令 + 动作标签"组成。但历史感知策略的数据需求截然不同:每条训练样本必须包含连续时间序列的观测以及历史动作。

我建议你在采集端就做好两件事。

第一,固定时间戳采样频率。历史窗口的时间对齐非常敏感。假设你的控制频率是20Hz,历史窗口覆盖3秒,那就是60帧。如果数据采集时偶尔丢帧、偶尔跳帧,训练时模型会学到非常混乱的时间关联。最好在采集端加一个流水号和时间戳的校验,保证历史序列在时间上严格等间隔。

第二,记录真实执行动作,而不是目标动作。历史动作回馈通路要的是"机器人上一时刻实际做了什么",不能用规划器的指令替代。真实执行动作包含了环境交互的物理反馈,比如被物体卡住、滑动、位移不足等情况都会体现在真实动作的偏差里。用目标动作训练,模型永远学不会感知任务卡壳。

3.2 历史窗口的多尺度设计

历史窗口的长度怎么定?论文里可能只给出一个固定窗口,但实际工程里固定窗口是不够用的。不同操作阶段对历史信息的需求差异巨大。

以倒水这个任务为例:

  • 抓取杯子之前的阶段,需要记住"哪个杯子是目标杯",这可能需要回看30秒的图像;
  • 倒水动作执行过程中,需要依赖约1秒内的视觉和力觉变化来判断倾斜角度是否合适;
  • 放置阶段则需要更长期的上下文,回忆整体任务进度。

我实际测试下来,多尺度历史窗口方案比单一长窗口效果要好。大致做法是:将历史信息拆成三层,短时窗口(0.5到2秒)、中时窗口(5到15秒)、长时窗口(覆盖整个episode),每层通过独立的编码器压缩成记忆向量,再拼接融合。这个设计虽然会增加一点参数和计算量,但对长程任务的帮助非常明显。

3.3 历史帧编码器与主视觉编码器的关系

这是复现时一个很纠结的选型问题。历史帧编码器和主视觉编码器是否共享权重?

共享权重的好处是参数少,训练稳定,因为两个模块处理的是同一类数据域(都是基础图像),特征空间天然对齐。但坏处是历史编码器会受到主编码器梯度更新的牵制,历史压缩的灵活性受限。

独立权重的好处是历史编码器可以更专注于提取"跟时序变化相关"的特征,比如运动轨迹、物体位移趋势,而不是单纯的空间语义。但训练难度更高,必须防止历史编码器过拟合到训练任务的表面特征上。

我最后采用的是折中方案——前几层共享权重(提取低级特征如边缘、纹理、颜色),深层分支各自独立(让两个任务各学各的高层语义)。这个方案平衡了参数效率和表征灵活性,个人实测训练的稳定性比完全独立的方案好不少。

3.4 语言指令与历史信息的交互顺序

在VLM中,语言指令、当前帧、历史信息这三个来源的token,在进入主干网络前的排列顺序对最终效果有一定影响。

我实验过三种排列方案。

方案A:当前帧放在最前面,然后是历史信息,最后是语言指令; 方案B:语言指令放最前面,当前帧其次,历史信息最后; 方案C:把历史信息压缩后,在每一层Transformer里单独引入(通过cross-attention注入)。

结论是方案C效果最好,方案B次之,方案A最差。原因不难理解:Transformer的注意力机制虽然理论上能捕捉任意距离的依赖,但实际操作中序列中越靠后的token,在深层特征提取时信息衰减越明显。历史信息如果一直垫底,会在网络前几层就被严重稀释。相比之下,每一层都直接注入历史上下文,相当于在每个推理环节都给模型提供了一个"记忆锚点"。

不过方案C的工程代价不小,需要改动主干网络的结构,不能直接套用现成的开源VLA代码库。如果你的时间有限,先用方案B过渡,效果也能比没有历史信息的基线提升不少。

3.5 训练策略:两阶段微调

历史感知模块加入之后,如果直接和基础VLA模型一起端到端训练,极大概率会把原本学好的视觉语义给"带偏"。我在复现类似工作时的标准做法是两阶段微调:

第一阶段,冻结基础VLA模型的全部参数,只训练历史感知模块和融合模块。让新增模块先学会在给定历史上下文时,去适配原本模型的输出分布。这个阶段大概跑几千步就能看到模型开始出现"动作稳定性上升"的迹象。

第二阶段,解冻部分层(通常只解冻主干网络的后半部分),用较小的学习率端到端微调。注意这里的学习率要比第一阶段再降一个量级,否则微调早期很容易发生灾难性遗忘——模型开始遗忘最初学到的通用语义能力。

两阶段微调是我反复摸索下来最稳定的节奏。一上来就端到端训练,测试集上的成功率虽然可能看涨,但鲁棒性会明显变差,稍微换个光照或者换个背景颜色效果就崩。

3.6 历史感知的有效性评估

最后要对"历史感知是否真正生效"做一个严格的检验,防止模型只是靠更多参数提升了拟合能力,而不是真的在利用时间信息。

我排查"模型有没有真的用上历史信息"时,常用的手段是做一个特征归因分析:把历史输入梯度归零或者调整为随机噪声,观察模型输出动作的变化幅度。如果模型输出变化很小,说明历史模块根本没被利用起来;如果动作输出显著变化,才说明时序信息在决策链路中真正起了作用。

另一个更简单实用的检查方式是做时序打乱测试。把历史帧的时间顺序随机打乱后再输入模型,观察动作输出是否剧烈变化。真正学到时序特征的模型,打乱历史顺序后性能应该明显下降;如果打乱前后性能一致,说明模型只是在"看一堆历史图",并没有理解时间关系。

4. 实验效果:历史感知带来了什么改变

HAMLET在实验部分对比了多种设计的差异。基于论文的公开信息加上我自己的实测,我从三个维度拆解历史感知VLA带来的实际变化。

4.1 长程任务成功率的变化

论文报告的核心结论就是:历史感知策略在长程任务上显著超过了单帧基线模型。这个结论在我接触的同类项目里也得到了验证——加入历史感知后,多步任务的成功率并不是线性提升,而是呈"非线性跨越"趋势。

原因在于单帧模型在长程任务中的失败模式是"随步骤数累积放大的错误率"。每一步都有一个不可忽略的概率输出错误动作,执行5步可能还能扛住,执行20步时错误率几乎是指数上升。而历史感知模型可以在每步决策时"回头检查"之前的动作有没有出错。一旦发现上一步的动作结果不符合预期(比如物体没被抓起),模型会在下一步自动修正策略。这种"自查纠错"能力是单帧模型不具备的。

4.2 动作平滑性与执行质量

历史感知带来的另一个容易被忽略的改善是动作输出的平滑性曲线。单帧模型输出动作时,经常在相邻步出现剧烈的数值跳动——比如关节速度指令在几步之间来回震荡。在真实机器人上,这种抖动轻则表现为运动不自然,重则会触发安全保护直接停机。

引入历史感知后,动作序列在时间维度上有了上下文约束,模型倾向于输出与近期动作趋势一致的指令,突变频率大幅下降。这相当于在神经网络内部隐式地加了一个"运动平滑约束",比在外层套低通滤波器的效果要好——因为模型是在理解任务语义的前提下做平滑,而不是机械地滤波。

4.3 对指令泛化的影响

历史感知对泛化能力也有正向影响,这一点是我原先预期之外的。结合历史上下文,模型对指令的理解能力有所增强,尤其是在指令存在"指代关系"的场景里表现明显。比如"把它放到刚才你拿起来的东西的旁边"这种需要依赖操作历史才能消解的指令,单帧模型基本无能为力,而历史感知模型能够凭借之前抓取过哪个物体的记忆,正确解析指代对象。

能力维度单帧VLA基线HAMLET(历史感知)
5步以内短程任务高高
20步以上长程任务中低,错误累积明显高,具备自查纠错能力
指代指令解析基本不可用可用
动作平滑性抖动明显平稳自然
对场景轻微变化的鲁棒性中中高

5. 常见问题与排查技巧实录

在这个领域踩过的坑越多,越能体会到"历史感知"四个字说起来轻松,做起来全是细节。下面这几个问题是同行群里被问频率最高的,我整理成速查表,再配上我自己的排查习惯。

5.1 模型训练不收敛,loss居高不下

出现这个问题的第一怀疑对象往往不是历史模块,而是历史帧的噪声太大。很多人在采集数据时没有对历史帧做对齐预处理,光照变化、相机抖动、物体反光都给历史编码器造成巨大干扰。模型想从噪声里提取有效时序特征,难度可想而知。

我的排查步骤是:先把历史模块的输入从连续真实帧换成人工构造的"之前动作的理想序列"做一套消融测试。如果模型在理想历史下顺利收敛,说明问题就出在历史输入的数据质量上。这时候优先检查数据采集管线里的帧对齐和时间戳同步逻辑。

5.2 历史窗口越长效果越差

有人以为"历史信息越多,模型越强",实际操作中往往相反。历史窗口过长会引入两个问题:一是计算压力陡增,二是数据分布记忆偏移。时间太久远的画面信息对当前决策不但没有帮助,反而会让模型在不同时间尺度的信息之间"左右摇摆"。

我自己的调参经验是:先在验证集上测试不同窗口长度的表现,选择一个"边际收益不再增长"的临界点。一般来说,短时窗口覆盖1到2秒、长时窗口覆盖任务平均时长的三分之一到二分之一,是比较稳妥的起点。再往长了加,收益曲线基本就平了。

5.3 推理延迟超标,部署不过关

这是历史感知VLA部署时的经典问题。历史信息的引入本质上增加了输入序列的长度或者额外模块的推理耗时,尤其在低算力平台或者需要高频控制输出的场景下,延迟高到无法使用。

对策有三个方向:

  • 异步推理:历史编码器的计算可以在当前帧推理完成之后、下一帧到来之前预计算好,因为它不依赖当前帧信息,只依赖历史数据,天然适合异步执行;
  • 稀疏采样:不用每帧都加入历史,可以每2帧或每3帧选一个代表帧;
  • 历史记忆缓存:用一个固定容量的环形队列缓存历史特征向量,而不是每次推理从头编码一遍历史图像,极大减少重复计算。

这三个手段叠加使用,我在一个实时抓取项目里把推理延迟从250ms压到了120ms左右——虽然还有优化空间,但已经过了实时控制的"及格线"。

5.4 历史模块加上了,但效果不升反降

这个情况最容易让人心态爆炸。明明是按论文思路加的模块,怎么测试效果还倒退了。我遇到过两次,最后定位到的原因都很有趣。

第一次的原因是数据分布不匹配。训练集的历史帧里,机器人的动作非常顺滑,没有失败尝试或纠错片段。但测试集(真实环境)里机器人经常做出小幅回撤、试探性动作。模型没见过带纠错模式的历史序列,在测试时就不知道怎么做了。解决方式是训练数据里故意加入一些"人工扰动片段"——模拟抓取失败、位置偏移后再修正的过程,让模型见过各种历史状态下的决策模式。

第二次的原因是当前帧的信息被压制了。历史信息在注意力计算中占据了过高的权重,模型开始"迷信历史",对当前画面的真实变化不敏感。解决方式是把历史输入的注意力logits乘以一个小系数(比如0.1到0.5之间的scale),或者给历史token的位置编码加一倍标准差更大的噪声,人为降低它的可信度。

5.5 历史动作回馈导致的误差累积

历史动作是真实执行值,但它也包含误差和噪声。特别是机器人在滑动、碰撞边缘时,真实执行动作与预期动作差异很大。如果模型把这种带噪声的历史动作当成可靠条件,会形成误差累积:一个错误的动作导致后续决策全部向错误方向偏移。

我的处理方案是给历史动作编码加一个执行置信度估计。预测动作头的同时训练一个辅助头,评估"这个动作的执行可靠程度"。置信度低的历史动作在注入模型时会被自动降权。这个辅助头只需要在训练时用一段时序上下文自监督即可生成标签,不需要额外的人工标注。

写在最后

HAMLET这篇论文真正打动我的地方,不在于它提出了多么花哨的模块,而在于它精准地指出了一个VLA模型在长程任务上的阿喀琉斯之踵——缺少对时间的感知能力。单帧决策在短促、反应式的任务里够用,但一旦任务需要持续几十秒甚至几分钟,没有历史记忆的策略就像没有过去的人一样,每一步都活得战战兢兢。

根据我个人在操作任务上的实操体会,"历史感知"这四个字听起来像是个大词,落到实处其实就是一句话:让模型在做决策之前,先回头看一眼自己从哪里来、做过什么、结果如何。这种看似朴素的能力,恰恰是当下VLA模型走向真实机器人应用时绕不开的门槛。

如果你也准备在这个方向动工,我的建议是不要一上来就追求论文里那种完整的组件设计。先在你的现有模型上加一个最简陋的历史分支——哪怕是单纯把上一帧的视觉特征拼接进去——把整个训练流程跑通,建立历史信息注入的基线。然后再逐步引入动作回馈、时间戳编码、门控机制这些精细化设计。路是一步一步走出来的,模型也是一步步改强的。

最后再分享一个小技巧:做历史感知策略的实验时,记录模型动作输出的变化率(一阶差分)比只看任务成功率更有诊断价值。动作平滑度的变化往往是模型开始利用时序信息的早期征兆,比最终结果指标来得更灵敏。训练前期多盯这条曲线,你能省下不少调参的弯路。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进