煮过头了¶
概述¶
Overcooked-AI 是一个用于完全合作的人机任务性能的基准环境,基于广受欢迎的视频游戏 Overcooked。
游戏的目标是尽可能快地递送汤。每份汤需要将最多3种食材放入锅中,等待汤煮熟,然后让一个代理拿起汤并递送它。
此环境可用于测试协作代理的鲁棒性、RL代理与人类之间的交互等。
环境仍在开发中,但目前已有六篇研究论文正在使用Overcooked-AI,你可以在原始的Overcooked-AI仓库中找到这些论文。
原始的 overcooked-ai 仓库包含了 5 种可用的布局,如下所示:
新布局很容易硬编码或通过编程生成。
安装¶
安装方法¶
安装 overcooked-ai。你可以通过命令 pip 安装或从源代码构建。
# Method1: Install Directly
pip install overcooked-ai
# Method2: Build from source
git clone https://github.com/HumanCompatibleAI/overcooked_ai.git
pip install -e overcooked_ai/
安装检查¶
安装完成后,您可以通过以下命令检查是否成功:
cd DI-engine
pytest -sv dizoo/overcooked/envs/test_overcooked_env.py
RL 环境空间¶
观察空间¶
目前我们使用cramped_room设置来描述overcooked环境的观察空间。cramped_room的布局形状为
(5, 4)。包含2个代理。
每个代理的观测形状是
(layout_width, layout_height, 26),即对于cramped_room来说是(5, 4, 26)。如果在环境中使用
concat_obs,那么观测形状将是(2*layout_width, layout_height, 26),否则观测形状将是(2, (layout_width, layout_height, 26))。如果启用了
action_mask,观察结果还将返回一个action_mask,它将不可用的动作屏蔽为零(而一表示动作可用)。action_mask的形状为(2, 6)。
动作空间¶
动作空间也包含2个代理。
游戏中使用的按钮。通常有6个离散动作(N在不同的子环境中有所不同)。
动作的含义。 - 0:北(上)
1:南(下)
2:东(左)
3:西(右)
4:停留
5:互动
奖励空间¶
《煮糊了》的游戏分数。
请注意,我们使用了奖励塑形来简化训练过程。您可以通过将
use_shaped_reward设置为True或False来开启或关闭奖励塑形。
其他¶
游戏在固定的步数后结束(默认设置为400步)。
关键事实¶
环境中包含两个代理。
离散动作空间。
如果我们设置
use_shaped_reward为False,奖励可能会很稀疏。
其他¶
不同的布局¶
你可以通过更改环境配置中的env_name来改变使用的布局。然而,overcooked环境仍在开发中,因此并非所有布局都受支持。
你也可以手动编写自己的布局,参考此链接获取布局文件。
DI-zoo 代码示例¶
完整的训练配置在github链接。 你可以按照以下方式运行演示:
from ding.config import compile_config
from ding.worker import BaseLearner, Episode1v1Collector, OnevOneEvaluator, NaiveReplayBuffer
from ding.envs import BaseEnvManager, DingEnvWrapper
from ding.policy import PPOPolicy
from dizoo.overcooked.models.overcooked_vac import BaselineVAC
from ding.utils import set_pkg_seed
from dizoo.overcooked.envs import OvercookGameEnv
from dizoo.overcooked.config import overcooked_demo_ppo_config
def wrapped_overcookgame():
return OvercookGameEnv({})
def main(cfg, seed=0, max_iterations=int(1e10)):
cfg.exp_name = 'selfplay_demo_ppo'
cfg = compile_config(
cfg,
BaseEnvManager,
PPOPolicy,
BaseLearner,
Episode1v1Collector,
OnevOneEvaluator,
NaiveReplayBuffer,
save_cfg=True
)
collector_env_num, evaluator_env_num = cfg.env.collector_env_num, cfg.env.evaluator_env_num
collector_env = BaseEnvManager(env_fn=[wrapped_overcookgame for _ in range(collector_env_num)], cfg=cfg.env.manager)
evaluator_env1 = BaseEnvManager(
env_fn=[wrapped_overcookgame for _ in range(evaluator_env_num)], cfg=cfg.env.manager
)
evaluator_env2 = BaseEnvManager(
env_fn=[wrapped_overcookgame for _ in range(evaluator_env_num)], cfg=cfg.env.manager
)
collector_env.seed(seed)
evaluator_env1.seed(seed, dynamic_seed=False)
evaluator_env2.seed(seed, dynamic_seed=False)
set_pkg_seed(seed, use_cuda=cfg.policy.cuda)
model1 = BaselineVAC(**cfg.policy.model)
policy1 = PPOPolicy(cfg.policy, model=model1)
model2 = BaselineVAC(**cfg.policy.model)
policy2 = PPOPolicy(cfg.policy, model=model2)
tb_logger = SummaryWriter(os.path.join('./{}/log/'.format(cfg.exp_name), 'serial'))
learner1 = BaseLearner(
cfg.policy.learn.learner, policy1.learn_mode, tb_logger, exp_name=cfg.exp_name, instance_name='learner1'
)
learner2 = BaseLearner(
cfg.policy.learn.learner, policy2.learn_mode, tb_logger, exp_name=cfg.exp_name, instance_name='learner2'
)
collector = Episode1v1Collector(
cfg.policy.collect.collector,
collector_env, [policy1.collect_mode, policy2.collect_mode],
tb_logger,
exp_name=cfg.exp_name
)
# collect_mode ppo use multimonial sample for selecting action
evaluator1_cfg = copy.deepcopy(cfg.policy.eval.evaluator)
evaluator1_cfg.stop_value = cfg.env.stop_value
evaluator1 = OnevOneEvaluator(
evaluator1_cfg,
evaluator_env1, [policy1.collect_mode, policy2.collect_mode],
tb_logger,
exp_name=cfg.exp_name,
instance_name='selfplay_evaluator1'
)
evaluator2_cfg = copy.deepcopy(cfg.policy.eval.evaluator)
evaluator2_cfg.stop_value = cfg.env.stop_value
evaluator2 = OnevOneEvaluator(
evaluator2_cfg,
evaluator_env2, [policy2.collect_mode, policy1.collect_mode],
tb_logger,
exp_name=cfg.exp_name,
instance_name='selfplay_evaluator2'
)
for _ in range(max_iterations):
if evaluator1.should_eval(learner1.train_iter):
stop_flag1, reward = evaluator1.eval(learner1.save_checkpoint, learner1.train_iter, collector.envstep)
tb_logger.add_scalar('selfplay1_evaluator_step/reward_mean', reward, collector.envstep)
if evaluator2.should_eval(learner1.train_iter):
stop_flag2, reward = evaluator2.eval(learner1.save_checkpoint, learner1.train_iter, collector.envstep)
tb_logger.add_scalar('selfplay2_evaluator_step/reward_mean', reward, collector.envstep)
if stop_flag1 and stop_flag2:
break
train_data, _ = collector.collect(train_iter=learner1.train_iter)
for i in range(cfg.policy.learn.update_per_collect):
learner1.train(train_data[0], collector.envstep)
learner2.train(train_data[1], collector.envstep)
if __name__ == "__main__":
main(overcooked_demo_ppo_config)
算法基准测试¶
待办事项