深度强化学习

Posted 岩枭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度强化学习相关的知识,希望对你有一定的参考价值。

强化学习有两个基本概念:环境(即外部世界)和智能体(即你正在编写的算法)。智能体向环境发送行为,环境回复观察和奖励(即分数)。

强化学习其实也是机器学习的一个分支,但是它与我们常见监督学习和无监督学习又不太一样。强化学习旨在选择最优决策,它讲究在一系列的情景之下,通过多步恰当的决策来达到一个目标,是一种序列多步决策的问题,而监督式学习和非监督式学习主要关注的是做出预测。。该学习算法能帮助我们公式化表达生物体以奖励为动机(reward-motivated)的行为。比如说,让一个孩子坐下来安静地为考试而复习是十分困难的,但如果你在他每次学完一章时奖励一块巧克力,那么他就会明白只有保持学习才能获得奖励,因此也就有动力复习备考。而现在,如果这个孩子在备考时没有明确的方法,他可能会花大量时间学习一个章节而不能及时完成课程大纲。所以我们需要小孩有效率地学,因此如果小孩在一小时内完成某章节,那么就奖励大块巧克力,而超过 1 小时那就只奖励小块巧克力。现在他不仅会学习,同时大脑会思考设计出更快完成章节学习的方法。

在这个例子中,孩子就是代表着训练实体(Agent :与环境交互的对象)。奖励系统和考试就代表着环境(Environment)。而章节就可以类比为强化学习的状态(States)。所以孩子们就需要决定哪些章节更重要(即计算每一个章节的值),这也就是价值函数(Value-Function)所做的事。并且小孩每次从一个状态到另一个状态就能收到奖励,而他随时间完成章节的方式就是策略(Policy)。

强化学习和其他机器学习范式有什么不同:

  • 没有大量标注数据进行监督,所以也就不能由样本数据告诉系统什么是最可能的动作,训练主体只能从每一步动作得出奖励。因此系统是不能立即得到标记的,而只能得到一个反馈,也可以说强化学习是一种标记延迟的监督学习。

  • 时间序列的重要性,强化学习不像其他接受随机输入的学习方法,其更注重序列型数据,并且下一步的输入经常依赖于前一状态的输入。

  • 延迟奖励的概念,系统可能不会在每步动作上都获得奖励,而只有当完成整个任务时才会获得奖励。

  • 训练实体的动作影响下一个输入。如你可以选择向左走或向右走,那么当选择的方向不同时,下一个时间步的输入也会不同。即选择不同的动作进入不同的状态后,当前可选的动作又不一样。

总的来说,强化学习的目标就是要寻找一个能使得我们获得最大累积奖赏的策略。因此,强化学习实际上和我们人类与环境的交互方式类似,是一套非常通用的框架,可以用来解决各种各样的人工智能的问题。

  

如上所示,在任何时间步(t),训练实体会得到一个环境的观察值(实例)。然后它会从所有可行动作中采取一种,并获得环境的奖励和下一个观察值。所以我们需要为训练实体提供算法,其所作出的决策应该是以最大化提升结束时的全部奖励为目的。

历史与状态

历史(History)是描述在环境和训练实体之间发生的所有事件的变量集合。

  

训练实体必须将历史映射到一个确切的动作中。对于环境,其必须将历史映射到需要发送的下一组观察值。因此,训练实体必须持续保持并储存大量的信息,这将占用大量的储存空间和处理时间。

所以,我们想创建历史的抽象表征,它可以储存足够的信息以便我们可以选择下一步动作,这也就是状态的概念。所以基本上系统的输出就取决于我们怎样定义状态。

在上式中,S 表征状态、f 表征一种能对时间步「t」的历史求和的函数。

上述表达式中,前一个代表训练实体的内部表征,其可以对历史求和并允许在以后采取动作。而后一个代表环境的内部表征,其允许发送下一个观察值。

马尔可夫状态(Markov State)

马尔可夫状态使用抽象形式储存过去所有的信息。所以如果训练实体预测未来的动作,其并不会使用全部的历史,而是使用马尔可夫状态。本质上来说,马尔可夫状态储存的信息并不比历史少。

所以在给定状态 St 的情况下求未来状态 St+1 的概率和给定前面所有状态求 St+1 的概率相同。这是因为状态 St 已经将前面所有状态的信息都嵌入了其中。

序列的游戏

  

现在假设有个游戏发生在餐厅里,餐厅提供三种食物:甜甜圈、饮料和三明治。现在顾客要求服务员带五样食品,且服务员会按顺序依次提供这五样食品。如果顾客喜欢这些食物的顺序,那么服务员将得到奖励,否则就会得到惩罚。现在服务员第一次提供食物的顺序如 S1 所示,他得到了奖励。

然而,当下一次服务员又以另一个顺序带来五份食品(S2)时,他得到了惩罚。那么现在第三个序列 S3 的输出是什么,奖励还是惩罚?

这里的解决方案取决于先前状态的定义。如果说状态的定义仅仅只是采用食物序列最后三项的顺序,那么根据 S1 最后三项的结果,S3 序列能获得奖励。然而如果根据每个食物出现的数量来定义,那么 S3 最有可能得到惩罚,因为 S2 和 S3 每一份食物的数量都相同。所以本质上系统的输出是依赖于状态的定义。

环境

如果你在电脑上玩自己编写的象棋,那么你就很清楚计算机是如何分析怎样下棋。所以基本上你知道在给定的行动下电脑确定的是哪一步棋。这是一种完全可观察的环境(Fully Observable Environment)。

现在如果你在玩由其他人编写的象棋游戏,你并不知道电脑下一步会怎么下。所以现在你能做的就是在下一步棋后观察电脑的下棋。这是一种部分可观察环境(Partially Observable Environment)。在这种情况下,你能做的就是预测游戏的内部动态,并期望能对其内部状态能有一个足够好的预测。

另外,根据周志华的《机器学习》,我们需注意「机器」与「环境」的界限。例如在种西瓜任务中,环境是西瓜生长的自然世界;在下棋对弈中,环境是棋盘与对手;在机器人控制中,环境是机器人的躯体与物理世界。总之,在环境中状态的转移、奖赏的返回是不受机器控制的,机器只能通过选择要执行的动作来影响环境,也只能通过观察转移后的状态和返回的奖赏来感知环境。

最后总结一下强化学习的概念,强化学习的输入 是:

  • 状态 (States) = 环境,例如迷宫的每一格就是一个状态

  • 动作 (Actions) = 在每个状态下,有什么行动是容许的

  • 奖励 (Rewards) = 进入每个状态时,能带来正面或负面的价值 (utility)

而输出就是:

  • 策略 (Policy) = 在每个状态下,你会选择哪个行动?

如上图所示,强化学习的思想主要:即训练实体 (Agent) 不断地采取动作 (action), 之后转到下一个状态 (State), 并且获得一个奖励 (reward), 从而进一步更新训练实体。

在了解了强化学习的基本概念后,我们就可以进一步理解 Q 学习(Q-Learning)的原理和实现。

下面我们将从迷宫寻宝游戏开始了解 Q 学习的基本概念。该游戏规则如下:

该游戏从一个给定的位置开始,即初始状态(starting state)。在每一个状态下训练实体都可以保留原地或选择向上、下、左、右移动,但不能穿越迷宫的边界。每个动作都将使得训练实体进入不同的单元格(即不同的状态)。现在在某个单元格有一个宝箱(即目标状态)。此外,迷宫的某些位置/状态有蛇。因此训练实体的目标就是通过寻找一条没有蛇的路径从起始状态走到目标状态。

现在当我们在网格中(即环境中)放置一个训练实体,它首先会开始探索。它最开始不知道蛇是什么,也不知道什么是宝箱或宝箱在哪。所以我们需要给定训练主体蛇和宝箱的概念,并在每一步动作后给予一定的奖励。对于每一块有蛇的单元格(状态),我们给予-10 的奖励,而对于宝藏,我们给予+10 的奖励。现在我们希望训练实体尽快完成任务(采取最短路径),因此我们给予其他状态-1 的奖励。最后我们给定训练实体的目标就是最大化最后累积得分。随着训练实体的探索,它会知道蛇是有害的,宝藏是有益的,并且它需要尽可能快地得到宝箱。上图中「-」就表示从起始状态到目标状态最短的路径。

Q 学习(Q-Learning)就尝试在给定状态下学习当前值,并采取特定的动作。

现在我们设计一张表格,其中每行是训练实体的状态,而每列是训练实体可能采取的动作。所以上例有 16×5 种可能的状态-行动对,其中每种状态都是迷宫中的一个单元格。

首先我们初始化矩阵(上文所述的 16×5 表格)为零矩阵,然后根据不同动作所获得的奖励更新矩阵的元素。当然,更新该矩阵的方法为计算贝尔曼方程(Bellman Equation):

「S」代表当前状态,「a」代表训练实体在当前状态下所采取的动作,「S'」代表采取该动作所产生的状态,「r'」是采取该动作所得到的奖励。贴现系数(discount factor)「γ」决定了训练实体对未来奖励的重视程度,γ越大,训练实体就会越重视以往经验,而γ越小,训练实体只重视眼前的利益。如果说训练实体向远离目标状态的状态运动,而该状态遇到蛇的概率减少,那么实时奖励将减少,未来奖励将增加,训练实体更注重未来的奖励。

我们将每次迭代(训练主体的尝试动作)作为一个 episode。对于每一次 episode,训练主体将尝试到达目标状态,并且对于每一次动作,Q 矩阵元素都会进行一次更新。

现在让我们了解一下 Q 矩阵是如何计算的(为了更简洁,我们采用更小的 2×2 迷宫):

Q 矩阵的初始状态如下(每行代表一个状态,每列代表一个动作):

U—向上走, D—向下走, L—向左走, R—向右走

奖励矩阵如下所示:

其中 E 代表空值(NULL,训练主体不能采取该动作)

算法:

  1. 初始化 Q 矩阵为零矩阵,设定「γ」值,完成奖励矩阵。

  2. 对于每一 episode,选择一个随机起始状态(在这个案例中,我们严格限制起始状态为-1)。

  3. 在当前状态(S)的所有可能动作中选择一个。

  4. 作为该动作(a)的结果,训练主体移往下一个状态(S')。

  5. 对于状态(S')产生的所有可能动作,选择 Q 值最大的动作。

  6. 使用贝尔曼方程(Bellman Equation)更新 Q 矩阵。

  7. 将下一个状态设置为当前状态。

  8. 如果到达目标状态,结束算法。

我们可以从以下一段伪代码进一步理解:

现在假设训练主体从状态 1 开始,其可以采取动作 D 或 R。如果采取了动作 D,那么训练主体到达状态 3(蛇),并可以采取动作 U 或 R。现在取值γ = 0.8,那么方程有:

Q(1,D) = R(1,D) + γ*[max(Q(3,U) & Q(3,R))]

Q(1,D) = -10 + 0.8*0 = -10

其中,因为 Q 矩阵还没有更新,max(Q(3,U) & Q(3,R)) = 0。设定踩上蛇的奖励为-10。现在新的 Q 矩阵的值就如下所示:

现在,状态 3 为当前状态,从状态 3 采取了动作 R。训练主体就到达状态 4,并其可以采取动作 U 或 L。

Q(3,R) = R(3,R) + 0.8*[max(Q(4,U) & Q(4,L))]

Q(3,R) = 10 + 0.8*0 = 10

再一次更新 Q 矩阵的值:

所以,现在训练主体到达目标状态 4。接下来终止该进程,并进行更多的训练直到训练主体理解了所有状态和动作,且所有的 Q 矩阵元素成为常数。这也就意味为训练主体已经尝试了所有的状态-动作对。

OpenAI Gym由两部分组成:
1.gym开源库:一个测试问题集合—环境(environment),可以用于自己的强化学习算法开发,这些环境有共享的接口,允许用户设计通用的算法
2.OpenAI Gym服务: 一个站点和API,允许用户对他们训练的算法进行性能比较。

运行一个环境来体验一下OpenAI Gym

Cart-Pole世界包括一个沿水平轴移动的车和一个固定在车上的杆子。 在每个时间步,你可以观察它的位置(x),速度(x_dot),角度(theta)和角速度(theta_dot)。 这是这个世界的可观察的状态。 在任何状态下,车只有两种可能的行动:向左移动或向右移动。
换句话说,Cart-Pole的状态空间有四个维度的连续值,行动空间有一个维度的两个离散值。

运行一个CartPole-v0环境的实例1000步,在每一步渲染环境。 你会看到一个弹出的窗口,呈现出经典的倒立摆问题:

要开始运行,您需要先安装Python 3.5+的版本。在windows的cmd命令窗口下,使用pip安装gym:

pip install gym

从源代码构建

如果你愿意,你也可以直接克隆健身房的Git仓库。下载并安装使用:

git clone https://github.com/openai/gym
cd gym
pip install -e .

接下来演示程序例子:

import gym
env = gym.make('CartPole-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample()) # take a random action
其中env.reset()重置环境的状态,env.render()重绘环境的一帧。

程序效果:

这是一个典型的"agent-environment loop"的实现。每一个时间步,Agent选择一个action,Environment返回一个observation和reward。 

该进程通过调用reset来启动,它返回一个初始observation。 所以编写上面代码的更恰当的方法是遵守done的标志:

import gym
env = gym.make('CartPole-v0')
#env = gym.make('MountainCar-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(1000):
        env.render()
        print(observation)
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after  timesteps".format(t+1))
            break
运行结果:

当done 为真时,控制失败,此阶段episode 结束。可以计算每 episode 的回报就是其坚持的t+1 时间,坚持的越久回报越大,在上面算法中,agent 的行为选择是随机的,平均回报为20 左右。
替换库之后: 例子2:
import gym
#env = gym.make('CartPole-v0')
env = gym.make('MountainCar-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(1000):
        env.render()
        print(observation)
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after  timesteps".format(t+1))
            break

运行程序:

环境

gym主要目的是提供一个大的环境集合,暴露一个通用接口,并进行版本控制来比较,你可以查看系统提供环境:

找到最佳的策略

在Cart-Pole环境下,只要杆子还是挺直的,车还在边界内,你就可以获得奖励。 一旦杆子超过某个角度,或者车子向左或向右偏离太远,游戏就会结束。 当它连续100次直立超过195个时间步,这个问题被认为解决了,
一个策略就是你在特定状态下所采取的行动。 在这里,你想找到可以最大化你的奖励的策略。 换句话说,你想为每个可能的状态找到最佳政策。

Q-Learning

Q-Learning就是找到这些最优策略的一种方法。本质上,通过试错法,你可以找到每个状态-行动对的Q值。 这个Q值表示在当前状态下一个行动的可取性。 随着时间的推移,如果世界是静态的(即物理或因果不变),则Q值会收敛,给定状态的最优策略将是具有最大Q值的行动。
要使用Q-Learning,您必须将连续维度离散到多个桶。 一般来说,你想要有更少的桶,并保持尽可能小的状态空间。 找到更少的最优政策意味着更快的训练。 然而,将状态空间过于粗糙地离散化可能会阻止收敛,因为重要的信息可能会被离散化。

DQN(Deep Q Network)

Deep Q Network的简称叫DQN,是将Q learning的优势和Neural networks结合了。如果我们使用tabular Q learning,对于每一个state,action我们都需要存放在一张q_table的表中。但在现实生活中,我们有千千万万个state,如果将这千万个state的值都放在表中,受限于我们计算机硬件,这样从表中获取数据,更新数据是没有效率的。这就是DQN产生的原因了。我们可以使用神经网络来估算这个state的值,这样就不需要一张表了.

 

以上是关于深度强化学习的主要内容,如果未能解决你的问题,请参考以下文章

深度学习--基于深度矩阵分解的属性表征学习

深度学习--基于深度矩阵分解的属性表征学习

连接因果科学与深度学习的桥梁:因果表征学习读书会启动

深度学习,NLP和表征(译)

强化学习、深度学习和深度强化学习有啥区别?

深度学习自然语言处理和表征方法