和我一起入门强化学习(一)

写在前面

大家好,这里是新人Nobody,立志于在有生之年看到并参与通用人工智能开发工作,现在刚入职某公司担任算法工程师,尽量坚持和大家一起学习进步,并将自己学习的笔记和小小心得分享给大家。

以下是本文的思维导图

强化学习 第一章 绪论.png

一、概述

强化学习(Reinforcement Learning,RL) 讨论的问题是智能体(agent) 如何在复杂、不确定的环境(environment) 中最大化它能够获得的奖励(reward)

强化学习由智能体和环境两部分组成。

强化学习示意.png

1.1 强化学习与监督学习

在监督学习中,我们有大量的已标注好标签的数据,例如汽车、飞机、椅子这些被标注的图片,这些图片都要满足独立同分布。我们在用这些图片训练神经网络时,当其做出错误的预测时,我们根据错误写出一个损失函数,通过反向传播来训练神经网络。

汽车、飞机.png

独立同分布:通常假设样本空间中全体样本服从一个未知分布,每个样本都是独立地从这个分布上采样获得的,即独立同分布。

因此在监督学习过程中,有两个假设:

  • 输入的数据没有关联,服从独立同分布。
  • 需要告诉学习器正确的标签是什么。

但在强化学习中,以上两个假设都无法满足。以打砖块游戏为例,将木板视为智能体,智能体得到的观测(observation)不是独立同分布的,我们得到的数据是相关的时间序列数据。除此之外,该游戏没有立即告诉我们哪个动作是正确的,木板向右移我们就只能知道球会向上一些或者向左一些,无法得到即时的反馈。

打砖块.png

因此,强化学习就是一个玩游戏的过程,我们将序列数据输入到网络中,希望网络输出一个动作来决定智能体(即木板)向左移动或者向右移动。但是,我们无法得到当前该动作是正确的还是错误的,我们得等到游戏结束才能知道这个时刻的动作对于游戏胜负是不是有力的。因此我们就面临着延迟奖励的挑战。

综上所述,我们可以得到强化学习和监督学习的区别:

  • 强化学习处理的大多数是序列数据
  • 学习器没有告诉我们每一步正确的动作应该是什么
  • 强化学习中的探索和利用。探索即智能体采用一些新的动作,这新的动作可能会使得我们得到更多的奖励,当然,也有可能一无所有。利用即采用过往的经验,因为我们知道这样做可以稳定获得奖励。
  • 强化学习是无监督的,只有奖励信号,这种奖励信号还是延迟的。

1.2 强化学习的例子

  • 羚羊刚出生时还不会站立,但通过不断试错就可以适应环境
  • 通过玩雅达利游戏或者其他电脑游戏,我们通过不断试错才知道怎么玩可以通关

雅达利游戏.png
以上为强化学习的一个经典例子,即雅达利的 Pong 游戏,训练好的智能体会一直做无意义的上下往复移动,而正常玩家不会做出这样的操作。在游戏过程中,强化学习会通过一个策略网络来进行分类,策略网络会输入当前帧的图片,从而输出所有决策的可能性。

智能体在玩游戏的过程中,会对动作进行采样,预演(rollout) 到游戏结束,然后对每一个动作进行惩罚。预演是指我们从当前帧对动作进行采样,生成很多种可能。 将当前的智能体和环境进行交互,会得到一系列观测,每一个观测可以看作一条轨迹(trajectory)。轨迹即当前帧以及它采取的策略,即状态和动作的序列。

τ=(s0,a0,s1,a1,...)\tau=(s_0,a_0,s_1,a_1,…)

我们可以通过观测序列以及最终奖励来训练智能体,使其尽可能采取可以获得最终奖励的动作。一场游戏称为一个回合(episode)或者试验(trial)。

二、序列决策概述

2.1 智能体和环境

强化学习研究的是智能体与环境交互的问题。智能体把它的动作输出给环境,环境取得这个动作后会进行下一步,把下一步的观测与这个动作带来的奖励返还给智能体,这样的交互会产生很多观测,智能体的目的是从这些观测之中学到能最大化奖励的策略。

2.2 奖励

奖励是由环境给出的一种标量的反馈信号,这种信号可显示智能体在某一步采取某个策略的表现如何。强化学习的目的是最大化智能体可以获得的奖励,智能体在环境中存在的目的就是最大化它的期望的累计奖励(excepted cumylative reward)

2.3 序列决策

在一个强化学习环境中,智能体的目的是选取一系列的动作来最大化奖励,因此这些动作必须有长期的影响。然后奖励是延迟的,我们在当前时刻采取了某一个动作,我们需要在很久之后才能知道这个动作是起到正反馈的还是负反馈的。

强化学习中一个重要的问题就是近期奖励和远期奖励的权衡(trade-off),即研究怎么让智能体取得更多的远期奖励。

在智能体与环境进行交互的过程中,会获得许多观测。对于每一个观测,智能体会采取一个动作,也会得到一个奖励。因此,历史是观测、动作、奖励的序列。

Ht=o1,a1,r1,...,ot,at,rtH_t=o_1,a_1,r_1,…,o_t,a_t,r_t

而智能体在采取动作的时候会依赖于之前的历史,因此我们可以将状态看成关于这个历史的函数。

st=f(Ht)s_t=f(H_t)

状态和观测之间的关系:状态是对世界的完整描述,不会隐藏世界的信息;观测是对状态的部分描述,可能会遗漏一部分信息。

马尔可夫决策过程:

  • 完全可观测的马尔可夫决策过程(fully observed Markov decision process,FOMDP):当智能体的状态和环境的状态等价的时候,即当智能体能够观察到环境的所有状态时,我们称这个为完全可观测的马尔可夫决策过程。在马尔可夫决策过程中,观测和状态服从以下等式。

    ot=ste=stao_t=s_t^e=s_t^a
  • 部分可观测的马尔可夫决策过程(partially observable Markov decision process, POMDP):当智能体只能看到部分的观测,我们就称这个环境是部分可观测的。部分可观测马尔可夫决策过程可以用一个七元组描述:(S,A,T,R,Ω,O,γ)。其中S表示状态空间,为隐变量,A为动作空间,T(s’|s,a)为状态转移概率,R为奖励函数,Ω(o|s,a)为观测概率,O为观测空间,γ为折扣因子。

三、动作空间

  • 离散动作空间
  • 连续动作空间

四、强化学习智能体的组成部分和类型

4.1 策略

策略:智能体会用策略来选取下一步的动作。策略是智能体的动作模型,它决定了智能体的动作。

  • 随机性策略:输入一个状态s,输出一个概率p。这个概率是智能体所有动作的概率,然后对这个概率分布进行采样,可以得到智能体将要采取的动作。随机性策略可以描述成下面的函数形式

    π(as)=p(at=ast=s)\pi(a|s)=p(a_t=a|s_t=s)
  • 确定性策略:智能体直接采取最有可能的动作。

    a=argmaxπ(as)a^*=argmax\pi(a|s)

以雅达利游戏为例,策略函数的输入是游戏的一帧,它的输出决定智能体向左还是向右移动。

随机性策略的优点:

  • 在学习时可以引入一定的随机性来更好地探索环境
  • 随机性策略的动作具有多样性,这一点在多个智能体博弈时非常重要
  • 采用确定性策略的智能体总是对同样的状态采取相同的动作,这样它的策略容易被对手洞悉。

4.2 价值函数

价值函数的值是对未来奖励的预测,我们用它来评估状态的好坏。价值函数中有一个折扣因子(discount factor) ,我们希望在尽可能短的时间内得到尽可能多的奖励。价值函数的定义为

Vπ(s)=Eπ[Gtst=s]=Eπ[k=0γkrt+k+1st=s]V_{\pi}(s)=E_{\pi}[G_t|s_t=s]=E_{\pi}[\sum_{k=0}^∞\gamma^kr_{t+k+1}|s_t=s]

还有一种价值函数:Q函数。Q函数中包含两个变量:状态和动作,其定义为

Qπ(s,a)=Eπ[Gtst=s,at=a]=Eπ[k=0γkrt+k+1st=s,at=a]Q_{\pi}(s,a)=E_{\pi}[G_t|s_t=s,a_t=a]=E_{\pi}[\sum_{k=0}^∞\gamma^kr_{t+k+1}|s_t=s,a_t=a]

因此我们未来可以获得奖励的期望取决于当前的状态和当前的动作。

4.3 模型

模型决定了下一步的状态。下一步的状态取决于当前的状态以及当前采取的动作。它由状态转移概率和奖励函数两个部分组成。状态转移概率即

pssa=p(st+1=sst=s,at=a)p_{ss’}^a=p(s_{t+1}=s’|s_t=s,a_t=a)

奖励函数是指我们在当前状态采取了某个动作,可以得到多大的奖励,即

R(s,a)=E[rt+1st=s,at=a]R(s,a)=E[r_{t+1}|s_t=s,a_t=a]

当我们有了策略、价值函数和模型这三部分后,就可以形成一个马尔可夫决策过程。我们可以用不同的强化学习方法来处理环境。如基于策略的强化学习方法和基于价值的强化学习方法。

4.4 智能体的类型

  • 基于价值与基于策略的智能体(根据智能体学习的事物不同)

    • 基于价值的智能体:显式地学习价值函数,隐式地学习其策略。策略是从学习到的价值函数中推算出来的

    • 基于策略的智能体:直接学习策略,给他一个状态,他就会输出对应动作的概率。

    • 把以上两种智能体结合起来就有了演员-评论员智能体(actor-critic agent) 。后面会再学习介绍。

    • 区别:

      • 从决策方法来看:在基于策略的强化学习方法中,智能体会指定一套动作策略,即确定在给定状态下需要采取何种动作,并根据这个策略进行操作,强化学习直接对策略进行优化;在基于价值的强化学习方法中,智能体不需要制定显式的策略,它维护一个价值表格与价值函数,并通过这个价值表格或价值函数来选取价值最大的动作。
  • 有模型强化学习智能体与免模型强化学习智能体(根据智能体到底有没有学习环境模型)

    • 有模型强化学习智能体:通过学习状态的转移来采取动作。马尔可夫决策过程可以用来定义强化学习任务,并将其表示为四元组<S,A,P,R>,即状态集合、动作集合、状态转移函数和奖励函数。当智能体知道状态转移函数和奖励函数后,它就能知道在某一状态下执行某一动作后能带来的奖励和环境的下一个状态,这样智能体就不需要在真实环境中采取动作,直接在虚拟世界中学习和规划策略即可。
    • 免模型强化学习智能体:它没有直接估计状态的转移,也没有得到环境的具体转移变量,它通过学习价值函数和策略函数进行决策。在实际应用中,智能体并不是那么容易知道马尔可夫决策过程中所有的元素,通常来说,状态转移函数和奖励函数很难估计。
    • 区别:免模型强化学习的泛化性要优于有模型强化学习,因为有模型强化学习需要对真实环境进行建模,并且虚拟环境和真实环境之间可能还有差异,这限制了有模型强化学习算法的泛化性。

五、学习与规划

学习(learning)和规划(planning) 是序列决策的两个基本问题。一个常用的解决思路:先学习环境如何工作,也就是了解环境工作的方式,即学习得到一个模型,然后利用这个模型进行规划。

六、探索与利用

  • 探索:我们去探索环境,通过尝试不同的动作来得到最佳的策略(带来最大奖励的策略)。
  • 利用:即我们不去尝试新的动作,而是采取已知的可以带来很大奖励的动作。

七、强化学习实验

7.1 Gym

Gym是OpenAI的一个环境仿真库,其中包含了很多现有的环境。针对不同的场景,我们可以选择不同的环境。

我们可以通过在终端中输入以下代码来安装Gym库。

pip install gym 

在PyCharm中输入以下代码导入Gym库

import gym


我们尝试构建一个实验来模拟智能体和环境的交互。我们先来看看这个任务的观测空间和动作空间。

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))

输出:

观测空间 = Box([-1.2  -0.07], [0.6  0.07], (2,), float32)
动作空间 = Discrete(3)
观测范围 = [-1.2  -0.07] - [0.6  0.07]
动作数 = 3

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

接下来要考虑智能体,我们自己实现一个智能体类。

class BespokeAgent:
    def __int__(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):
        return

智能体的decide()方法实现了决策功能,而learn()方法实现了学习功能。该类是一个比较简单的类,只按照固定的数学公式来进行决策,不能算真正意义上的强化学习智能体类,但是我们只是将其用于演示智能体和环境的交互。

接下来我们让智能体和环境进行交互。

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

输出:

回合奖励 = -123.0

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

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

输出:

回合奖励 = -105.4

小车上山环境有一个参考的回合奖励值-110,如果连续100个回合的平均回合奖励大于-110,则认为这个任务被完成了。

以下为完整代码

import gym


import numpy as np
​
class BespokeAgent:
    def __int__(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):
        return
​
def play_montecarlo(env, agent, render=False, train=False):
    episode_reward = 0  # 记录回合总奖励,初始化为0
    observation = env.reset()  # 重置游戏环境
    while True:  # 不断循环,直到游戏结束
        if render:  # 判断是否显示图像界面
            env.render()  # 显示图像界面
        action = agent.decide(observation)
        next_observation, reward, done, k = env.step(action)  # 执行动作
        episode_reward += reward  # 收集回合奖励
        if train:  # 判断是否训练智能体
            agent.learn(observation, action, reward, done)  # 学习
        if done:  # 回合结束,跳出循环
            break
        observation = next_observation
    return episode_reward  # 返回回合总奖励
​
​
if __name__ == '__main__':
    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))
    env.seed(0)  # 设置随机种子,确保结果可以复现
    agent = BespokeAgent()
    episode_rewrd = [play_montecarlo(env, agent) for _ in range(100)]
    print('回合奖励 = {}'.format(np.mean(episode_rewrd)))
    env.close()

总结:使用 env=gym.make(环境名) 取出环境,使用 env.reset() 初始化环境,使用 env.step(动作) 执行一步环境,使用env.render() 显示环境,使用 env.close() 关闭环境。大家可以搜索Gym库的官方文档来学习Gym库。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY4X452v' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片