OpenVLA-OFT-LIBERO进阶实战:自定义任务微调与LIBERO评测避坑指南

原创2026-10-17 19:10:151,844 阅读

OpenVLA-OFT-LIBERO进阶实战:自定义任务微调与LIBERO评测避坑指南

本仓库是 OpenVLA-OFT 视觉-语言-动作(VLA)模型 在 LIBERO-Spatial 基准上的微调权重(checkpoint),约 15GB,可直接用于机器人动作推理与评测。本文将从模型结构、快速推理、自定义任务微调到 LIBERO 评测中最容易踩的 6 个坑,带你完整走通这套"连续动作版 OpenVLA"。

一、OpenVLA-OFT 是什么?为什么值得上手

OpenVLA-OFT(论文:Fine-Tuning Vision-Language-Action Models: Optimizing Speed and Success,arXiv:2502.19645)是对原版 OpenVLA 的微调优化方案,核心改进可以概括为 3 点 🚀:

对比维度 原版 OpenVLA OpenVLA-OFT
动作输出方式 离散 token 逐字解码 连续回归(MLP 头,L1 损失)
推理速度 慢(自回归解码 70 个动作 token) 快 5 倍以上(一次前向出 10 步动作)
LIBERO 成功率 基线 显著提升

一句话理解:OFT 把"机器人动作"从"写作文"变成了"填坐标",既快又稳。本仓库即 LIBERO-Spatial 套件微调后的成品权重。

二、模型构成速览:看懂这份 checkpoint 里装了什么

仓库是一个标准的 HuggingFace 模型目录,核心文件如下(详见 README.md):

文件 作用
model-00001-of-00004.safetensors ~ model-00004-of-00004.safetensors 模型权重,共 4 片,约 15GB,索引见 model.safetensors.index.json
config.json 模型主配置:骨干网络、动作维度、归一化统计等
dataset_statistics.json 动作/本体感知的 q01/q99 归一化统计量
modeling_prismatic.py 模型定义,核心类 OpenVLAForActionPrediction
configuration_prismatic.py 配置类 OpenVLAConfig 定义
processing_prismatic.py 图像/文本处理器 PrismaticProcessor
preprocessor_config.json 图像预处理参数(224×224 双图输入)
tokenizer_config.json Llama 分词器配置

从 config.json 可以读出几个关键超参,建议先记住它们,后面微调与评测全靠对号入座:

  • action_dim: 7 —— 7 维动作:xyz 平移 + 3 维姿态 + 夹爪;
  • num_actions_chunk: 10 —— 每次前向输出未来 10 步动作(action chunk);
  • num_images_in_input: 2 —— 同时输入第三人称相机 + 腕部相机两张图;
  • vision_backbone_id: dinosiglip-vit-so-224px —— DINOv2 + SigLIP 融合双视觉骨干;
  • llm_backbone_id: llama2-7b-pure —— Llama-2-7B 语言骨干;
  • n_action_bins: 256 —— 离散动作 bin 数(仅离散模式使用,OFT 连续模式下由 MLP 头输出);
  • invert_gripper: true —— 夹爪维度方向需翻转(评测时容易忽略的细节)。

三、快速上手教程:5 步生成机器人动作

注意:本仓库只含模型权重,训练/推理代码在 OpenVLA-OFT 官方代码项目中(clone 方式:git clone https://gitcode.com/hf_mirrors/Sakits/openvla-oft-libero 仅拉权重,代码需另配 conda 环境,见官方 README 说明)。

推理管线固定为 5 步加载 + 1 次前向(官方 Quick Start 见 README.md):

cfg = GenerateConfig(
    pretrained_checkpoint="moojink/openvla-7b-oft-finetuned-libero-spatial",
    use_l1_regression=True,   # 关键:MLP 头直接回归连续动作
    use_diffusion=False,      # 不使用扩散头
    use_film=False,           # 不使用 FiLM 噪声动作
    num_images_in_input=2,    # 第三人称 + 腕部双图
    use_proprio=True,         # 注入本体感知 state
    center_crop=True,        # 与训练保持一致的裁剪
    num_open_loop_steps=1,   # 闭环评测时置 1(见坑 3)
    unnorm_key="libero_aggregated",  # 必须与 norm_stats 中的 key 一致!
)
vla = get_vla(cfg)                       # 1. 加载 VLA 主干
processor = get_processor(cfg)           # 2. 加载图像/文本处理器
action_head = get_action_head(cfg, llm_dim=vla.llm_dim)           # 3. 连续动作 MLP 头
proprio_projector = get_proprio_projector(cfg, llm_dim=vla.llm_dim, proprio_dim=PROPRIO_DIM)  # 4. 本体感知投影器
actions = get_vla_action(cfg, vla, processor, obs, obs["task_description"], action_head, proprio_projector)  # 5. 生成动作块

输入 observation 是一个字典,四个键缺一不可:full_image(主视角)、wrist_image(腕部)、state(7 维本体感知)、task_description(英文任务指令)。输出为 (10, 7) 的动作块张量。

四、自定义任务微调:数据格式与归一化统计是命门

想在 LIBERO 之外的新任务(或新套件)上微调,核心只做好两件事 👇

1. 按标准格式组织观测数据

采集数据时保证每条样本包含上述四元组,图像统一为 224×224 输入(处理器使用 resize-naive 策略直接缩放,不做 letterbox,见 preprocessor_config.json)。动作统一为 7 维末端执行器增量 + 夹爪。

2. 为每个数据集计算并注册归一化统计量

OFT 推理时会把模型输出的 -1, 1] 归一化动作,用训练集的 q01/q99 边界反归一化回真实动作空间(实现见 [modeling_prismatic.py)。本仓库只预置了 libero_aggregated 这一份统计量(见 dataset_statistics.json),且第 7 维(夹爪)mask=false 不参与缩放、只做翻转。

微调自定义任务时,必须:

  1. 用官方 compute_stats 类脚本对新数据集统计 q01/q99;
  2. 以新的 key(如 libero_object_no_noops)写入 checkpoint 的 norm_stats;
  3. 推理配置里 unnorm_key 指向新 key。

五、LIBERO 评测避坑指南:6 个常见坑一次讲清

坑 1:unnorm_key 对不上,动作直接"乱飞"

官方 README 示例中写的是 unnorm_key="libero_spatial_no_noops",但本 checkpoint 的 norm_stats 里只有 libero_aggregated(见 config.json)。key 不一致会导致 KeyError 或用错统计量,表现就是机械臂抖动、抓取全失败。

✅ 对策:评测前先 print(cfg.unnorm_key),确认它存在于 norm_stats 字典中。

坑 2:找不到 sample_libero_spatial_observation.pkl

README 示例加载的示例观测文件 experiments/robot/libero/sample_libero_spatial_observation.pkl 位于代码仓库中,而本仓库是纯权重目录,里面没有它。

✅ 对策:从官方代码项目同步该文件,或用自己采集的一条真实观测代替——后者更能暴露环境配置问题。

坑 3:num_open_loop_steps 开环/闭环搞混

Quick Start 为了演示一次打印完整动作块,用的是开环模式(num_open_loop_steps=NUM_ACTIONS_CHUNK,即 10 步不回流新观测)。LIBERO 正式评测必须闭环:每执行 1 步就重新推理,否则累积误差会让成功率大幅缩水。

✅ 对策:评测脚本中固定 num_open_loop_steps=1。

坑 4:显存不够直接 OOM

权重 bf16 约 15GB,FP16 加载加激活开销,24GB 显卡跑闭环评测都很紧张。

✅ 对策:显存 <20GB 时开 load_in_8bit=True 或 load_in_4bit=True(QLoRA 式量化加载),推理精度损失很小,是评测场景性价比最高的选择。

坑 5:图像预处理与训练不一致

模型要求恰好两张 224×224 图(主视角 + 腕部),center_crop、resize-naive 等参数必须与训练对齐。只传一张图、分辨率不对、或 use_proprio 开关与训练不符,都会让成功率"无声地"掉一截。

✅ 对策:逐字对照 preprocessor_config.json 的 input_sizes 和 image_resize_strategy 检查输入管线。

坑 6:忽略夹爪翻转 invert_gripper

本 checkpoint 配置了 invert_gripper: true:训练数据中夹爪是"开=1",部分真实/仿真环境是"开=0"。方向接反的表现是"抓取时松手、该松手时夹紧",非常难排查。

✅ 对策:把推理输出的第 7 维送到环境前,统一做一次 1 - gripper 转换,并在环境端验证一次开/闭爪动作。

六、延伸阅读与关键文件索引

想了解 看这里
模型加载与推理示例 README.md
连续动作反归一化逻辑 modeling_prismatic.py
动作 bin 与词表构造 modeling_prismatic.py
视觉/LLM 骨干映射表 configuration_prismatic.py
双视觉骨干融合加载 modeling_prismatic.py
归一化统计量 dataset_statistics.json

总结:用好 OpenVLA-OFT-LIBERO 的关键在于"三对齐"——归一化 key 对齐、图像预处理对齐、闭环策略对齐。把本文 6 个坑逐一排掉后,你就能在它之上平滑扩展到自定义任务的微调与评测 🎯。

登录后查看全文
openvla-oft-libero