具身操作 Benchmark 深度教程长文版 · 一章一页 · LIBERO · D49

总览 / LIBERO · D49

LIBERO:终身学习的任务注册表

Spatial / Object / Goal / LIBERO-10 / LIBERO-90:知识迁移、遗忘度量与持续学习评测框架全文。

接近原文长文版仅排版加工 · 未删减压缩LIBERO · D49

可以。LIBERO 可以从下面四个维度理解:任务集、引擎与本体、评估指标与分数基线、以及面向评测 harness 的工程优化

先说明一个版本差异:仓库当前代码注册的是 libero_spatiallibero_objectlibero_goallibero_10libero_90;README 将其描述为四个主要套件:Spatial、Object、Goal 和 LIBERO-100。README 中还写有总计 130 个任务,而当前 bddl_files 目录通常对应 10 + 10 + 10 + 10 + 90 的组织方式,即 120 个 BDDL 文件。因此介绍时应以具体 commit 和代码中的 benchmark 注册表为准。


1. 任务集

LIBERO 的核心目标不是单纯测试机器人能否完成某一个动作,而是测试机器人能否在多个任务之间进行知识迁移、任务泛化和持续学习

1.1 LIBERO-Spatial

对应目录:

libero/libero/bddl_files/libero_spatial

大约 10 个任务,重点是空间关系理解。

典型关系包括:

  • next to
  • between
  • front
  • back
  • on
  • in
  • top of
  • under

典型任务:

  • 从桌子中央拿起黑碗并放到盘子上;
  • 从盘子、烤盅或饼干盒附近取出黑碗;
  • 将黑碗从柜子顶部或抽屉中取出;
  • 将目标物放到盘子、炉子或柜子上。

评测重点

它主要测试:

  1. 语言中的空间关系是否被正确理解;
  2. 是否能从多个相似物体中找到满足空间描述的目标;
  3. 机器人是否能根据相对位置规划抓取和放置动作。

1.2 LIBERO-Object

对应目录:

libero/libero/bddl_files/libero_object

大约 10 个任务,操作模式比较统一,主要是:

拿起指定物体,并将其放入篮子。

涉及的物体包括:

  • alphabet soup
  • BBQ sauce
  • butter
  • chocolate pudding
  • cream cheese
  • ketchup
  • milk
  • orange juice
  • salad dressing
  • tomato sauce

评测重点

该任务集控制了任务结构,使变化主要来自物体类别:

  • 识别语言指定的目标物体;
  • 区分外观相似的包装;
  • 将“抓取—移动—放置”策略迁移到新物体;
  • 测试物体类别分布变化下的泛化能力。

1.3 LIBERO-Goal

对应目录:

libero/libero/bddl_files/libero_goal

大约 10 个任务,重点是目标状态和交互状态变化。

任务包括:

  • 打开中间抽屉;
  • 打开顶部抽屉并把碗放入其中;
  • 把盘子推到炉子前面;
  • 把碗放到盘子上;
  • 把碗放到炉子上;
  • 把物体放到柜子顶部;
  • 把奶油奶酪放入碗中;
  • 把酒瓶放到酒架上;
  • 打开炉子。

这类任务不只是检查物体位置,还要检查家具或设备状态。例如:

(And
  (Close white_cabinet_1_bottom_region)
  (In akita_black_bowl_1 white_cabinet_1_bottom_region)
)

表示必须同时满足:

  1. 黑碗在底部抽屉内;
  2. 底部抽屉已经关闭。

评测重点

  • 抽屉、微波炉、炉子等可交互设备;
  • OpenCloseTurnOnTurnOff 等状态变化;
  • 多个目标谓词的联合满足;
  • 操作顺序和最终状态控制。

1.4 LIBERO-10

代码定义位于:

libero_suite_task_map.py

LIBERO-10 是一个精选的综合任务集,包含厨房、客厅和书房中的 10 个多阶段任务。

代表性任务包括:

  • 打开炉子并将摩卡壶放上去;
  • 将黑碗放入底部抽屉并关闭抽屉;
  • 将马克杯放入微波炉并关闭微波炉;
  • 将两个摩卡壶放到炉子上;
  • 将两种食品同时放入篮子;
  • 将两个杯子分别放到左右盘子上;
  • 将书放入收纳架后部隔间;
  • 将白色马克杯放到盘子上,并把巧克力布丁放到盘子右侧。

评测重点

LIBERO-10 更适合快速验证一个策略是否具备:

  • 多物体操作能力;
  • 多阶段任务规划能力;
  • 状态变化处理能力;
  • 任务语言理解能力;
  • 不同房间和场景之间的迁移能力。

1.5 LIBERO-90 / LIBERO-100

当前代码中注册的是 LIBERO_90

@register_benchmark
class LIBERO_90(Benchmark):
    ...
    self.name = "libero_90"

它包含大规模综合任务,覆盖:

  • 厨房;
  • 客厅;
  • 书房;
  • 抽屉、微波炉、炉子、酒架、篮子、托盘、盘子和书架;
  • 碗、杯子、酒瓶、食品包装、煎锅、摩卡壶和书等物体。

任务变化来自多个维度:

变化维度示例
场景厨房、客厅、书房
物体黑碗、白碗、杯子、食品包装、书
初始位置桌面、柜顶、抽屉、盘子旁边
目标位置盘子、篮子、托盘、抽屉、炉子、柜顶
空间关系左右、前后、上下、相邻
状态抽屉开关、炉子开关、微波炉开关
操作复杂度单物体、双物体、堆叠和多阶段任务

因此,LIBERO-90 更接近完整的 lifelong learning benchmark,而不是单一技能测试。


2. 引擎与本体

2.1 仿真引擎:MuJoCo + robosuite

依赖版本中明确指定:

  • robosuite==1.4.0
  • bddl==1.0.1
  • gym==0.25.2
  • robomimic==0.2.0
  • torch==1.11.0+cu113
  • Python 3.8.13

环境封装代码位于:

libero/libero/envs/env_wrapper.py

核心关系是:

BDDL 文件
   ↓
BDDLUtils 解析任务
   ↓
根据 problem_name 选择任务环境
   ↓
robosuite 创建 MuJoCo 仿真
   ↓
Panda 机器人执行动作
   ↓
谓词系统检查任务是否完成

LIBERO 的环境包装器会:

  1. 读取 BDDL 文件;
  2. 解析任务名称、语言指令和问题描述;
  3. 根据任务类型选择对应的环境;
  4. 创建 robosuite 环境;
  5. 设置相机、渲染方式、控制频率和机器人控制器;
  6. 调用 _check_success() 判断任务是否完成。

2.2 机器人本体:Panda

默认机器人配置为:

robots=["Panda"]

默认控制器为:

controller="OSC_POSE"

因此,项目默认使用:

  • Franka Panda 机械臂;
  • OSC Pose 操作空间控制;
  • 默认夹爪;
  • 7 维动作接口。

README 中的示例也使用:

dummy_action = [0.] * 7

这说明基准策略最终输出的是 7 维连续控制动作。


2.3 观测与视觉

环境支持:

  • RGB 图像;
  • 机器人手腕相机;
  • agentview 相机;
  • 离屏渲染;
  • 深度图;
  • segmentation mask;
  • 物体实例分割。

主要环境类型包括:

  • ControlEnv
  • OffScreenRenderEnv
  • SegmentationRenderEnv
  • DemoRenderEnv

其中:

  • OffScreenRenderEnv 用于训练和评估;
  • SegmentationRenderEnv 用于获得物体实例级 segmentation;
  • DemoRenderEnv 用于演示数据或可视化。

默认图像尺寸通常为:

128 × 128

2.4 BDDL 与谓词本体

BDDL 是 LIBERO 的任务表示核心,用于描述:

  • 场景中的固定物体;
  • 可操作物体;
  • 区域和位置;
  • 物体初始状态;
  • 任务目标。

任务文件通常包含:

(:language ...)
(:regions ...)
(:fixtures ...)
(:objects ...)
(:obj_of_interest ...)
(:init ...)
(:goal ...)

LIBERO 中使用的典型谓词包括:

  • In
  • On
  • Open
  • Close
  • TurnOn
  • TurnOff
  • Up

对应实现位于:

libero/libero/envs/predicates

当前环境的成功判断是对 goal state 中的谓词进行联合检查:

result = True
for state in goal_state:
    result = self._eval_predicate(state) and result
return result

也就是说,复合目标中的所有谓词都必须成立。


3. 评估指标和分数基线

3.1 核心指标:Success Rate

LIBERO 当前主要使用稀疏成功奖励:

  • 任务完成:+1
  • 未完成:0

README 明确说明,当前主要支持 sparse reward,因此项目重点是行为克隆和 lifelong learning,而不是直接用稀疏奖励进行强化学习。

成功率计算逻辑位于:

libero/lifelong/metric.py

基本形式是:

success_rate =
成功完成的 rollout 数量 / 总 rollout 数量

默认评估配置中:

n_eval: 20
num_procs: 20
max_steps: 600

因此,一个任务通常使用 20 个评估 rollout,每个 rollout 最多执行 600 步。


3.2 单任务成功率

单个任务的评估流程是:

  1. 加载固定的初始仿真状态;
  2. 创建一个或多个并行环境;
  3. 让环境先进行若干步零动作物理稳定;
  4. 策略根据视觉观测和任务语言生成动作;
  5. 运行最多 max_steps
  6. 根据环境的 done 或成功谓词判断是否完成;
  7. 汇总多个 rollout 的成功率。

这比只在一个随机初始状态下测试更加稳定和可复现。


3.3 Loss 指标

除了仿真成功率,项目还计算行为克隆的测试损失:

evaluate_loss(...)

它会遍历任务数据集,调用:

algo.policy.compute_loss(data)

然后计算每个任务上的平均 loss。

因此,项目同时记录:

  • 行为克隆 loss;
  • 仿真任务 success rate。

需要注意:loss 低不一定意味着仿真成功率高。LIBERO 最终更关注机器人在 MuJoCo 环境中是否真的完成任务。


3.4 Continual Learning 指标

项目在 main.py 中预先构建了几类 lifelong learning 统计量:

L_conf_mat
S_conf_mat
L_fwd
S_fwd

含义可以理解为:

指标含义
L_conf_mat不同学习阶段、不同任务上的 loss 矩阵
S_conf_mat不同学习阶段、不同任务上的 success rate 矩阵
L_fwdloss 形式的 forward transfer
S_fwdsuccess 形式的 forward transfer

Success Confusion Matrix

S_conf_mat[k][p] 表示:

学习到第 k 个任务后,在第 p 个任务上的成功率。

这个矩阵可以观察:

  • 学习新任务后旧任务是否遗忘;
  • 后续任务是否受益于之前学到的知识;
  • 多任务训练和顺序训练的差异。

3.5 基线算法

README 中提供的算法选项包括:

base
er
ewc
packnet
multitask

对应的含义大致是:

算法作用
Base顺序微调 / sequential fine-tuning 基线
ERExperience Replay,经验回放
EWCElastic Weight Consolidation,参数重要性约束
PackNet通过参数掩码分配不同任务的网络容量
Multitask多任务联合训练基线

README 还支持三种策略网络:

bc_rnn_policy
bc_transformer_policy
bc_vilt_policy

包括:

  • RNN 行为克隆策略;
  • Transformer 行为克隆策略;
  • ViLT 风格视觉语言策略。

因此,LIBERO 的基线组合通常是:

任务集 × 策略架构 × lifelong 算法

例如:

LIBERO-90 × BC-RNN × EWC
LIBERO-10 × BC-Transformer × PackNet
LIBERO-Goal × BC-ViLT × Multitask

3.6 分数基线如何理解

从仓库实现来看,LIBERO 提供的是:

  1. 可复现的任务和数据集;
  2. 统一的仿真环境;
  3. 统一的成功率计算;
  4. 顺序学习和多任务学习基线;
  5. 多种视觉策略网络;
  6. lifelong learning 算法。

但当前仓库 README 和代码中并没有维护一张完整的、所有组合对应的官方数值分数表。因此,不建议仅依据当前仓库代码声称某个算法在某个任务集上的具体百分比。

更准确的说法是:

  • 分数单位:任务成功率,通常是 0 到 1;
  • 基础对照:Base / sequential fine-tuning;
  • 联合训练对照:Multitask;
  • 持续学习方法:ER、EWC、PackNet;
  • 策略网络对照:RNN、Transformer、ViLT;
  • 论文分数:需要以对应论文实验表格和指定 commit 为准。

4. 对评测 Harness 做了什么优化

仓库没有直接出现名为 harness 的独立模块,但它已经实现了一套比较完整的 benchmark/evaluation harness。主要优化集中在可复现、批量并行、统一接口、结果追踪和调试回放

4.1 固定初始状态,减少评测噪声

每个任务都有对应的 init states 文件:

init_states = torch.load(init_states_path)

评测时不是完全随机初始化,而是从固定状态中取样:

indices = np.arange(...) % init_states.shape[0]
init_states_ = init_states[indices]
env.set_init_state(init_states_)

这样做的好处是:

  • 不同算法使用相同初始状态;
  • 不同实验之间更加公平;
  • 结果更容易复现;
  • 降低随机摆放造成的方差。

这是评测 harness 最重要的设计之一。


4.2 多环境并行 rollout

评估逻辑支持:

use_mp: true
num_procs: 20

num_procs > 1 时,使用:

SubprocVectorEnv(...)

否则使用:

DummyVectorEnv(...)

这样可以并行执行多个 MuJoCo 环境,在同样的时间内获得更多 rollout 样本。

评估代码会根据任务数和进程数自动计算:

env_num = min(cfg.eval.num_procs, cfg.eval.n_eval)

因此不会因为进程数大于评估样本数而创建多余环境。


4.3 训练与评估解耦

项目支持两种评估方式:

训练过程中自动评估

配置中:

eval: true
eval_every: 5

训练每隔若干 epoch 自动在仿真环境中评估。

单独评估已有模型

README 提供:

python libero/lifelong/evaluate.py \
  --benchmark BENCHMARK_NAME \
  --task_id TASK_ID \
  --algo ALGO_NAME \
  --policy POLICY_NAME \
  --seed SEED \
  --ep EPOCH \
  --load_task LOAD_TASK \
  --device_id CUDA_ID

这使得训练和评估可以分离,适合:

  • GPU 资源有限;
  • 批量评估多个 checkpoint;
  • 重新评估历史模型;
  • 对不同任务单独定位问题。

4.4 统一 Benchmark API

任务集通过统一接口注册:

get_benchmark_dict()
get_benchmark(...)

每个任务集都支持类似的接口:

get_num_tasks()
get_task_names()
get_task_problems()
get_task_bddl_files()
get_task_init_states()
get_task_demonstration()
get_task_emb()

这使得训练代码不需要针对每个任务集写不同逻辑。

例如训练主流程只需要:

benchmark = get_benchmark(cfg.benchmark_name)(...)

然后统一加载:

  • BDDL 文件;
  • demonstration 数据;
  • 初始状态;
  • 语言描述;
  • task embedding。

这是对 benchmark harness 的重要抽象。


4.5 语言任务 embedding 统一注入策略

main.py 中,每个任务的语言描述会被转换为 task embedding:

task_embs = get_task_embs(cfg, descriptions)
benchmark.set_task_embs(task_embs)

评估时,语言 embedding 会与视觉观测一起传入策略:

data = raw_obs_to_tensor_obs(obs, task_emb, cfg)
actions = algo.policy.get_action(data)

因此同一套 policy API 可以支持不同任务语言,而不需要为每个任务单独设计网络。


4.6 Off-screen rendering 和无界面评测

评估环境强制使用离屏渲染:

class OffScreenRenderEnv(ControlEnv):
    def __init__(self, **kwargs):
        kwargs["has_renderer"] = False
        kwargs["has_offscreen_renderer"] = True

这适合:

  • 服务器 GPU;
  • 无显示器环境;
  • 批量实验;
  • 多进程仿真;
  • 自动化 CI 或远程评测。

4.7 任务成功判断从奖励中独立出来

任务完成不是依赖人工分数,而是由 BDDL goal predicate 直接检查:

def check_success(self):
    return self.env._check_success()

例如:

  • 物体是否在容器内;
  • 物体是否位于指定表面;
  • 抽屉是否关闭;
  • 炉子是否打开;
  • 微波炉是否关闭。

这样可以避免使用模糊的距离阈值作为任务成功条件,使指标更接近语义目标。


4.8 失败重试和 MuJoCo 稳定性处理

环境 reset 时会捕获 robosuite 的 RandomizationError

while not success:
    try:
        ret = self.env.reset()
        success = True
    except RandomizationError:
        pass

多进程环境创建也带有重试机制:

while not env_creation and count < 5:
    try:
        ...
        env_creation = True
    except:
        time.sleep(5)
        count += 1

这类机制主要用于减少:

  • 随机初始化失败;
  • MuJoCo frame buffer 问题;
  • 多进程环境创建不稳定;
  • 批量评估中偶发的环境启动错误。

4.9 视频、仿真状态和结果矩阵保存

评估支持:

  • 保存 rollout 视频;
  • 保存 MuJoCo simulation state;
  • 之后回放或可视化;
  • 保存 loss/success confusion matrix;
  • 保存 forward transfer 结果;
  • 保存完整配置文件;
  • 使用 Weights & Biases 跟踪实验。

配置文件会写入实验目录:

with open(os.path.join(cfg.experiment_dir, "config.json"), "w") as f:
    json.dump(cfg, f, ...)

结果保存为:

torch.save(result_summary, ...)

这让实验具有较好的:

  • 可审计性;
  • 可复现实验配置;
  • 失败样本调试能力;
  • 历史 checkpoint 对比能力。

总结

从这四个维度看,LIBERO 不只是一个 MuJoCo 任务集合,而是一套面向 lifelong robot learning 的完整评测框架:

任务集
  ├── Spatial:空间关系泛化
  ├── Object:物体类别泛化
  ├── Goal:目标状态泛化
  ├── LIBERO-10:精选综合任务
  └── LIBERO-90/100:大规模综合任务

引擎与本体
  ├── MuJoCo
  ├── robosuite 1.4
  ├── Franka Panda
  ├── OSC_POSE
  └── BDDL + 逻辑谓词

评估指标与基线
  ├── sparse success rate
  ├── behavior cloning loss
  ├── success/loss confusion matrix
  ├── forward transfer
  ├── sequential fine-tuning
  ├── ER / EWC / PackNet
  └── Multitask

评测 Harness 优化
  ├── 固定初始状态
  ├── 多进程并行 rollout
  ├── 统一 benchmark API
  ├── 训练与评估解耦
  ├── off-screen rendering
  ├── 自动 reset 和环境创建重试
  ├── 视频与仿真状态回放
  └── 配置、结果矩阵和 W&B 记录

如果要把 LIBERO 接入一个更通用的 robot-learning evaluation harness,最值得复用的部分是:

  1. Benchmark 任务注册接口;
  2. BDDL 驱动的任务与成功判断;
  3. 固定 init states;
  4. SubprocVectorEnv 并行评估;
  5. success/loss confusion matrix;
  6. 视频和仿真状态保存机制。