一、 强化学习及MountainCar-v0 Example

一、 强化学习及MountainCar-v0 Example

强化学习讨论的问题是一个智能体 (agent) 怎么在一个复杂不确定的环境 (environment) 里面去
极大化它能获得的奖励。下面是它的示意图:
在这里插入图片描述
示意图由两部分组成:agent 和 environment。在强化学习过程中,agent 跟 environment 一直在交互。Agent 在环境里面获取到状态,agent 会利用这个状态输出一个动作 (action),一个决策。然后这个决策会放到环境之中去,环境会根据 agent 采取的决策,输出下一个状态以及当前的这个决策得到的奖励。Agent 的目的就是为了尽可能多地从环境中获取奖励。

1. 对比下强化学习和监督学习

  1. 强化学习输入的是序列数据,而不是像监督学习里面这些样本都是独立的。
  2. 学习器并没有被告诉你每一步正确的行为应该是什么。学习器需要自己去发现哪些行为可以得到最多的奖励, 只能通过不停地尝试来发现最有利的动作。
  3. Agent 获得自己能力的过程中,其实是通过不断地试错探索 (trial-and-error exploration)。
  4. 探索(exploration) 和利用 (exploitation) 是强化学习里面非常核心的一个问题。

2. 举一些在现实生活中强化学习的例子

  1. 在自然界中,羚羊其实也是在做一个强化学习,它刚刚出生的时候,可能都不知道怎么站立,然后它
    通过试错的一个尝试,三十分钟过后,它就可以跑到每小时 36 公里,很快地适应了这个环境。
  2. 把股票交易看成一个强化学习的问题,就怎么去买卖来使你的收益极大化。
  3. 玩雅达利游戏或者一些电脑游戏,也是一个强化学习的过程。

3. 什么是 Reward?

奖励是由环境给的一个标量的反馈信号 (scalar feedback signal),这个信号显示了 agent 在某一步采
取了某个策略的表现如何。强化学习的目的就是为了最大化 agent 可以获得的奖励,agent 在这个环境里面存在的目的就是为了极大化它的期望的累积奖励 (expected cumulative reward)。

4. Sequential Decision Making

部分可观测马尔可夫决策过程 (Partially Observable Markov Decision Processes, POMDP)是一个马尔可夫决策过程的泛化。POMDP 依然具有马尔可夫性质,但是假设智能体无法感知环境的状态 s,只能知道部分观测值 o。比如在自动驾驶中,智能体只能感知传感器采集的有限的环境信息。
POMDP 可以用一个 7 元组描述:(S, A, T, R, Ω, O, γ),其中 S 表示状态空间,为隐变量,A 为动作空间,T(s′|s, a) 为状态转移概率,R 为奖励函数,Ω(o|s, a) 为观测概率,O 为观测空间,γ 为折扣系数。

5. Action Spaces

在给定的环境中,有效动作的集合经常被称为动作空间 (action space)。
像 Atari 和 Go 这样的环境有离散动作空间 (discrete action spaces),在这个动作空间里,agent的动作数量是有限的。在其他环境,比如在物理世界中控制一个 agent,在这个环境中就有连续动作空间(continuous action spaces) 。在连续空间中,动作是实值的向量。

6. Policy

Policy 是 agent 的行为模型,它决定了这个 agent 的行为,它其实是一个函数,把输入的状态变成行为。这里有两种 policy:
stochastic policy(随机性策略),它就是 π 函数 π(a|s) = P [At = a|St = s] 。当你输入一个状态 s 的时候,输出是一个概率。这个概率就是你所有行为的一个概率,然后你可以进一步对这个概率分布进行采样,得到真实的你采取的行为。比如说这个概率可能是有 70% 的概率往左,30% 的概率往右,那么你通过采样就可以得到一个 action。
deterministic policy(确定性策略),就是说你这里有可能只是采取它的极大化,采取最有可能的动作
a∗ = arg max a π(a | s)
即你现在这个概率就是事先决定好的。

7. Value Function

价值函数是未来奖励的一个预测,用来评估状态的好坏。
价值函数里面有一个discount factor(折扣因子),我们希望尽可能在短的时间里面得到尽可能多的奖励。如果我们说十天过后,我给你 100 块钱,跟我现在给你 100 块钱,你肯定更希望我现在就给你 100 块钱,因为你可以把这 100 块钱存在银行里面,你就会有一些利息。所以我们就通过把这个折扣因子放到价值函数的定义里面,价值函数的定义其实是一个期望,如下面公式:
在这里插入图片描述
这里有一个期望 Eπ,这里有个小角标是 π 函数,这个 π 函数就是说在我们已知某一个策略函数的时
候,到底可以得到多少的奖励
我们还有一种价值函数:Q 函数。Q 函数里面包含两个变量:状态和动作,其定义如下式
在这里插入图片描述
这个 Q 函数是强化学习算法里面要学习的一个函数。因为当我们得到这个 Q 函数后,进入某一种状态,它最优的行为就可以通过这个 Q 函数来得到。

8. Model

模型决定了下一个状态会是什么样的,就是说下一步的状态取决于你当前的状态以及你当前采取的行为。
我们来看一个走迷宫的例子。如下图所示,要求 agent 从 start 开始,然后到达 goal 的位置;每走一步,你就会得到 -1 的奖励;可以采取的动作是往上下左右走;当前状态用现在 agent 所在的位置来描述。
在这里插入图片描述
如果采取的是基于策略的 (policy-based)RL,当学习好了这个环境过后,在每一个状态,我们就会得到一个最佳的行为
在这里插入图片描述
如果换成基于价值的 (value-based)RL 这个算法,利用价值函数来作为导向,我们就会得到另外一种
表征,这里就表征了你每一个状态会返回一个价值。比如说你在 start 位置的时候,价值是 -16,因为你最快可以 16 步到达终点。因为每走一步会减一,所以你这里的价值是 -16。当我们快接近最后终点的时候,这个数字变得越来越大。在拐角的时候,比如要现在在第二格 -15。然后 agent 会看上下,它看到上面值变大了,变成 -14 了,它下面是 -16,那么 agent 肯定就会采取一个往上走的策略。所以通过这个学习的值的不同,我们可以抽取出现在最佳的策略。
在这里插入图片描述
9. Gym库

OpenAI Gym 是一个环境仿真库,里面包含了很多现有的环境。针对不同的场景,我们可以选择不同
的环境,
• 离散控制场景 (输出的动作是可数的,比如 Pong 游戏中输出的向上或向下动作)
• 连续控制场景 (输出的动作是不可数的,比如机器人走路时不仅有方向,还要角度,角度就是不可数
的,是一个连续的量)。
我们可以通过 pip 来安装 Gym:

pip install gym

在 Python 环境中导入 Gym,如果不报错,就可以认为 Gym 安装成功,测试一下:

import gym
env = gym.make("Taxi-v3")
observation = env.reset()
agent = load_agent()
for step in range(100):
    action = agent(observation)
    observation, reward, done, info = env.step(action)

CartPole 是通过控制一个平板,让木棍立起来。
看一下 CartPole 的这个环境。对于这个环境,有两个动作,Cart 往左移还是往右移。这里得到了观测:这个车当前的位置,Cart 当前往左往右移的速度,这个杆的角度以及杆的最高点的速度。如果 observation 越详细,就可以更好地描述当前这个所有的状态。这里有 reward 的定义,如果能多保留一步,你就会得到一个奖励,所以你需要在尽可能多的时间存活来得到更多的奖励。当这个杆的角度大于某一个角度(没能保持平衡)或者这个车已经出到外面的时候,游戏就结束了,你就输了。所以这个agent 的目的就是为了控制木棍,让它尽可能地保持平衡以及尽可能保持在这个环境的中央。
在这里插入图片描述
接下来绘制实验的图形界面窗口:

import gym  # 导入 Gym 的 Python 接口环境包
env = gym.make('CartPole-v0')  # 构建实验环境
env.reset()  # 重置一个 episode
for _ in range(1000):
    env.render()  # 显示图形界面
    action = env.action_space.sample()  # 从动作空间中随机选取一个动作
    env.step(action)  # 用于提交动作,括号内是具体的动作
    env.close()  # 关闭环境

关闭该窗口的最佳方式是调用 env.close()。试图直接关闭图形界面窗口可能会导致内存不能释放,甚至会导致死机。
打印 env.action_space.sample() 的返回值,能看到输出为 1 或者 0。
env.action_space.sample()的含义是,在该游戏的所有动作空间里随机选择一个作为输出。在这个例子中,意思就是,动作只有两个:0 和 1,一左一右。
env.step() 这个方法的作用不止于此,它还有四个返回值,分别是 observation、reward、done、info。
observation(object) 是状态信息,是在游戏中观测到的屏幕像素值或者盘面状态描述信息
想要查看当前 Gym 库已经注册了哪些环境,可以使用以下代码:

from gym import envs
env_specs = envs.registry.all()
envs_ids = [env_spec.id for env_spec in env_specs]
print(envs_ids)

10. 示例 MountainCar-v0 Example

通过一个例子来学习如何与 Gym 库进行交互。我们选取小车上山 (MountainCar-v0)作为例子。
首先看下这个任务的观测空间和动作空间:

import gym
env = gym.make('MountainCar-v0')
print('观测空间 = {}'. format(env.observation_space))
print('动作空间 = {}'. format(env.action_space))
print('观测范围 = {} ~ {}'. format(env.observation_space.low,
            env.observation_space.high))
print('动作数 = {}'. format(env.action_space.n))

由输出可知,观测空间是形状为 (2,) 的浮点型 np.array,动作空间是取 0,1,2 的 int 型数值

  • 观测空间 = Box(2,)
  • 动作空间 = Discrete(3)
  • 观测范围 = [-1.2 -0.07] ~ [0.6 0.07]
  • 动作数 = 3
  • 可以实现一个智能体类:BespokeAgent 类,代码如下所示:

智能体的 decide() 方法实现了决策功能,而 learn() 方法实现了学习功能。BespokeAgent类是一个比较简单的类,它只能根据给定的数学表达式进行决策,不能有效学习。所以它并不是一个真正意义上的强化学习智能体类。但是,用于演示智能体和环境的交互已经足够了。

class BespokeAgent:
    def __init__(self, env):
        pass
    def decide(self, observation): # 决策

        position, velocity = observation
        lb = min(-0.09 * (position + 0.25) ** 2 + 0.03,
                 0.3 * (position + 0.9) ** 4 - 0.008)
        ub = -0.07 * (position + 0.38) ** 2 + 0.07
        if lb < velocity < ub:
            action = 2
        else:
            action = 0
            return action # 返回动作
    def learn(self, *args): # 学习
        pass
agent = BespokeAgent(env)

接下来试图让智能体与环境交互,代码如下所示:
play_montecarlo 函数可以让智能体和环境交互一个回合。这个函数有 4 个参数:
env 是环境类,agent 是智能体类,render 是 bool 类型变量,指示在运行过程中是否要图形化显示如果函数参数 render 为 True,那么在交互过程中会调用 env.render() 以显示图形化界面,而这个界面可以通过调用 env.close() 关闭。train 是 bool 类型的变量,指示在运行过程中是否训练智能体。在训练过程中应当设置为 True,以调用 agent.learn() 函数;在测试过程中应当设置为 False,使得智能体不变。这个函数有一个返回值 episode_reward,是 float 类型的数值,表示智能体与环境交互一个回合的回合总奖励。

def play_montecarlo(env, agent, render=False, train=False):
    episode_reward = 0. # 记录回合总奖励,初始化为0
    observation = env.reset() # 重置游戏环境,开始新回合
    while True: # 不断循环,直到回合结束
        if render: # 判断是否显示
            env.render() # 显示图形界面,图形界面可以用 env.close() 语句关闭
        action = agent.decide(observation)
        next_observation, reward, done, _ = env.step(action) # 执行动作
        episode_reward += reward # 收集回合奖励
        if train: # 判断是否训练智能体
            agent.learn(observation, action, reward, done) # 学习
        if done: # 回合结束,跳出循环
            break
        observation = next_observation
    return episode_reward # 返回回合总奖励

使用下列代码让智能体和环境交互一个回合,并在交互过程中图形化显示,可用 **env.close()**语句关闭图形化界面。

env.seed(0) # 设置随机数种子,只是为了让结果可以精确复现,一般情况下可删去
episode_reward = play_montecarlo(env, agent, render=True)
print('回合奖励 = {}'. format(episode_reward))
env.close() # 此语句可关闭图形界面

输出:回合奖励 = -105.0
为了系统评估智能体的性能,下列代码求出了连续交互 100 回合的平均回合奖励。

episode_rewards = [play_montecarlo(env, agent) for _ in range(100)]
print('平均回合奖励 = {}'. format(np.mean(episode_rewards)))

输出:平均回合奖励 = -102.61
小车上山环境有一个参考的回合奖励值 -110,如果当连续 100 个回合的平均回合奖励大于 -110,则
认为这个任务被解决了。BespokeAgent 类对应的策略的平均回合奖励大概就在 -110 左右。测试 agent 在 Gym 库中某个任务的性能时,学术界一般最关心 100 个回合的平均回合奖励。至于为什么是 100 个回合而不是其他回合数(比如 128 个回合),完全是习惯使然,没有什么特别的原因。对于有些环境,还会指定一个参考的回合奖励值,当连续 100 个回合的奖励大于指定的值时,就认为这个任务被解决了。但是,并不是所有的任务都指定了这样的值。对于没有指定值的任务,就无所谓任务被解决了或者没有被解决。

总结一下 Gym 的用法:

  • 使用 env=gym.make(环境名) 取出环境
  • 使用 env.reset()初始化环境
  • 使用env.step(动作)执行一步环境
  • 使用 env.render() 显示环境
  • 使用 env.close() 关闭环境
  • 最后如果有问题可以阅读文档来学习 Gym。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值