转载自公众号:敢敢AUTOHUB
1. 引言:机器人视觉感知的根本性挑战
在人工智能与机器人技术快速发展的今天,视觉-语言-动作(Vision-Language-Action, VLA)模型正在引领机器人走向更通用、更智能的新时代。这些模型能够理解自然语言指令,感知视觉场景,并输出可执行的机器人动作。然而,在这些看似强大的模型背后,一个根本性的问题逐渐浮出水面:机器人真的"看准"了吗?
当我们给机器人下达指令,例如"把蓝色积木放到粉色积木上",模型必须将视觉焦点精确锁定在"蓝色积木"这个目标物体上。然而,大量实证研究表明,现有的VLA模型往往难以做到这一点。它们的视觉注意力就像一层"雾气"平均分布在整张图像上,而非像"聚光灯"一样精准打在目标物体上。特别是在背景杂乱、存在多个干扰物的复杂场景中,这种注意力分散现象会导致机器人抓取错误的物体,最终造成任务失败。这不仅影响了机器人的操作精度,也限制了其在真实世界场景中的应用潜力。
论文链接: https://arxiv.org/abs/2508.10333
代码链接: https://github.com/Chowzy069/Reconvla
2. 现有方法的局限性分析
在深入了解ReconVLA之前,我们需要理解现有视觉定位(Visual Grounding)方法的局限性。目前主流的方法可以分为三大类:
2.1 显式定位(Explicit Grounding)
这是最直观的方法。研究者引入额外的 "定位专家"模型,如Grounding DINO或YOLO等目标检测器,先从图像中精确定位目标物体并将其裁剪出来,然后将原始图像和裁剪后的目标图像一起输入到VLA模型中。例如,RoboGround使用LISA作为高级分割器来提取目标物体和背景,VIP则使用YOLOv11进行目标分割并放大后提供给策略网络。
这种方法虽然在一定程度上有效,但存在明显的缺陷:它严重依赖外部专家模型的准确性,增加了系统的复杂度和计算开销。更重要的是,这种方法并没有从根本上提升VLA模型自身的视觉定位能力,模型本身仍然不知道如何"看准"目标。
2.2 思维链定位(Chain-of-Thought Grounding)
受到大语言模型思维链推理的启发,研究者让VLA模型在输出动作之前,先输出目标物体的边界框(Bounding Box)坐标。这种方法试图让模型在执行动作前明确知道目标物体的位置。ECoT和GraspVLA采用了这种链式思维方式,通过顺序输出边界框和动作,同时训练定位能力。
然而,这种方法面临一个技术难题:让模型直接回归精确的坐标数值是极其困难的。神经网络在预测连续数值方面本身就存在挑战,加上视觉场景的复杂性和多样性,这种方法往往导致性能不佳,在实际应用中的成功率较低。
2.3 隐式定位的创新思路
ReconVLA提出了第三种范式——隐式定位(Implicit Grounding)。这种方法不要求模型输出任何额外的坐标或裁剪图像,而是设计了一个巧妙的辅助任务:让模型在输出动作的同时,其内部的视觉特征必须能够**"重建"出目标物体的图像区域**。
三种定位范式对比
3. ReconVLA核心架构详解
ReconVLA的整体架构由两个协同工作的分支组成:视觉重建分支和动作预测分支。这种双分支设计是其创新的核心所在。
ReconVLA架构图
3.1 输入处理阶段
模型接收三类输入信息:多视角相机图像、自然语言指令以及机器人本体状态。这些多模态信息首先被编码成统一的表征空间。具体来说,视觉编码器(采用SigLIP-SO400M)将图像转换为视觉token,而文本编码器将自然语言指令转换为文本token。这些token随后被送入大型语言模型(LLM)主干网络进行融合处理。
在实现上,ReconVLA基于预训练的LLaVA-7B模型构建,使用Qwen2-7B作为LLM骨干。这种设计充分利用了大规模预训练模型的语言理解能力和视觉-语言对齐能力。
3.2 动作预测分支:将连续动作转换为离散token
在动作预测分支中,模型需要将机器人的连续动作空间(如关节角度、末端位置等)转换为离散的token,这样才能被语言模型处理。想象一下,机器人的手臂可以移动到无限多个位置,但我们需要把这些连续的位置 **"量化"**成有限的几个档位,就像把温度计上的连续刻度简化为"冷、温、热"三个等级一样。
ReconVLA使用了一个叫做ActionTokenizer的组件来完成这个转换。它将每个动作维度(比如X轴位置、Y轴位置、抓取器开合度等)划分为256个离散的"箱子"(bins),然后把连续的动作值映射到最接近的箱子编号。这个编号就成为了动作token,可以像文字一样被语言模型处理。
# 来自 reconvla/action_tokenizer.py
class ActionTokenizer:
def __init__(self, tokenizer, bins=256, min_action=-1, max_action=1):
"""
将连续的机器人动作离散化为N个bins,并映射到词表中最少使用的token
参数:
- tokenizer: 基础的LLM分词器
- bins: 每个连续值的离散化箱数,默认256
- min_action: 动作的最小值(用于裁剪和设置bin区间下界)
- max_action: 动作的最大值(用于裁剪和设置bin区间上界)
"""
self.n_bins = bins
self.min_action = min_action
self.max_action = max_action
# 创建均匀的bins并计算每个bin的中心值
self.bins = np.linspace(min_action, max_action, bins + 1)
self.bin_centers = (self.bins[:-1] + self.bins[1:]) / 2.0
# 动作token从词表的末尾开始分配
self.action_token_begin_idx = tokenizer.vocab_size - (bins + 1)
def __call__(self, action):
"""将连续动作裁剪并离散化为词表末尾的token"""
# 先将动作值裁剪到[min_action, max_action]范围内
action = np.clip(action, self.min_action, self.max_action)
# 使用digitize找到每个动作值应该放入哪个bin
discretized_action = np.digitize(action, self.bins)
# 转换为实际的token ID
action_token_ids = self.tokenizer.vocab_size - discretized_action
return action_token_ids
这种设计的巧妙之处在于:它利用了词表末尾那些很少被使用的token,避免与正常的文本token冲突。当模型生成动作时,就像在"说话"一样,只不过说出的是代表机器人动作的特殊"词汇"。
动作生成采用自回归方式,即每个动作token的生成都依赖于之前已经生成的token。这就像写句子时,后面的词要根据前面的词来决定一样。这种方式使得模型能够生成连贯、符合物理规律的动作序列。
动作生成的数学表达式为:
其中 表示第 个动作token, 和 分别是图像token和文本token, 是动作序列的总长度。
3.3 视觉重建分支:让模型学会"看准"
视觉重建分支是ReconVLA的核心创新点,也是它能够精准定位目标的关键所在。这个分支的设计理念非常巧妙:不是直接告诉模型"你应该看哪里",而是通过一个重建任务,让模型自己学会把注意力放在正确的地方。
打个比方,这就像教小孩认识物体。与其直接指着苹果说"看这里",不如让孩子画出苹果的样子。为了画得像,孩子必须仔细观察苹果的形状、颜色、纹理等细节。同样,ReconVLA要求模型**"重建"目标物体的图像**,为了完成这个任务,模型必须学会精确地关注目标区域。
具体实现分为三个关键步骤:
步骤1: 视觉token化——将图像压缩为潜在表示
首先,系统使用一个预训练的变分自编码器(VAE)将 "凝视区域"(也就是需要操作的目标物体图像)编码为低维的潜在token。这个VAE来自Stable Diffusion模型,它能够将一张图像压缩成一组数字向量,同时保留图像的关键视觉信息。
想象一下,原始图像可能是256×256像素,包含65536个像素点。但VAE可以将其压缩为32×32的潜在表示,只有1024个数值,大大减少了数据量,同时保留了图像的核心特征。这就像把一本厚书浓缩成摘要,虽然字数少了,但关键信息都在。
# 视觉tokenizer将凝视区域编码为潜在token
# VAE编码器将图像从像素空间映射到潜在空间
z_0 = VAE_encoder(gaze_region_image) # 输入: [B, 3, H, W] -> 输出: [B, C, h, w]
# 其中B是批次大小,C是潜在通道数,h和w是压缩后的空间维度
步骤2: 重建token生成——模型的"视觉理解"输出
主干网络(基于Qwen2-7B的大语言模型)在处理完图像和文本输入后,除了输出动作token,还会额外输出一组**"重建token" h_R**。这些token包含了模型对目标区域的理解和表征,它们将作为下一步重建过程的**"指导信号"**。
可以把重建token理解为模型的**"内心独白"**——它在告诉重建网络:"我看到的目标物体应该长这样"。这些token的质量直接决定了重建的效果,而为了生成高质量的重建token,模型必须真正"看懂"目标物体。
步骤3: 扩散去噪重建——从噪声中恢复清晰图像
最后一步使用扩散模型的去噪过程。系统先在潜在表示z_0上添加高斯噪声,得到噪声版本z_t,然后训练一个去噪网络,在重建token h_R的指导下,将z_t恢复为z_0。
这个过程就像在雾中辨认物体。一开始图像被噪声完全覆盖,什么都看不清。但去噪网络根据重建token提供的"线索",一步步去除噪声,最终恢复出清晰的目标物体图像。关键在于,只有当模型真正理解了目标物体的特征,才能生成有效的重建token,进而成功完成去噪重建。
扩散去噪的损失函数定义为:
其中:
- • , 是添加的高斯噪声• 是扩散时间步(控制噪声强度)• 是去噪网络• 是模型输出的重建token(条件信号)
# 来自 reconvla/recon/model/recon_arch.py 的扩散去噪实现
class DiffusionDenoiser(nn.Module):
def __init__(self, hidden_dim=768, num_layers=6):
super().__init__()
self.transformer_blocks = nn.ModuleList([
TransformerBlock(hidden_dim) for _ in range(num_layers)
])
self.time_embedding = nn.Sequential(
nn.Linear(hidden_dim, hidden_dim * 4),
nn.SiLU(),
nn.Linear(hidden_dim * 4, hidden_dim)
)
def forward(self, z_t, h_R, t):
"""
参数:
z_t: 噪声潜在表示 [B, N, D]
h_R: 重建token条件 [B, M, D]
t: 时间步 [B]
返回:
预测的噪声 [B, N, D]
"""
# 时间步嵌入
t_emb = self.time_embedding(t)
# 拼接噪声token和条件token
x = torch.cat([z_t, h_R], dim=1)
# Transformer处理
for block in self.transformer_blocks:
x = block(x, t_emb)
# 提取去噪后的token(只取前N个,对应z_t的部分)
noise_pred = x[:, :z_t.shape[1], :]
return noise_pred
这个损失函数的作用是:让去噪网络学会根据重建token,准确预测出添加在 上的噪声。如果预测准确,就能通过 恢复出原始的 。而为了让 包含足够的信息来指导去噪,主干网络必须从输入图像中提取目标物体的精细特征,这自然而然地引导模型将注意力聚焦到目标区域。
3.4 联合训练策略:动作预测与视觉重建的协同优化
ReconVLA的训练过程同时优化两个目标:一个是让模型生成正确的动作,另一个是让模型重建目标区域的图像。这两个任务看似独立,实际上相互促进,形成了一个巧妙的协同机制。
总体训练目标结合了动作预测损失和视觉重建损失:
其中:
- • : 动作预测的交叉熵损失,确保生成正确的动作token• : 视觉重建的均方误差损失,确保能重建目标区域
# 来自 reconvla/train_vla.py 的训练循环
def training_step(model, batch):
"""
ReconVLA的训练步骤
"""
images = batch['images'] # 原始图像
gaze_regions = batch['gaze_regions'] # 凝视区域图像
instructions = batch['instructions'] # 语言指令
actions = batch['actions'] # 动作标签
# 前向传播
outputs = model(
images=images,
instructions=instructions,
gaze_regions=gaze_regions
)
# 计算动作预测损失
action_logits = outputs.action_logits
L_action = F.cross_entropy(
action_logits.view(-1, action_logits.size(-1)),
actions.view(-1)
)
# 计算视觉重建损失
reconstructive_tokens = outputs.reconstructive_tokens
target_latents = outputs.target_latents
L_visual = diffusion_loss(
reconstructive_tokens,
target_latents
)
# 总损失
L_total = L_action + L_visual
return L_total
这种联合训练的精妙之处在于:为了最小化视觉重建损失,语言模型必须从输入图像中提取关于目标物体最精细、最准确的视觉信息,并将其编码到重建token 中。而这个过程会自然地引导模型的注意力机制聚焦到目标区域,因为只有关注正确的区域,才能提取到足够的信息来完成重建任务。
可以这样理解:如果模型的注意力分散在整张图上,它提取的信息就会很模糊,无法生成高质量的重建token,重建损失就会很大。只有当模型像聚光灯一样精准地照在目标物体上,提取到清晰的特征,才能生成有效的重建token,完成重建任务,降低损失。因此,重建任务成为了一种隐式的监督信号,引导模型学会正确的视觉注意力分配。
同时,动作预测任务确保模型不会只关注重建而忽略了最终目标——生成正确的机器人动作。两个任务的梯度会同时回传到主干网络,共同塑造模型的参数,使其既能精准感知目标,又能准确输出动作。
Token排列的特殊设计
值得注意的是,在训练过程中,研究团队采用了一种特殊的token排列方式:将指令token放在图像token之前。这种设计确保了图像token能够通过因果注意力机制"看到"指令信息,从而知道应该关注图像中的哪个物体。
# Token序列排列方式
# 传统方式: [图像tokens] [指令tokens] [动作tokens]
# ReconVLA方式: [指令tokens] [图像tokens] [动作tokens] [重建tokens]
# 这样图像tokens在处理时就能融合指令信息
# 确保模型关注的是指令指定的目标物体
这种交错格式通过因果注意力机制,让图像token能够融合来自指令的信息,确保VLA模型处理的视觉token确实对应于指令所指定的目标,而不是图像中的其他物体。
4. 大规模预训练:泛化能力的基石
现有VLA模型的视觉重建能力天然受限,因为它们的基础模型(VLM)主要是在"看图说话"类的任务上训练的,并没有学过如何"画图"。就像一个只学过阅读理解的学生,突然要求他画画,肯定画不好。为了让ReconVLA具备强大的视觉重建能力,研究团队专门构建了一个大规模的预训练数据集,让模型从零开始学习如何重建目标物体的图像。
4.1 数据集构建:整合多源机器人数据
预训练数据集整合了三个大型开源机器人数据集,每个数据集都有其独特的价值:
BridgeData V2: 这是一个真实世界机器人操作数据集,包含了真实机器人在各种家庭和办公场景中执行任务的视频。这些数据的价值在于"真实性"——真实的光照、真实的物体纹理、真实的背景杂乱度,这些都是仿真环境难以完美复现的。通过在真实数据上训练,模型能够学会处理真实世界的复杂性。
LIBERO: 这是一个高质量的仿真数据集,在MuJoCo物理引擎中生成。虽然是仿真数据,但LIBERO的场景设计非常精心,物体种类丰富,任务多样化。仿真数据的优势是可以大规模生成,成本低,而且可以精确控制各种变量,比如物体位置、光照条件等。
CALVIN: 这是一个专门为长时序任务设计的仿真数据集,包含需要连续完成多个子任务的复杂操作。比如"打开抽屉,拿出物体,放到桌上,再关上抽屉"这样的任务序列。这类数据帮助模型学习任务规划和子目标切换能力。
最终数据集的规模达到:
超过10万条交互轨迹: 每条轨迹是一个完整的任务执行过程,包含从开始到结束的所有观测和动作
约200万个数据样本: 每个样本是一个(图像,指令,动作,凝视区域)的四元组
涵盖多样化的场景和物体: 从厨房到办公室,从积木到餐具,物体种类超过1000种
这个规模在机器人领域已经相当可观。要知道,收集真实机器人数据的成本非常高,每小时的数据采集可能需要数千美元的设备和人力成本。
4.2 自动化标注流程:让机器给机器打标签
有了原始数据还不够,ReconVLA需要知道每张图像中的"凝视区域"在哪里——也就是机器人应该关注和操作的目标物体。如果靠人工标注,200万张图像的工作量是天文数字。因此,研究团队设计了一套巧妙的自动化标注流程,让计算机自己完成这项工作。
整个流程分为三个步骤,每一步都有明确的输入输出:
步骤1: 从原始数据中提取任务片段
原始的机器人数据集通常是长视频,包含多个任务的连续执行。第一步需要把这些长视频切分成独立的任务片段,每个片段对应一个完整的操作任务。
# 步骤1: 从CALVIN数据集提取任务
python ./scripts/helper/calvin_extract_task.py \
--ann_path /path/to/auto_lang_ann.npy \ # 语言标注文件
--npz_src_dir /path/to/training/ \ # 原始数据目录
--root_folder /output/path/ # 输出目录
# 这个脚本会做什么?
# 1. 读取语言标注文件,获取每个任务的描述和时间范围
# 2. 从原始视频中提取对应时间段的图像帧
# 3. 按任务组织数据,每个任务一个文件夹
执行后,数据会被组织成这样的结构:
output_folder/
├── 0_pick_up_blue_block/ # 任务0: 拿起蓝色积木
│ ├── lang_ann/
│ │ └── lang_ann.yaml # 任务描述和帧索引
│ └── img/
│ ├── frame_0000000.png # 第0帧图像
│ ├── frame_0000001.png # 第1帧图像
│ └── ...
├── 1_place_block_on_pink/ # 任务1: 把积木放到粉色积木上
│ └── ...
这一步的关键是将连续的数据流切分成有意义的任务单元,为后续处理做准备。
步骤2: 使用目标检测模型自动分割凝视区域
这是整个流程中最关键的一步。研究团队使用了Grounding DINO这个强大的开放词汇目标检测模型。Grounding DINO的特点是可以根据文本描述(比如"蓝色积木")在图像中找到对应的物体,并给出精确的边界框。
但是,原始的Grounding DINO是在通用图像数据集上训练的,对机器人操作场景的理解不够精准。因此,研究团队先在机器人数据上对其进行了微调,让它更擅长识别机器人任务中的目标物体。
# 步骤2的伪代码(实际实现在crop.py中)
for each_task in extracted_tasks:
instruction = task.language_annotation # 例如: "pick up the blue block"
for each_frame in task.images:
# 使用微调后的Grounding DINO检测目标物体
bounding_box = grounding_dino.detect(
image=each_frame,
text_prompt=instruction
)
# 根据边界框裁剪出凝视区域
gaze_region = crop_image(each_frame, bounding_box)
# 保存裁剪后的图像
save_image(gaze_region, f"crop/frame_{i}.png")
这一步的输出是每张原始图像对应的凝视区域图像。比如原图是整个桌面场景,凝视区域图像就只包含蓝色积木这个目标物体。
步骤3: 生成训练用的JSON配置文件
最后一步是将所有数据整理成模型训练需要的格式。这个脚本会生成一个JSON文件,记录每个训练样本的信息:原始图像路径、凝视区域图像路径、语言指令、机器人动作等。
# 步骤3: 生成训练用的JSON文件
python ./scripts/helper/calvin_json.py \
--calvin_original_data_path /path/to/original/calvin/ \
--calvin_crop_data_path /path/to/extracted/tasks/ \
--calvin_processed_directory /path/to/processed/images/ \
--calvin_processed_json_path /path/to/output.json
# 生成的JSON格式示例:
# {
# "samples": [
# {
# "image": "/path/to/frame_0000000.png", # 原始图像
# "gaze_region": "/path/to/crop/frame_0000000.png", # 凝视区域
# "instruction": "pick up the blue block", # 语言指令
# "action": [0.1, 0.2, -0.3, 0.0, 0.0, 0.0, 1.0], # 机器人动作
# "robot_obs": [...] # 机器人状态
# },
# ...
# ]
# }
这个JSON文件就是训练时的"菜单",告诉模型每个样本包含哪些信息,从哪里读取。有了这个文件,训练脚本就可以自动加载数据,无需人工干预。
整个自动化流程的优势在于:
可扩展性: 一旦流程搭建好,处理100万张图像和处理1000张图像的人力成本几乎相同
一致性: 机器标注的标准是统一的,不会像人工标注那样因为疲劳或主观判断产生不一致
成本效益: 相比人工标注每张图像可能需要几十秒,自动化流程每张图像只需几毫秒
# 步骤3: 生成训练用的JSON文件
python ./scripts/helper/calvin_json.py \
--calvin_original_data_path /path/to/original/calvin/ \
--calvin_crop_data_path /path/to/extracted/tasks/ \
--calvin_processed_directory /path/to/processed/images/ \
--calvin_processed_json_path /path/to/output.json
最终生成的数据格式包含原始图像和对应的凝视区域图像对,为模型提供了丰富的视觉重建监督信号。
4.3 预训练的重要性:数据规模带来质的飞跃
为什么要花这么大力气构建预训练数据集?消融实验给出了明确的答案。研究团队对比了有预训练和无预训练两种情况下模型的性能,结果令人印象深刻。
在CALVIN ABC→D任务上的对比结果显示:
| 配置 | 1/5任务成功率 | 5/5任务成功率 | 平均长度 |
|---|---|---|---|
| 无预训练 | 89.8% | 46.5% | 3.42 |
| 有预训练 | 95.6% | 64.1% | 3.95 |
这些数字背后的含义是什么?让我们详细解读:
首任务成功率提升5.8个百分点: 从89.8%到95.6%,看似提升不大,但要知道在接近90%的高基准上再提升是非常困难的。这意味着模型在面对第一个任务时,几乎总能找到正确的目标并成功操作。
五任务连续成功率提升17.6个百分点: 这是最关键的指标。从46.5%到64.1%,提升幅度达到38%!这说明预训练显著增强了模型在长时序任务中的稳定性。要连续完成5个子任务,模型需要在每个阶段都准确定位目标、规划动作、执行操作,任何一个环节出错都会导致整个任务链断裂。预训练让模型学会了更鲁棒的视觉感知和动作生成能力。
平均完成长度提升0.53: 从3.42到3.95,意味着模型平均能多完成半个任务。在长时序任务中,这个提升非常可观。
为什么预训练如此有效?
预训练的作用可以从三个层面理解:
视觉重建能力的通用化: 预训练让模型在大量不同场景、不同物体上练习重建任务,学会了提取通用的视觉特征。就像学画画,画过100种物体的人,再画第101种物体时会更得心应手。
注意力机制的强化: 通过反复练习"找到目标-重建目标"这个过程,模型的注意力分配机制得到了充分训练,形成了稳定的"聚焦"模式。
泛化能力的提升: 预训练数据的多样性使模型见过各种各样的场景和物体,当遇到新任务时,即使物体从未见过,模型也能根据其视觉特征(形状、颜色、纹理等)进行合理的推断。
这就是为什么研究团队强调"大规模预训练是泛化能力的基石"。没有预训练,模型就像一个只在课本上学过理论的学生;有了预训练,模型就像经历过大量实战训练的老手,面对新情况时更加从容。
5. 实践指南:如何使用ReconVLA
对于希望使用或改进ReconVLA的研究者和开发者,这里提供一个详细的上手指南。我们会从环境配置开始,一步步讲解如何训练和评估模型。
5.1 环境配置:搭建开发环境
首先需要准备Python环境和必要的依赖库。ReconVLA基于PyTorch深度学习框架,需要CUDA支持的GPU。
# 第1步: 克隆代码仓库
git clone <https://github.com/Chowzy069/Reconvla.git>
cd ReconVLA
# 第2步: 创建独立的conda环境
# 使用conda可以避免与系统其他Python包冲突
conda create -n reconvla python=3.10.16
conda activate reconvla
# 第3步: 安装依赖包
# recon_requirements.txt包含了所有需要的Python库
pip install -r recon_requirements.txt
# 第4步: 进入代码目录
cd reconvla
环境要求说明:
Python 3.10.16: 这个版本经过充分测试,兼容性最好•
CUDA 11.8+: 用于GPU加速,训练大模型必需•
至少80GB GPU显存: 推荐使用A100或H100 GPU•
500GB以上磁盘空间: 用于存储数据集和模型权重
如果你的GPU显存不足,可以通过减小批次大小、使用梯度累积等技术来适配,但训练速度会变慢。
5.2 数据准备:从原始数据到训练样本
数据准备是最耗时的步骤,但也是最重要的。高质量的数据是模型性能的基础。
下载公开数据集:
需要下载三个数据集,每个都有几十到几百GB:
BridgeData V2: 访问 https://rail.eecs.berkeley.edu/datasets/bridge_release/data/•
LIBERO: 访问 https://libero-project.github.io/datasets•
CALVIN: 访问 https://github.com/mees/calvin
下载后,将数据解压到合适的目录,比如 /data/robot_datasets/
数据预处理流程:
# 步骤1: 提取任务片段
# 这一步会将长视频切分成独立的任务
python ./scripts/helper/calvin_extract_task.py \
--ann_path /data/robot_datasets/calvin/auto_lang_ann.npy \
--npz_src_dir /data/robot_datasets/calvin/training/ \
--root_folder /data/processed/calvin_tasks/
# 执行时间: 约2-3小时(取决于数据量)
# 输出: 按任务组织的图像和标注文件
# 步骤2: 生成凝视区域
# 这一步使用Grounding DINO自动标注目标物体
# 详细说明参考: reconvla/scripts/helper/Readme.md
# 需要先下载Grounding DINO预训练权重
wget <https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth>
# 运行裁剪脚本
python ./scripts/helper/crop.py \
--input_dir /data/processed/calvin_tasks/ \
--output_dir /data/processed/calvin_crops/ \
--model_path groundingdino_swint_ogc.pth
# 执行时间: 约4-6小时
# 输出: 每张原图对应的凝视区域图像
# 步骤3: 生成训练配置JSON
# 这一步整合所有信息,生成模型可以直接读取的配置文件
python ./scripts/helper/calvin_json.py \
--calvin_original_data_path /data/robot_datasets/calvin/ \
--calvin_crop_data_path /data/processed/calvin_tasks/ \
--calvin_processed_directory /data/processed/calvin_images/ \
--calvin_processed_json_path /data/processed/calvin_train.json
# 执行时间: 约30分钟
# 输出: 包含所有训练样本信息的JSON文件
完成这三步后,你会得到一个结构化的数据集,包含原始图像、凝视区域图像、语言指令和动作标签,可以直接用于训练。
5.3 模型训练:从预训练到微调
ReconVLA的训练分为两个阶段:预训练和微调。预训练在大规模混合数据集上进行,学习通用的视觉重建能力;微调在特定任务数据上进行,适配具体的操作场景。
预训练阶段:
预训练需要强大的计算资源。标准配置是8张A100 GPU,每张80GB显存。
# 启动预训练
bash scripts/train_vla/pretrain.sh
# pretrain.sh脚本的核心内容:
# #!/bin/bash
#
# # 设置分布式训练参数
# export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 # 使用8张GPU
# export MASTER_PORT=29500
#
# # 启动训练
# torchrun --nproc_per_node=8 --master_port=$MASTER_PORT train_vla.py \
# --model_name_or_path lmms-lab/llava-onevision-qwen2-7b-ov \
# --data_path /data/processed/pretrain_data.json \
# --image_folder /data/processed/images \
# --target_image_folder /data/processed/gaze_regions \
# --mm_pixel_decoder flux1-dev-fp8-flux/vae \
# --action_stat /data/processed/action_stats.json \
# --per_device_train_batch_size 4 \
# --gradient_accumulation_steps 4 \
# --num_train_epochs 3 \
# --learning_rate 2e-5 \
# --use_diffusion_head True \
# --output_dir ./checkpoints/reconvla_pretrain
关键训练参数解释:
model_name_or_path: 基础VLM模型,这里使用LLaVA-OneVision•
data_path: 训练数据的JSON配置文件•
mm_pixel_decoder: VAE模型路径,用于图像编码•
per_device_train_batch_size: 每张GPU的批次大小,设为4•
gradient_accumulation_steps: 梯度累积步数,设为4•
use_diffusion_head: 启用扩散去噪头,这是ReconVLA的核心
全局批次大小计算:
全局批次 = 每GPU批次 × 梯度累积 × GPU数量
= 4 × 4 × 8 = 128
这个批次大小经过精心调优,既能保证训练稳定性,又能充分利用GPU资源。
预训练时间: 在8×A100上,完整预训练需要约5-7天。
微调阶段:
预训练完成后,需要在特定任务数据上进行微调,让模型适配目标环境。
# 启动微调
bash scripts/train_vla/finetune.sh
# finetune.sh的核心参数:
# torchrun --nproc_per_node=8 train_vla.py \
# --model_name_or_path ./checkpoints/reconvla_pretrain \ # 加载预训练权重
# --data_path /data/calvin/finetune_data.json \
# --per_device_train_batch_size 4 \
# --num_train_epochs 10 \
# --learning_rate 1e-5 \ # 微调时学习率要小一些
# --output_dir ./checkpoints/reconvla_finetune
微调时间较短,通常1-2天即可完成。
资源受限时的调整策略:
如果你只有4张GPU或更少,可以这样调整:
# 4张GPU的配置
per_device_train_batch_size=2 # 减小批次
gradient_accumulation_steps=8 # 增加累积步数
# 全局批次 = 2 × 8 × 4 = 64 (减半,但仍可接受)
# 2张GPU的配置
per_device_train_batch_size=1
gradient_accumulation_steps=16
# 全局批次 = 1 × 16 × 2 = 32 (训练会变慢,但仍可行)
关键是保持全局批次大小尽可能接近原始设置,这样训练效果才不会下降太多。
5.4 模型评估:测试性能
训练完成后,需要在测试集上评估模型性能。ReconVLA采用客户端-服务器架构,支持并行评估。
启动推理服务器 (终端1):
# 激活环境
conda activate reconvla
cd reconvla/reconvla
# 启动多服务器推理
bash scripts/test_vla/start_multi_server.sh
# 这个脚本会启动多个推理进程,每个处理一部分任务
# 关键参数:
# --model_path ./checkpoints/reconvla_finetune # 模型路径
# --num_chunks 8 # 将任务分成8块并行处理
# --save_dir ./results # 结果保存目录
启动评估服务器 (终端2):
# 切换到CALVIN环境
conda activate calvin_venv
cd reconvla/calvin/calvin_agent/evaluation
# 启动评估
bash evaluate_policy_multiserver.sh
# 这个脚本会:
# 1. 连接到推理服务器
# 2. 在CALVIN仿真环境中执行任务
# 3. 记录成功率和完成长度
# 4. 生成评估报告
评估过程会运行500个测试回合,每个回合尝试连续完成5个子任务。整个评估大约需要2-3小时。
评估结果解读:
评估完成后,会生成类似这样的报告:
CALVIN ABC→D Evaluation Results:
================================
Task 1/5 Success Rate: 95.6%
Task 2/5 Success Rate: 87.6%
Task 3/5 Success Rate: 76.9%
Task 4/5 Success Rate: 69.3%
Task 5/5 Success Rate: 64.1%
Average Length: 3.95
Top Failed Tasks:
1. "rotate_red_block_right" - 12 failures
2. "place_in_drawer" - 8 failures
3. "stack_block" - 6 failures
这些数据告诉你:
- • 模型在简单任务上表现优秀(95.6%)• 长序列任务的成功率随任务数增加而下降(这是正常的)• 平均能完成接近4个连续任务• 可以针对失败率高的任务进行针对性改进
5.5 使用预训练模型:快速开始
如果你不想从头训练,可以直接使用研究团队提供的预训练权重:
# 方法1: 使用Hugging Face CLI下载
pip install huggingface_hub
huggingface-cli download zzyzyzy/ReconVLA --local-dir ./pretrained_models/
# 方法2: 使用Python代码下载
from huggingface_hub import snapshot_download
snapshot_download(
repo_id="zzyzyzy/ReconVLA",
local_dir="./pretrained_models/"
)
# 方法3: 手动下载
# 访问 <https://huggingface.co/zzyzyzy/ReconVLA>
# 下载所有模型文件到本地目录
使用预训练模型的好处:
节省时间: 跳过5-7天的预训练过程
节省成本: 不需要8×A100的昂贵算力
快速验证: 可以直接在你的任务上微调,快速看到效果
加载预训练模型进行微调:
# 在train_vla.py中指定预训练权重路径
model_args.model_name_or_path = "./pretrained_models/ReconVLA"
# 然后正常运行微调脚本
bash scripts/train_vla/finetune.sh
6. 结论
ReconVLA通过引入重建式隐式视觉定位范式,从根本上解决了现有VLA模型在视觉注意力分配上的核心问题。这项工作的创新不仅仅是技术层面的突破,更重要的是它改变了我们思考机器人视觉感知的方式。
随着预训练数据规模的进一步扩大(比如利用互联网上的人类操作视频),模型架构的持续优化(比如更高效的扩散模型),以及与其他模态的深度融合(比如触觉、力反馈),我们有理由相信,具备精准视觉感知能力的通用机器人将在不久的将来走进千家万户,真正成为人类生活和工作的得力助手。ReconVLA让机器人真正学会了"看准"目标,这是通向通用机器人智能的关键一步。
113