Skip to content

Latest commit

 

History

History
110 lines (82 loc) · 7.46 KB

File metadata and controls

110 lines (82 loc) · 7.46 KB

从演示中学习

ManiSkill 通过统一的 API 支持各种从演示中学习/模仿学习方法,并提供多个现成的、经过测试的基线以供使用/比较。以下页面展示了如何为从演示中学习设置数据集/环境以及如何使用基线。所有基线结果都发布到我们的公共 wandb 页面。在该页面上,可以按使用的算法、环境类型等进行过滤。我们仍在进行所有实验,因此并非所有结果都已上传。

设置

本页记录了在 ManiSkill 环境下使用演示数据进行学习时需要了解的关键事项,包括:

下载并回放轨迹 / 标准数据集

默认情况下,为了实现快速下载和较小的文件体积,ManiSkill 的演示数据以高度简化/压缩的格式存储,这种格式不包含任何观测数据。运行以下命令下载原始的最小化演示数据:

python -m mani_skill.utils.download_demo "PickCube-v1"

为了确保每个人使用相同的预处理/回放数据集,请务必运行以下脚本:ManiSkill/scripts/data_generation/replay_for_il_baselines.sh at main · haosulab/ManiSkill · GitHub。请注意,部分脚本使用 GPU 模拟(通过 -b physx_cuda 标记)进行回放,这可能会比你可用的 GPU 内存要求更多。如果需要,可以通过设置 --num-procs 参数为较小的数值来降低并行回放的环境数量。

该脚本为轨迹回放固定了设置,以生成观测数据并为所有基准任务设置期望的动作空间/控制器。所有在 Wandb 项目 中详细记录的基准训练运行结果,都使用了上述脚本回放生成的数据。

如果你需要更高级的轨迹回放用例(例如生成点云、更改控制器模式),请参阅 轨迹回放文档。如果你希望在本地生成原始数据集,我们在 data_generation 文件夹中保存了所有用于数据集生成的脚本。

评估

由于存在多种类型的环境、算法和评估方法,下面描述了一种一致且标准化的方式,用于公平地评估 ManiSkill 中的各种演示学习策略。简而言之,为了确保公平评估,需要进行如下设置:

  • 关闭部分重置(partial resets),环境在成功/失败/终止时不会重置(ignore_terminations=True)。而是记录多种成功/失败指标。
  • 所有并行环境在重置时均会重新配置(reconfiguration_freq=1),这将随机化任务中物体的几何形状(如果任务包含物体随机化)。

下面给出在 ManiSkill 中公平评估策略并记录标准指标的代码示例。我们分别提供了 CPU 和 GPU 向量化环境的选项,原因在于根据你的演示数据所采集的模拟后端,你可能希望在相同的后端上评估你的策略。

GPU 向量化环境下的评估代码示例

import gymnasium as gym
from mani_skill.vector.wrappers.gymnasium import ManiSkillVectorEnv
env_id = "PushCube-v1"
num_eval_envs = 64
env_kwargs = dict(obs_mode="state")  # 根据需要修改 env_kwargs
eval_envs = gym.make(env_id, num_envs=num_eval_envs, reconfiguration_freq=1, **env_kwargs)
# 在此处添加其他需要的 wrappers
eval_envs = ManiSkillVectorEnv(eval_envs, ignore_terminations=True, record_metrics=True)

# 评估循环,仅记录完整回合的指标
obs, _ = eval_envs.reset(seed=0)
eval_metrics = defaultdict(list)
for _ in range(400):
    action = eval_envs.action_space.sample()  # 用你的策略动作替换该行
    obs, rew, terminated, truncated, info = eval_envs.step(action)
    # 注意,由于没有部分重置,所有环境的 truncated 同时为 True
    if truncated.any():
        for k, v in info["final_info"]["episode"].items():
            eval_metrics[k].append(v.float())
for k in eval_metrics.keys():
    print(f"{k}_mean: {torch.mean(torch.stack(eval_metrics[k])).item()}")

CPU 向量化环境下的评估代码示例

import gymnasium as gym
from mani_skill.utils.wrappers import CPUGymWrapper
env_id = "PickCube-v1"
num_eval_envs = 8
env_kwargs = dict(obs_mode="state")  # 根据需要修改 env_kwargs

def cpu_make_env(env_id, env_kwargs=dict()):
    def thunk():
        env = gym.make(env_id, reconfiguration_freq=1, **env_kwargs)
        env = CPUGymWrapper(env, ignore_terminations=True, record_metrics=True)
        # 在此处添加其他需要的 wrappers
        return env
    return thunk

vector_cls = gym.vector.SyncVectorEnv if num_eval_envs == 1 else lambda x: gym.vector.AsyncVectorEnv(x, context="forkserver")
eval_envs = vector_cls([cpu_make_env(env_id, env_kwargs) for _ in range(num_eval_envs)])

# 评估循环,仅记录完整回合的指标
obs, _ = eval_envs.reset(seed=0)
eval_metrics = defaultdict(list)
for _ in range(400):
    action = eval_envs.action_space.sample()  # 用你的策略动作替换该行
    obs, rew, terminated, truncated, info = eval_envs.step(action)
    # 注意,由于没有部分重置,所有环境的 truncated 同时为 True
    if truncated.any():
        for final_info in info["final_info"]:
            for k, v in final_info["episode"].items():
                eval_metrics[k].append(v)
for k in eval_metrics.keys():
    print(f"{k}_mean: {np.mean(eval_metrics[k])}")

下面是记录和解释的指标:

  • success_once:在回合中的任意时刻任务是否成功。
  • success_at_end:在回合的最后一步任务是否成功。
  • fail_once / fail_at_end:与上面两个类似,但用于失败情况。注意,并非所有任务都有成功/失败的标准。
  • return:整个回合中累计的奖励总和。

通常对于演示学习而言,唯一重要的指标是 "success_once",这也是 ManiSkill 相关研究和工作中通常报告的指标。

常见的注意事项

通常,如果演示数据是在例如 PhysX CPU 模拟环境中收集的,那么你需要确保在相同的模拟后端上评估任何在该数据上训练的策略。对于高度精密的任务(例如 PushT),即使 1e-3 的误差也可能导致不同的结果,这一点尤为重要。这也是为何我们所有通过轨迹回放工具回放的演示数据,都会在轨迹文件名上标注所使用的模拟后端。

你的演示数据来源在很大程度上会影响训练表现。经典的行为克隆方法可以较好地模仿由神经网络/RL 策略生成的演示数据,但对于多模态的演示数据(例如人类遥操作或运动规划生成的数据)则较难模仿。像 Diffusion Policy (DP) 这样的方法就是为了解决这个问题。如果你不确定,所有 ManiSkill 官方数据集都会在轨迹元数据的 JSON 文件中详细说明数据的采集方式及数据类型。