首页 / 资讯中心 / 文章详情

视觉-动作指令微调:提升机器人学习泛化性的关键

视觉-动作指令微调:提升机器人学习泛化性的关键 ★ FEATURED ARTICLE
做机器人学习这块的朋友应该都有一种共同的体感视觉语言模型VLM越来越强但要把它真正“接”到机械臂上总觉得隔着一层东西。最近我花了一晚上认真读了这篇标题很长的论文《LLARVA: Vision-Action Instruction Tuning Enhances Robot Learning》虽然名字绕口但核心命题非常直接把视觉观测和动作输出放到同一个“指令微调”框架里到底能不能提升机器人学习的泛化性读完之后我的结论是这个思路的工程价值被低估了。这篇博文就是一篇论文拆解笔记我会先讲清楚它解决的问题是什么、方法骨架怎么搭、实验上通常关注哪些维度再聊聊如果我想在自己的数据集上复现这套视觉-动作指令微调管线应该从哪下手、有哪些坑。适合两类人看一是刚入机器人学习、想搞懂VLAVision-Language-Action这条路线的同学二是已经在跑模仿学习基线但困惑“为什么视觉特征和动作头总是不太匹配”的工程师。1. 这篇论文到底在解决什么问题1.1 一个容易被忽略的错位视觉特征和动作输出没有对齐早期的机器人模仿学习管线通常是两条腿视觉模块负责从图像里抽取特征动作模块负责把这些特征映射成关节速度或末端位姿。常见的做法是拿一个预训练的视觉模型做backbone后面再接一个MLP或者Transformer动作头。听起来顺理成章但实际操作中你会发现一个尴尬的问题视觉模型在ImageNet或者Web数据集上预训练时根本没有接触过“这张图接下来对应什么动作”这个信息。它学习到的是物体类别、场景语义而不是“我现在应该把手往左移5厘米”。这就像教一个新手开车给他看了大量道路照片告诉他这是红灯、这是行人、这是车道线但从来没有把“看到红灯”和“踩刹车”这两件事绑定训练。等真上车的时候他能认出路况却不知道手脚该怎么动。LLARVA这篇论文的出发点就是把“看到什么”和“接下来动一下”直接打包成指令样本让模型在训练阶段就开始建立视觉特征与动作输出之间的强关联。这种做法术语叫Vision-Action Instruction Tuning本质上是对齐视觉表征和动作表征的语义空间。1.2 为什么不是从头训练而是“指令微调”有人可能会问既然视觉和动作对不齐那干脆用一个端到端的大模型从零开始学任务不就行了理论上可以但实际上有几个很现实的问题。第一是数据量。机器人示教数据的采集成本极高一条有效轨迹往往需要人工遥控机械臂、反复演示、清洗时间戳不对齐的坏样本。哪怕是在仿真环境里批量生成也很难短时间凑够从零训练一个大模型所需的千万级样本量。第二是算力。从头训练一个多模态模型对大多数人来说遥不可及。第三是灾难性遗忘。即便你费尽力气从零训了一个模型它的语言理解能力和通用视觉先验也会因为训练目标太聚焦而退化后续换一个任务又得重来。所以“指令微调”是性价比最高的路线先利用VLM已有的视觉语言基础把动作知识当作一种新任务注入进去而且注入的方式不是传统的“给一段文字prompt让它输出动作”而是把动作本身变成一个可以和视觉token相互作用的语义角色。这也是我把这类工作归为VLA路线里偏“指令派”的原因。为了更直观我画了张对比表来区分主流做法和LLARVA这类指令微调做法的差别对比维度传统“视觉特征动作头”通用VLM直接输出动作Vision-Action指令微调视觉特征训练目标识别/分类为主语言对齐为主与动作token对齐为主动作输出方式连续向量单独head文本化/离散化token潜在动作token解码器还原模间关系视觉模块和动作头分开训练模型“读”文本prompt再输出视觉动作联合组成指令样本数据效率需要大量配对数据需要强语义任务描述中等数据量即可有明显提升2. 方法拆解Vision-Action指令微调是怎么搭起来的2.1 数据层面把“图像序列动作序列”做成指令对理解这套方法最关键的突破点在于数据组织方式。传统方法里一条演示数据是“若干帧图像 每个时刻对应的动作向量”。LLARVA的做法是把动作序列先编码成潜在动作token然后按照语言模型的指令模板把“观测图像”和“动作token”组合成类似多轮对话的样本。举个例子假设一个桌面抓取任务示教数据有50帧图像每一帧对应一个六维末端位姿动作。做法不是让模型每帧输出一个连续向量而是把整个动作序列通过一个动作编码器压缩成若干个离散token然后排列成类似这样的格式System: 你是一个机械臂控制模型请根据当前观测输出下一步动作。User: [观测图像帧1][观测图像帧2][观测图像帧3]...Assistant: [动作token_1][动作token_2][动作token_3]...这样做的第一个好处是模型在推理时看到的输入格式和训练时完全一致没有“换个场景就不知道该怎么组织输入”的问题。第二个好处是动作被离散化之后VLM可以像生成文本一样逐token生成动作不需要在模型的输出层外接一个额外的回归头模型结构变简单了训练也更稳定。关于动作编码器我理解的常见做法是用一个类VAE变分自编码器结构把原始连续动作压缩到低维潜在空间。为什么这样做因为直接让语言模型输出连续坐标本质上是在做一个高维回归任务这对LLM来说并不擅长。离散化之后模型可以把“预测下一个动作token”当作一个类别选择问题稳定性高很多。如果做个生活化类比连续动作就像是钢琴的每个琴键都要单独记忆而潜在动作token就像是五线谱上的音符只需要记住有限的音符组合就能还原出各种旋律。当然压缩过程中会有信息损失所以动作编码器的重建质量直接决定了整条管线的上限。这一点我在后面实操部分会再展开。2.2 模型结构视觉编码器、动作编码器与LLM主干如何协作这套方法的模型结构从大的模块上分无外乎几块视觉编码器、动作编码器、投影层、LLM主干以及动作解码器。视觉编码器负责把原始图像转换成视觉token序列。这里通常会用一个在大规模数据上预训练过的视觉Transformer但论文的取向是在视觉-动作指令微调阶段需要对视觉编码器做一定程度的解冻甚至是低秩适配因为通用视觉特征并不天然适合动作预测。只冻结视觉编码器的话后续LLM再怎么学也很难把视觉里面跟动作强相关的细节比如物体边缘的深度线索提出来。投影层的作用是把视觉token映射到LLM的embedding空间。这里有一个容易被忽视的细节投影层参数量不大但它决定了视觉信息以怎样的“语言形式”进入LLM。如果投影层训练不充分视觉token在LLM看来就是一堆乱码。所以论文里普遍的做法是在正式指令微调之前先做一个阶段性的跨模态预训练让投影层和视觉编码器适应动作token的表征方式。LLM主干承担的是跨模态推理职责。它不直接输出动作而是把“视觉上下文历史状态”融合成隐状态再用这个隐状态去预测动作token的分布。训练时的loss通常包括两部分一部分是语言/推理目标的交叉熵另一部分是对动作token预测的交叉熵。但要注意动作token预测的权重不宜过大否则模型会把所有容量都用在动作映射上语言理解能力会退化。在推理阶段模型接收最近N帧观测图像作为上下文自回归地生成一串潜在动作token然后通过动作解码器把它们还原成真实世界的动作序列。这里的上下文窗口设计也很有讲究窗口太短模型看不到运动趋势窗口太长则容易把无关的历史信息带进来而且推理延迟会显著上升。2.3 一套最小训练流程的伪代码为了把上面的抽象描述变成更可操作的东西我写一段简化的伪代码模拟从数据准备到训练再到推理的完整流程。这段代码不针对某个具体框架只用来表示关键步骤之间的依赖关系方便大家对照自己的项目理解。# 假设已有 # - demo_data: List[Dict]包含image_frames (T, H, W, 3) 和 actions (T, A) # - action_encoder: VAE模型含 encode() 和 decode() 方法 # - visual_encoder: 预训练视觉Transformer # - projector: MLP投影层把视觉token映射为llm embedding # - llm: 预训练语言模型 # - action_decoder: 与action_encoder配套 def prepare_instruction_samples(demo_data): samples [] for demo in demo_data: images demo[image_frames] actions demo[actions] # (T, A) latent_tokens action_encoder.encode(actions) # (T, L) for t in range(3, T): ctx_images images[t-3:t] # 取历史N帧 target_tokens latent_tokens[t] sample { images: ctx_images, input_ids: tokenize(根据观测输出动作), labels: target_tokens, } samples.append(sample) return samples def train_one_step(batch): img_feats [visual_encoder(img) for img in batch[images]] img_feats projector(torch.stack(img_feats)) # (B, N, D) txt_feats llm.embed(batch[input_ids]) fused llm.forward(inputs_embedstxt_feats img_feats) logits llm.lm_head(fused.hidden_states) loss cross_entropy(logits, batch[labels]) return loss def inference(obs_images, action_decoder): ctx projector(visual_encoder(obs_images)) pred_tokens llm.generate(inputs_embedsctx, max_new_tokens8) real_action action_decoder.decode(pred_tokens) return real_action这里我把目标token设计成单独的时间片实际论文里可能会采用更精细的因果掩码和窗口关系但核心思想是一致的模型看到的上下文是“视觉帧动作token的历史”预测目标是“下一个动作token”。训练对象不再是一个孤立的动作回归任务而是被嵌在指令模板里的多模态生成任务。3. 实验上最值得关注的三个维度3.1 零样本迁移与少样本拿捏这类论文最看重的一个指标是模型在训练时没见过的环境里表现如何。比如只在仿真桌面场景上做视觉-动作指令微调然后直接拿到真实机械臂平台上测试抓取成功率。这里的“零样本”不是指模型凭空学会抓取而是指它能把训练中抽象出来的“看到什么就做什么”映射规律迁移到新背景、新物体、新相机视角上。从标题语义和摘要描述来看LLARVA强调性能提升的关键是“指令微调”本身。也就是说同样的骨干网络如果只是做视觉特征提取动作头回归跟在指令模板里把视觉和动作token统一建模相比后者的迁移成功率会有明显领先。原因在于指令微调强制模型把视觉表征和动作语义绑定在一个上下文里模型学到的不是孤立特征而是“视觉-动作配对”的条件分布。少样本场景也值得关注。现实项目里不可能为每一个新物体都采集几百条演示所以论文实验如果展示了“在新任务上只给8~16条演示就能快速适应”那说明它的表征结构更适合被新任务扩展。这个特性我认为来源于它把动作离散化、语义化之后模型可以利用语言模型强大的模式记忆能力而不是从零拟合一个动作流形。3.2 动作token化的粒度与重建误差读这类论文不能只看最终成功率还要看动作编码器的信息瓶颈设置在什么位置。动作编码过程像一个压缩过程压缩率越高模型预测越容易但丢掉的动作细节也越多。比如一个小小的夹爪闭合动作可能只占潜在空间里很细微的一个维度如果压缩后这个维度被合并到其他动作里重建出来的动作就是“意思对了但差了那么一点”。公开研究里这种潜在动作表示通常会做一个重建误差表对比不同码本大小、不同潜在维度下的Mean Squared Error。我最关心的是在高频动作比如快速插拔、抖动、转向上重建误差是不是显著大于低速稳定动作。如果误差分布不均衡模型可能会系统性地学丢那些“关键时刻的小动作”导致任务失败。读实验部分时我建议重点关注这个误差表而不是只盯着平均成功率。3.3 泛化到“看不见的组合”的能力机器人学习领域有个常见陷阱模型在训练环境里跑得飞起但换一个光照条件、换一个同款但不同颜色的物体性能就断崖式下跌。这背后的原因是模型学到了背景特征和物体外表的捷径而不是真正理解“夹爪接近物体表面时应该张开到什么程度”这种物理关系。视觉-动作指令微调的作用就是把这些物理关系更直接地暴露在训练目标中。因为模型必须在视觉token和动作token之间建立显式依赖它很难绕过视觉信息直接记忆动作。如果论文的实验里设计了“训练时只出现红色方块测试时换成绿色方块”“训练时机械臂在左臂位测试时在右臂位”这类组合那确实能说明指令微调带来的泛化收益是结构性的而不是数据集本身的红利。4. 如果我要复现这个思路我会怎么做4.1 从最短路径开始先做一个单任务demo很多人拿到这类论文第一反应是“我要完整复现它的模型结构”。我的建议正好相反先不要碰复杂的模型架构而是把你自己的模仿学习数据集重新打包成“视觉-动作指令对”的格式然后在一个很小的模型上做一次指令微调实验。具体分三步第一步数据清洗。把演示数据中时间戳对齐、剔除停滞和抖动片段。这个工作在传统模仿学习里也是必须的但在指令微调范式下格外重要。因为指令微调会把动作序列离散成token如果某一段动作明显抖动token化之后会变成一堆互斥的离散选择模型无所适从。第二步训练一个最小的动作Token编码器。用你任务里最常见的几类动作片段比如平移、旋转、抓取、放置训练一个小的VAE。不用一开始就追求高精度重建只要重建后的动作能让机械臂在仿真里执行成功率达到60%左右就可以先拿去做指令微调实验。第三步跑一个消融对比。同一份数据、同一个基础模型A组用传统“图像特征动作回归头”B组用视觉-动作指令微调。你会发现B组的训练收敛速度可能略慢一些因为在初期视觉和动作token之间的对齐关系还没建立好但只要过了某个门槛它在新场景上的表现会稳定超出一截。这个过程本质上是为了验证“这个方法到底适不适合你的数据分布”而不是直接复现一个论文里的SOTA数字。我实验下来最值得复现的其实是这种“用指令模板把动作语义化”的思路而不是具体的网络维度。4.2 数据组织与超参选择的经验参考在数据组织上有一个细节容易踩坑图像帧和动作token之间的对应关系要非常严格。动作token的粒度决定了多少个动作step对应一个token。如果你把连续5个step编码成一个token那推理时模型只能每5个step输出一个动作中间的动作要靠解码器线性插值补上。这个问题在低速精细操作时很致命。我建议的动作token粒度是先把一段轨迹按时间均匀切片让每个token覆盖3到5帧前提是你的控制频率足够高比如30Hz以上。如果控制频率太低就不要过度压缩宁可让token序列长一点也要保证重建精度。超参方面有几个我实测后比较靠谱的参考值超参数建议范围个人心得上下文图像帧数4~8帧太少看不到运动趋势太多主要增加推理延迟视觉编码器状态部分解冻或LoRA适配完全冻结容易导致视觉特征与动作语义脱节动作token潜在维度16~64维维度太低动作细节丢失明显指令微调轮数2~4个epoch再多容易过拟合到数据集的轨迹模式训练batch size视计算资源而定小batch下先保证梯度稳定此外有一点容易被忽略推理时的动作平滑。即使模型预测的潜在动作token在语义空间是连续的解码到真实世界坐标系后依然可能出现相邻动作之间的小幅跳变。通常需要加一个低通滤波或者指数移动平均代价是会让动作延迟一点点但能显著提升实机部署的稳定性。4.3 计算资源不够时的替代方案如果手头没有A100这类大显存显卡也不是不能跑。可以先把视觉编码器冻结用LoRA微调投影层并且把语言模型换成最小号的开源模型甚至用中等规模的多模态模型。这时候模型的绝对性能不会太高但你依然可以验证一个核心问题视觉-动作指令微调这个数据组织方式是否比传统的独立动作头更好。我自己的经验是用大约50~100条示教数据在单张消费级显卡上花半小时训练一个最小demo就足以观察到明显的表征优势。因为指令微调成功与否很大程度上取决于数据的组织逻辑而不是模型的绝对规模。5. 实操中常见的坑与排查实录5.1 两个模态“鸡同鸭讲”loss下降缓慢这个坑我遇到过很多次。现象很典型loss降得非常慢或者降到某个值就下不去了视觉token和动作token在模型看来好像各说各话完全无法融合。排查思路很简单第一步先查投影层输出和文本embedding的分布是否在一个量级。如果视觉特征经过投影后像素值波动很大而文本embedding的分布很平滑那LLM根本没法把两者等权重地融合。另一个比较容易忽视的原因是视觉编码器输出token数量太多。一张384×384的图通常输出几百个视觉token如果全部塞给LLM注意力基本被视觉token淹没动作token很难得到有效关注。通常需要做一个token合并或者采样把视觉token数量压缩到几十个以内让动作token在序列里占有合理的比例。5.2 动作重建误差很大预测再准也是白搭我见过很多项目花了大量时间调指令微调模型最后发现瓶颈根本不在预测部分而是动作编码器重建动作时就已经变形了。最典型的例子是模型预测的潜在动作token明明很准但解码后的动作速度曲线有明显的“台阶感”不是平滑的轨迹。排查方法很简单从训练集里随机抽一批动作数据过一遍动作编码器解码然后把重建动作和原始动作画在同一张图上逐个维度检查误差。如果发现某个维度比如手腕旋转角度、夹爪开合度的误差显著大于其他维度不要急着调LLM先优化VAE那边的loss权重或者给那个维度单独增加重建损失权重。5.3 模型在训练环境很猛换一个背景就崩这个问题可以追溯到视觉编码器过拟合到背景特征。解决方法有两个方向。第一个方向是在数据组织阶段做视觉扰动比如随机改变亮度、随机裁剪、随机遮挡让模型必须依靠物体本身的几何特征而不是背景色块来做动作决策。第二个方向是在指令微调阶段刻意在部分样本里把物体和背景做组合重组比如仿真渲染的时候随机换桌面纹理强迫模型把视觉特征和动作逻辑解耦。如果条件不允许重新生成数据可以用一种“注意力引导”的排查法把模型在某个样本上的注意力图拿出来看它在生成动作token时注意力到底是集中在物体轮廓附近还是集中在背景某个角落。如果是后者那基本可以确定模型学了一个背景捷径。5.4 推理延迟过高实机控制跟不上机器人控制对延迟极其敏感。如果模型自回归生成动作token太慢控制频率跟不上整个策略就没法部署。一个常见的优化点是用“粗预测精修正”两段式先让模型以较快的速度生成一批低精度的动作草图token再在一个轻量解码器里做高精度的局部修正。另一个优化方向是缓存视觉特征。因为在一段连续的任务里相邻几个控制周期之间的图像变化通常不大不需要每帧都重新过一遍视觉编码器。每10帧或者20帧更新一次视觉特征中间的时间步直接复用缓存配合动作token的自回归预测可以把端到端延迟压到可接受范围内。6. 这个思路还能往外扩展到哪里视觉-动作指令微调这个思路不只是个“机械臂抓取任务专用”的小技巧。我个人的看法是它给了一类通用问题的解法当一个高能力的多模态模型需要接入一个低维度的连续控制量时与其在模型外面加一堆任务头不如先把控制量token化然后再用指令模板把它和观测输入一起“讲给”模型听。顺着这个思路我可以想到几个很有潜力的扩展方向。第一个是操作多个机器人的协同任务把每个机械臂的动作都编码成独立的token流模型可以交错预测两台机械臂的动作。第二个是移动机器人底盘的导航决策把线速度和角速度压成潜在动作token让模型基于第一视角图像预测下一步移动。第三个是智能体的工具使用模拟把鼠标移动和点击还原成token流让模型通过阅读屏幕截图来控制光标这其实和很多自动化脚本项目的底层逻辑是相通的。我自己目前在一套桌面整理演示数据上尝试了类似的做法最明显的变化不是单次准确率提升而是模型对“同样场景不同起始位置”的适应性变好了。以前动作头回归出来的轨迹像是背答案现在更像是在“看情况做决策”。虽然离真正的通用机器人策略还很远但至少这条路踩上去是实的。读这类论文我的建议是带着“它改变了什么接口关系”这个问题去读而不是只盯着准确率数字。LLARVA这类视觉-动作指令微调的核心其实就是把“视觉输入到动作输出”这件事从一个回归问题平移到了语言模型的token预测框架里。想通这一点剩下的网络结构和训练技巧都能按自己的资源条件做取舍。
阅读完成 · 觉得有帮助?
咨询建站