Shortcuts

CartPole

概述

倒立摆问题是强化学习中的经典控制问题。CartPole 是倒立摆问题中的一个离散控制任务。在游戏中有一个小车,上有竖着一根杆子。小车在一个光滑无摩擦的轨道上左右滑行,目的是使杆子保持竖直。如下图所示。

../_images/cartpole.gif

安装

安装方法

CartPole 环境内置在 gym 中,直接安装 gym 即可。其环境 id 是CartPole-v0

pip install gym

验证安装

在 Python 命令行中运行如下命令验证安装成功。

import gym
env = gym.make('CartPole-v0')
obs = env.reset()
print(obs)

环境介绍

动作空间

CartPole 的动作空间属于离散动作空间,有 2 个离散动作,分别是左移和右移。

  • 左移 : 0 表示让 agent 向左移动。

  • 右移 : 1 表示让 agent 向右移动。

使用 gym 环境空间定义则可表示为:

action_space = spaces.Discrete(2)

状态空间

CartPole 的状态空间有 4 个元素,分别是:

  • Cart Position :小车的位置,范围是 [-4.8, 4.8]

  • Cart Velocity :小车的速度,范围是 [-inf, inf]

  • Pole Angle :杆的角度,范围是 [-24 deg, 24 deg]

  • Pole Angular Velocity :杆的角速度,范围是 [-inf, inf]

奖励空间

每一步操作,都将获得值为 1 的奖励,直到 episode 终止(终止状态也将获得值为 1 的奖励)。

终止条件

CartPole 环境每个 episode 的终止条件是遇到以下任何一种情况:

  • 杆偏移的角度超过 12 度。

  • 小车出界,通常把边界距离设置为 2.4。

  • 达到 episode 的最大 step,默认为 200。

CartPole 任务在什么情况下视为胜利

当100次试验的平均 episode 奖励达到 195 以上时,视作游戏胜利。

DI-zoo 可运行代码示例

下面提供一个完整的 CartPole 环境 config,采用 DQN 算法作为 policy。请在DI-engine/ding/example 目录下运行dqn_nstep.py 文件,具体实现如下。

import gym
from ditk import logging
from ding.model import DQN
from ding.policy import DQNPolicy
from ding.envs import DingEnvWrapper, BaseEnvManagerV2
from ding.data import DequeBuffer
from ding.config import compile_config
from ding.framework import task
from ding.framework.context import OnlineRLContext
from ding.framework.middleware import OffPolicyLearner, StepCollector, interaction_evaluator, data_pusher, \
    eps_greedy_handler, CkptSaver, nstep_reward_enhancer, final_ctx_saver
from ding.utils import set_pkg_seed
from dizoo.classic_control.cartpole.config.cartpole_dqn_config import main_config, create_config


def main():
    logging.getLogger().setLevel(logging.INFO)
    main_config.exp_name = 'cartpole_dqn_nstep'
    main_config.policy.nstep = 3
    cfg = compile_config(main_config, create_cfg=create_config, auto=True)
    with task.start(async_mode=False, ctx=OnlineRLContext()):
        collector_env = BaseEnvManagerV2(
            env_fn=[lambda: DingEnvWrapper(gym.make("CartPole-v0")) for _ in range(cfg.env.collector_env_num)],
            cfg=cfg.env.manager
        )
        evaluator_env = BaseEnvManagerV2(
            env_fn=[lambda: DingEnvWrapper(gym.make("CartPole-v0")) for _ in range(cfg.env.evaluator_env_num)],
            cfg=cfg.env.manager
        )

        set_pkg_seed(cfg.seed, use_cuda=cfg.policy.cuda)

        model = DQN(**cfg.policy.model)
        buffer_ = DequeBuffer(size=cfg.policy.other.replay_buffer.replay_buffer_size)
        policy = DQNPolicy(cfg.policy, model=model)

        task.use(interaction_evaluator(cfg, policy.eval_mode, evaluator_env))
        task.use(eps_greedy_handler(cfg))
        task.use(StepCollector(cfg, policy.collect_mode, collector_env))
        task.use(nstep_reward_enhancer(cfg))
        task.use(data_pusher(cfg, buffer_))
        task.use(OffPolicyLearner(cfg, policy.learn_mode, buffer_))
        task.use(CkptSaver(policy, cfg.exp_name, train_freq=100))
        task.use(final_ctx_saver(cfg.exp_name))
        task.run()


if __name__ == "__main__":
    main()

实验结果

使用 DQN 算法的实验结果如下。横坐标是和环境交互的步数,即 env step ,纵坐标是epsiode reward mean

../_images/cartpole_dqn.png

参考资料