VLA 微调与评测
引言
视觉-语言-动作模型(Vision-Language-Action Model,VLA)的落地涉及数据、模型和控制器三套接口。损失下降只能说明模型正在拟合训练目标;机器人能否完成任务,还取决于动作语义、时序和闭环反馈。本页给出从公开数据到仿真评测的实验流程,基础概念见VLA 模型。
选择可复现的起点
| 实现 | 适合研究的内容 | 接入时的重点 |
|---|---|---|
| OpenVLA | 基于预训练视觉语言模型的动作预测与参数高效微调 | 图像预处理、动作离散化、数据集对应的反归一化统计量 |
| openpi | π₀、π₀-FAST、π₀.₅ 的训练与推理流程 | 对应模型的动作头、状态与相机输入、数据转换和模型配置 |
| robomimic | 从演示学习的对照实验 | 在相同观测、数据划分与控制接口下建立基线 |
openpi 中 π₀ 使用流匹配,π₀-FAST 使用基于 FAST 动作编码的自回归生成;仓库对 π₀.₅ 提供流匹配动作头。它们不能仅通过替换权重路径任意互换,需使用匹配的配置。官方实现说明
选择模型前先确认目标机器人所需的相机数量、状态输入和动作维度。权重公开也不意味着完整预训练数据都可以下载;应分别记录代码、权重和数据的来源与使用条件。
定义观测与动作契约
建议为每个数据集和部署控制器建立同一份接口说明。
| 字段 | 必须说明的语义 | 常见错误 |
|---|---|---|
| 图像 | 相机名称、RGB 顺序、裁剪、缩放、采样时间 | 训练时裁掉背景,部署时却保留整幅图像 |
| 本体状态 | 关节顺序、位置或速度、单位、夹爪状态 | 混用角度与弧度,交换左右臂 |
| 语言指令 | 原始指令、任务标签或生成描述 | 根据最终成功状态补写指令,泄漏未来信息 |
| 平移 | 绝对位置或增量、米或毫米、参考坐标系 | 把末端坐标系增量当作基座坐标系增量 |
| 旋转 | 欧拉角、轴角或四元数及分量顺序 | 将四元数分量当作普通向量直接平均 |
| 夹爪 | 位置目标、开合命令或力控制,开闭方向 | 把连续开度当作二值命令 |
| 时间 | 动作间隔、观测与动作对齐关系 | 把下一时刻图像配给当前动作 |
不同机器人的七维动作,即使形状相同,也可能具有完全不同的含义。应先进行单位与坐标变换,再计算训练统计量;归一化无法修复语义不一致。格式转换流程见开放机器人数据集实践。
从小样本检查到正式微调
数据检查
随机抽取完整 episode,连同图像播放状态和动作曲线,确认停止片段、抓取时刻与夹爪动作一致。训练集与验证集按 episode、场景或采集会话分组划分,不按相邻帧随机拆分。
归一化统计量只从训练划分计算,并随检查点保存。若使用预训练统计量,需要说明其适用的机器人和动作定义;更换数据源后不能凭字段名称沿用。模型需要分位数缩放、均值方差缩放还是其他方式,应按对应实现执行。
小规模过拟合检查
先取少量演示,检查模型能否拟合动作以及推理路径能否正确反归一化。这个步骤用于发现数据错位、掩码错误、被冻结的动作头等问题,不用于报告泛化性能。
对于预测长度为 的动作块,episode 末端不足 步的部分必须明确处理:可以裁掉不完整窗口,或填充后在损失中屏蔽。训练框架如有官方处理方式,应沿用其约定,避免让填充值成为虚假的停止行为。
正式训练
低秩适配(Low-Rank Adaptation,LoRA)可以减少可训练参数,但仍需要保存前向激活,显存需求还受相机数量、图像大小、序列长度、动作块长度和批量大小影响。先测量一个真实训练批次,再决定梯度累积或全参数微调方案。
至少保存以下内容:基础模型版本、数据版本、转换脚本版本、数据划分、归一化参数、优化器配置、随机种子,以及检查点选择规则。验证集用于选择检查点,最终测试集应保持独立。
OpenVLA 的官方仓库包含 LoRA 和数据加载说明;openpi 的官方微调流程则串联数据转换、训练配置、统计量计算、训练和策略服务。命令行接口随版本变化,复现时应固定仓库提交并使用对应文档。OpenVLA 微调入口、openpi 微调入口
训练样本如何组成
设轨迹在时刻 的观测为 ,语言指令为 ,动作块目标为 。模型可以只读取当前观测,也可以读取长度为 的历史:
这里的目标动作必须位于同一个 episode。历史不足、动作块越过末端,以及相机缺失是三类不同的掩码,不宜用一份布尔标记混合处理。将未来动作作为训练标签是正常的监督学习;把未来图像或实际完成结果作为部署时不存在的输入,才会泄漏未来信息。
下面的 NumPy 示例只展示单个 episode 的动作窗口和有效性掩码,不是 OpenVLA 或 openpi 的数据加载器。假定输入动作与观测已经按时间对齐,动作数组形状为 [T, D]。
import numpy as np
def action_window(actions, start, horizon):
actions = np.asarray(actions, dtype=np.float32)
if actions.ndim != 2 or actions.shape[1] == 0:
raise ValueError("actions 必须是 [T, D],且 D 大于 0")
if not np.isfinite(actions).all():
raise ValueError("动作中存在 NaN 或无穷值")
if horizon <= 0 or not 0 <= start < len(actions):
raise ValueError("动作窗口起点或长度无效")
valid = min(horizon, len(actions) - start)
target = np.zeros((horizon, actions.shape[1]), dtype=np.float32)
mask = np.zeros(horizon, dtype=bool)
target[:valid] = actions[start:start + valid]
mask[:valid] = True
return target, mask
actions = np.arange(15, dtype=np.float32).reshape(5, 3)
target, mask = action_window(actions, start=3, horizon=4)
print(target.shape, mask.tolist()) # (4, 3) [True, True, False, False]
对于连续回归动作头,一个按有效标量元素归一化的示例损失为
分母必须非零。若不同机器人还需要屏蔽动作维度,则分子和分母都改为使用 [B, H, D] 的掩码。离散 token、扩散和流匹配模型的实际训练目标不同,应使用各自实现的损失,不能直接套用这一均方误差公式。
用消融实验判断模型学到了什么
大模型成功率提高后,需要进一步确认改进来自预训练、语言信息、更多数据还是更合适的控制设置。下面是一组可以逐步进行的对照实验,不必一次运行全部组合。
| 对照实验 | 保持一致的条件 | 可以回答的问题 |
|---|---|---|
| 简单行为克隆与预训练 VLA | 数据划分、相机、动作接口、评测状态 | 预训练模型在该任务上是否带来实际收益 |
| 完整指令与空指令或打乱指令 | 场景、模型、动作执行方式 | 策略行为是否依赖语言输入 |
| 单相机与多相机 | 数据与训练预算口径 | 遮挡和深度歧义是否限制成功率 |
| 不同执行长度 | 检查点、控制频率、预测长度 | 性能是否主要受开环执行时间影响 |
| 不同演示数量 | 固定验证集和测试集,按组抽取训练数据 | 增加数据是否仍有收益,哪些任务最缺数据 |
| 原场景与单因素扰动 | 同一批任务及初始状态生成规则 | 模型对背景、目标位置或指令改写是否敏感 |
空指令和打乱指令可能产生训练分布之外的输入,因此它们只能提供诊断线索。更直接的语言测试是在同一个可行场景中,给出两条不同且有效的目标指令,检查目标选择是否变化。
比较数据规模时,明确是固定优化步数还是固定训练轮数:固定轮数会让大数据集获得更多参数更新。比较模型时,同时报告闭环结果与算力、训练时间和推理延迟,避免把预算差异解释为算法优势。
动作块不等于实时闭环
设控制周期为 ,模型每次预测 步,只执行前 步后重新观察,其中 。预测范围为 ,重新规划间隔为 。较大的 减少推理调用次数,但也延长了无法利用新观测纠错的时间。
例如控制频率为 20 Hz,预测 16 步、执行 4 步,则预测范围是 0.8 秒,重规划间隔是 0.2 秒。这些数字只是时序示例。异步流水线若要持续供给动作,图像处理、通信和推理的总耗时需要留在可用预算内;同步调用则会额外引入等待时间。
部署日志应记录观测采样、推理开始、推理结束和动作生效的时间。新动作块到达时,需要根据时间戳处理已经过期的动作;发生重置、人工接管或任务切换时,应清空旧队列。不要把上一个 episode 的剩余动作继续发给新场景。
同步与异步执行的选择
同步执行容易调试:采样观测、等待推理、执行 步,再进入下一轮。记录暂停期间控制器是在保持位置还是继续跟踪旧目标,这会影响实际轨迹。异步执行则允许控制器消耗旧动作时,模型预测新的动作块,但需要明确时间基准和队列替换规则。
| 运行时事件 | 建议定义的处理规则 |
|---|---|
| 观测比允许阈值更旧 | 请求新观测,记录拒绝原因,使用控制器约定的备用行为 |
| 新动作块迟到 | 根据时间戳与动作语义决定重新推理或衔接,不能盲目从第一步重播 |
| 动作队列耗尽 | 明确停止、保持目标或受控减速策略;不同动作接口需要不同处理 |
| 动作含非有限值或超出接口范围 | 拒绝该输出,记录原始预测与转换后的值 |
| 重置或人工接管 | 使旧请求失效,同时清空历史缓存和动作队列 |
对增量动作,跳过过期步可能丢失累计位移;对绝对目标,直接切换又可能产生不连续。异步调度不能仅靠截断数组解决,必须结合动作定义、当前状态和控制器的平滑机制验证。策略延迟较大时,先在仿真中注入同样的延迟分布,再评估部署效果。
分层评价策略能力
| 层次 | 记录什么 | 能发现的问题 |
|---|---|---|
| 离线预测 | 各动作分量误差、夹爪判断、异常值比例 | 单位错误、数据错位、某些维度被损失掩盖 |
| 基准闭环 | 每任务成功次数、完成时间、失败阶段 | 误差累积、恢复能力不足、多阶段任务中断 |
| 泛化测试 | 未见物体、位置、背景、指令改写 | 对场景或任务模板的记忆 |
| 运行时测试 | 延迟分位数、超时次数、观测年龄 | 平均推理速度合格但尾部延迟过大 |
比较语言条件策略时,可固定场景、改变指令中的目标,再观察行为是否相应变化。只在每个场景配一条固定指令上测试,无法区分模型是否真正使用语言信息。
选择 LIBERO 或 SimplerEnv 时,记录训练中是否见过相关任务和演示。对公开预训练模型,如果无法审计全部训练数据,应如实说明数据重叠未知,避免将结果称为严格的未见任务泛化。
常见故障排查
| 现象 | 优先检查 |
|---|---|
| 损失下降但机器人始终不动 | 停止片段占比、动作反归一化、控制器死区 |
| 末端持续向反方向运动 | 坐标系、动作正负号、绝对量与增量的区别 |
| 到达目标但夹不住 | 夹爪定义、动作与视频时间偏移、抓取阶段数据覆盖 |
| 训练场景成功,换背景即失败 | 场景划分、相机位置、背景捷径与视觉预处理 |
| 动作块边界抖动 | 队列切换、目标不连续、旧动作与新动作的时间对齐 |
| 单环境正常,并行评测异常 | 批次索引、独立历史状态、局部重置时的缓存清理 |