Обучение с подкреплением
ManiSkill поддерживает различные методы обучения с подкреплением через единый API и предоставляет несколько готовых, проверенных базовых решений (baselines) для использования и сравнения. На этой странице описано, как настроить среду обучения с подкреплением и как пользоваться базовыми решениями. Все результаты базовых решений опубликованы на нашей открытой странице wandb. На ней можно фильтровать результаты по алгоритму, типу среды и т. д. Эксперименты ещё продолжаются, поэтому загружены не все результаты.
Настройка
На этой странице собраны ключевые сведения, которые нужно знать при подготовке сред ManiSkill для обучения с подкреплением:
- как превратить среду ManiSkill в среду, совместимую с API gymnasium, в одиночном и векторизованном вариантах;
- как правильно и честно оценивать политики RL;
- полезные обёртки.
Среды ManiSkill создаются функцией make из gymnasium. По умолчанию результат — «пакетная» среда, в которой все входы и выходы пакетированы. Это не стандартный API gymnasium. Если нужны стандартные API среды gymnasium или векторизованной среды, см. следующий раздел.
import mani_skill.envs
import gymnasium as gym
N = 4
env = gym.make("PickCube-v1", num_envs=N)
env.action_space # shape (N, D)
env.observation_space # shape (N, ...)
env.reset()
obs, rew, terminated, truncated, info = env.step(env.action_space.sample())
# obs (N, ...), rew (N, ), terminated (N, ), truncated (N, )
API одиночной среды Gym
Если нужен CPU-симулятор или одиночная среда, можно применить CPUGymWrapper. Он по сути снимает всё пакетирование и переводит всё в numpy, поэтому среда ведёт себя как обычная среда gym. Подробности об API сред gym см. в документации.
import mani_skill.envs
import gymnasium as gym
from mani_skill.utils.wrappers.gymnasium import CPUGymWrapper
N = 1
env = gym.make("PickCube-v1", num_envs=N)
env = CPUGymWrapper(env)
env.action_space # shape (D, )
env.observation_space # shape (...)
env.reset()
obs, rew, terminated, truncated, info = env.step(env.action_space.sample())
# obs (...), rew (float), terminated (bool), truncated (bool)
API векторизованной среды Gym
Мы также используем интерфейс VectorEnv (он же AsyncVectorEnv) из gymnasium; его можно подключить одной обёрткой, поэтому алгоритмы, которые предполагают интерфейс VectorEnv, работают без изменений. Подробности об API векторизованных сред gym см. в документации.
import mani_skill.envs
import gymnasium as gym
from mani_skill.vector.wrappers.gymnasium import ManiSkillVectorEnv
N = 4
env = gym.make("PickCube-v1", num_envs=N)
env = ManiSkillVectorEnv(env, auto_reset=True, ignore_terminations=False)
env.action_space # shape (N, D)
env.single_action_space # shape (D, )
env.observation_space # shape (N, ...)
env.single_observation_space # shape (...)
env.reset()
obs, rew, terminated, truncated, info = env.step(env.action_space.sample())
# obs (N, ...), rew (N, ), terminated (N, ), truncated (N, )
При создании векторизованной среды доступны ещё два параметра. Параметр auto_reset определяет, нужно ли автоматически сбрасывать параллельную среду при её завершении или обрыве; это зависит от алгоритма. Параметр ignore_terminations определяет, сбрасывается ли среда, когда terminated равен True. Как и в векторизованных средах gymnasium, возможен частичный сброс, когда одни параллельные среды сбрасываются, а другие нет.
Обратите внимание: ради эффективности всё, что возвращает среда, — это пакетные тензоры torch на GPU, а не пакетные массивы numpy на CPU. Это, пожалуй, единственное различие между векторизованными средами ManiSkill и векторизованными средами gymnasium, которое стоит учитывать.
Оценка
Учитывая разные типы сред, алгоритмов и способов оценки, ниже описан единообразный и стандартизированный способ честно оценивать политики любого типа в ManiSkill. Вкратце, для честной оценки нужны такие настройки:
- Отключить частичные сбросы: среда не сбрасывается при успехе, неудаче или завершении (
ignore_terminations=True). Вместо этого записываются несколько видов метрик успеха и неудачи. - Все параллельные среды переконфигурируются при сбросе (
reconfiguration_freq=1), и если в задаче есть рандомизация объектов, то рандомизируется и геометрия объектов.
Ниже код, который честно оценивает политику в ManiSkill и записывает стандартные метрики. Для векторизованной 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)
# Другие обёртки добавляются здесь
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)
# Другие обёртки добавляются здесь
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: суммарная награда, накопленная за эпизод.
Полезные обёртки
Практики RL часто используют обёртки, чтобы менять и дополнять среду. Они описаны в разделе об обёртках. Некоторые распространённые:
- RecordEpisode: записывает видео и траектории rollout.
- FlattenRGBDObservations: сводит наблюдения
obs_mode="rgbd"илиobs_mode="rgb+depth"к простому словарю, в котором остаются только объединённый тензорrgbdи тензорstate.
Частые ошибки и замечания
В старых средах и бенчмарках часто для получения изображений для агента RL использовали env.render(mode="rgb_array") или env.render(). Это неверно: изображения наблюдений возвращаются напрямую из env.reset() и env.step(), а env.render в ManiSkill предназначен только для визуализации и записи видео.
Для задач с роботами наблюдения обычно состоят из информации о состоянии (например, углы суставов робота) и изображений с камер. Когда obs_mode отличен от state или state_dict (где есть истинные позы объектов), все задачи ManiSkill намеренно исключают часть привилегированной информации о состоянии. Кроме того, изображения, которые возвращают env.reset() и env.step(), обычно получают с камер, стоящих в определённых местах, чтобы обеспечить хороший обзор, при котором задача решаема.
Базовые решения
Мы предоставляем несколько разных базовых решений, которые учатся по награде методом онлайн-обучения с подкреплением.
В рамках этих базовых решений мы создали стандартизированные бенчмарки RL, которые охватывают широкий диапазон сложности (лёгкие для проверки, но не насыщенные) и разнообразие типов роботизированных задач, включая, помимо прочего, классическое управление, ловкие манипуляции, манипуляции на столе, мобильные манипуляции и т. д.
Базовые решения онлайн-RL
Список реализованных и протестированных базовых решений онлайн-RL. Ссылки на результаты ведут на соответствующие страницы wandb. Фильтры и вид можно поменять в рабочей области wandb, чтобы посмотреть результаты с другими настройками (например, обучение по состоянию или по RGB). Обратите внимание, что есть также базовые решения RL с использованием демонстраций (офлайн RL, онлайн-имитационное обучение).
| Базовое решение | Код | Результаты | Статья |
|---|---|---|---|
| Proximal Policy Optimization (PPO) | ссылка | ссылка | ссылка |
| Soft Actor-Critic (SAC) | ссылка | WIP | ссылка |
| Temporal Difference Learning for Model Predictive Control (TD-MPC2) | WIP | WIP | ссылка |
Стандартные бенчмарки
Стандартные бенчмарки RL в ManiSkill состоят из двух наборов: малого набора из 8 задач и большого набора из 50 задач; оба имеют варианты на основе состояния и на основе зрения. Все стандартные задачи снабжены нормированной плотной функцией награды. Рекомендуемый малый набор создан для того, чтобы исследователи без больших вычислительных ресурсов могли разумно протестировать и сравнить свои работы. Большой набор ещё разрабатывается и тестируется.
Эти задачи охватывают чрезвычайно широкий круг проблем робототехники и RL: большие размерности наблюдений и действий, большое распределение начальных состояний, манипуляции сочленёнными объектами, обобщаемые манипуляции, мобильные манипуляции, локомоцию и т. д.
Идентификаторы сред малого набора:
PushCube-v1, PickCube-v1, PegInsertionSide-v1, PushT-v1, HumanoidPlaceAppleInBowl-v1, AnymalC-Reach-v1, OpenCabinetDrawer-v1
Оценка
Чтобы правильно оценивать политики RL, см. раздел «Оценка» на странице настройки RL: там описано, как настроен код. Все результаты, которые приведены в ссылках выше, соблюдают один и тот же протокол оценки.