用Python和TensorFlow进行强化学习的指南

147 阅读20分钟

订阅并获得免费指南 - 使用Python的终极数据可视化指南

*表示需要

电子邮件地址*

在前两篇文章中,我们开始探索强化学习这个有趣的领域。首先,我们了解了机器学习中第三种范式的基础知识------。 强化学习.为了更新我们的记忆,我们看到这种类型的学习方法不同于之前探索的 监督 和**无监督的学习。在强化学习中,自学代理** 学习如何与环境 互动并解决其中的问题。

在这篇文章中,我们介绍了强化学习的完整指南,以及其中一种类型的Q-Learning(在深度学习的帮助下成为深度Q-Learning)。我们了解这种类型的学习背后的灵感,并通过PythonTensorFlowTensorFlow代理实现它。

Ultimate Guide to Machine Learning with Python

这捆电子书是专门为 初学者制作的 。
从Python基础知识到机器学习算法在生产中的部署,一切都在一个地方。
今天就成为一个机器学习的超级英雄 吧!

以下是我们在这篇文章中涉及的主题。

  1. 强化学习简介
  2. Q-Learning的直观性
  3. 用Python实现Q-Learning
  4. 深度-Q学习的直观性
  5. 用TensorFlow实现深Q学习

1.强化学习简介

爱德华观察他的猫,因为它们试图从自制的 拼图箱中逃脱。拼图是 ,猫咪只需要拉一下绳子或按一下投票器就可以出来了。 当第一次遇到谜题时,猫花了很长时间 ,以解决这个问题。然而,当遇到相同或类似的问题时,猫就能更快地解决它并逃脱 。他想出了一个术语 ,即效果法则,其中指出。

在某一特定情况下产生满意效果的反应在该情况下更有可能再次出现,而产生不适效果的反应在该情况下更不可能再次出现。

对了,我是不是忘了说这是1898年,而我们谈论的是心理学家爱德华-L-桑代克?大约在这个时候,伊万-巴甫洛夫用他的狗做了实验,并提出了他的诺贝尔价格理论**:** 古典条件反射。他注意到他的狗看到喂它的人就会流口水,尽管那里没有食物。

Reinforcement Learning - Cat

后来,在20世纪,B.F.斯金纳采用这两种方法,发明了操作性条件反射室,或 "斯金纳箱"。与爱德华-桑代克的谜题不同,这个盒子只给受试者(在这种情况下是小鼠)一两个简单的可重复选项。利用这些实验的数据,他和他的同事们将 操作性条件反射定义为一个学习过程,其中行为的强度由 强化 或惩罚来改变。

我们为什么要谈论这些?除了我们想成为著名的心理学家就需要养宠物之外,这对我们有什么意义?这一切与人工智能有什么关系? 好吧,这些话题探讨的是一种学习方式,在这种学习方式中,一些主体与 ,与 环境进行互动。这也是我们人类的学习方式。当我们还是婴儿时,我们 实验。

我们做了一些动作,从环境中得到了 反应 。如果反应是积极的**(奖励**),我们就重复这些动作,否则**(惩罚**)我们就停止做这些动作。在这篇文章中,我们将探讨 强化学习,这种学习类型是受这种目标导向的互动学习的启发。

1.1 强化学习基础知识

我们在这个网站上写了许多类型的 机器学习 ,主要集中在 监督学习 和 无监督学习。与这些类型的学习不同,强化学习有一个不同的范围。简而言之,它试图解决一个 不同类型的 问题。这种类型的学习观察一个正在环境中执行某些行动的代理,并根据它从这些行动中获得的奖励来模拟它的行为。它与上述两种类型的学习不同。

监督学习中,一个代理学习如何 某些输入映射到某些输出。代理人学习如何做到这一点,因为在学习过程中,它被提供给 训练输入 和 标记的这些输入的预期输出 。使用这种方法,我们能够解决许多类型的问题,主要是那些性质上的分类和回归问题。这是一种重要的学习类型,今天它主要被用于 商业 方法。

Supervised Learning Process

另一种类型的学习是 无监督学习。在这种类型的学习中,代理只被提供给 输入数据,它需要从中找出某种意义。代理人基本上是试图在其他非结构化的数据中找到 模式 。这种类型的问题通常用于分类或集群类型的问题。

人们可能会认为强化学习与无监督学习 ,因为它们在学习过程中没有预期的结果提供给它们,然而,它们在概念上 。在强化学习中,代理试图使它得到的奖励最大化,而不是寻找隐藏的模式。

正如你所看到的,这些类型的学习都没有像强化学习那样解决与环境互动的问题。这就是为什么这种类型的学习被认为是机器学习的第三范式。许多论文实际上认为,这种类型的学习是人工智能的未来。如果你考虑到这是一种自然选择的工具,这可能是真的。

Reinforcement Learning Process

好了,我们花了很多时间来讨论强化学习不是什么,现在让我们看看它是什么。 如前所述,这种类型的学习意味着 主动 代理 和其环境之间的 互动。该代理试图 在该环境中实现一个确定的 目标

代理人的每一个行动都会使环境处于不同的 状态 ,并影响代理人的未来选择和机会主义者。由于行动的效果无法预测,因为环境的不确定性,代理人必须监测它。你已经可以确定强化学习的一些主要元素。然而,还有一些隐藏的要素。

1.2 强化学习的主要内容

到目前为止,我们谈了很多关于 代理 和 环境。除此之外,我们还提到,代理正在执行 行动 ,改变环境的 状态 。有一些额外的强化学习元素,正在更详细地解释这个过程。它们是。

  • 奖赏
  • 政策
  • 价值函数

让我们深入了解它们的更多细节。

1.2.1 奖赏

这个元素定义了 代理人的 目标 。从本质上讲,我们把整个过程分成几个 时间步骤 ,我们认为在每个时间步骤中,代理人都要执行一些行动。在每个行动之后,环境 会改变 其状态,并以数字的形式给代理一个奖励。

这个数字取决于代理人在时间步骤 t中的行动 ,但也取决于环境在时间框架 t中的状态 。这样,代理人可以通过两种方式影响奖励。它可以 直接 通过自己的行动 获得更好的奖励 ,也可以 通过改变环境的状态 间接地 获得 奖励 。 简而言 之,奖励定义了行动是好是坏,代理人试图 在一段时间内使奖励最大化

Reinforcement Learning Process

1.2.2 政策

政策是 强化学习的 核心 元素。它定义了代理人在特定环境状态下要执行的行动。本质上,它 环境状态映射 到代理的行动。

这个元素也是从心理学中得到的灵感,它对应于 "一套刺激-反应规则"。乍一看,政策似乎只是一个简单的表格或函数。然而,事情可能要比这复杂得多,政策可能是随机的。

1.2.3 价值函数

我们已经定义了在每个状态下,代理人根据前一个时间步骤中的行动和环境状态获得一定的 奖励 。代理人观察到的奖励是 ,即处于某种状态的即时可取性 。意思是说,如果我们和人类做个类比,奖励就是短期目标。

与奖励不同, 价值函数 为代理人定义了一个 长期目标 。状态的 ,表示从该状态开始,代理人在未来可以积累的奖励量。该值代表对奖励的 预测。实质上,代理人将其观察为处于某种状态的长期可取性。

从代理人的角度来看,奖励是主要目标,而价值是次要的。这是由于环境的随机性造成的。然而,关于下一步将采取何种行动的决定总是基于 值。这意味着,代理人总是试图进入具有最高价值的状态,因为这意味着这将在 长期内获得更多的奖励。就像我们人类一样。

1.3 马尔可夫决策过程

现在,当我们知道这些元素后,我们对强化学习有了更好的了解。代理人在离散的时间步骤中与环境互动,在每个步骤中应用行动。基于该行动,环境将改变其状态,并给予某种数字形式的奖励。代理人将使用价值函数,并试图提出将奖励最大化的政策。强化学习实际上就是要解决这个问题。

为了在数学上表示这个 ,我们使用一个叫做 马尔科夫决策过程 (MDPs)的框架。几乎所有的强化学习问题都可以用这个框架进行形式化。一般来说,MDPs用于建模决策,其中决策的结果部分是随机的,部分是由决策者控制的。这对强化学习来说是完美的。在这篇文章中,我们观察的是 有限 MDPs。意思是说,环境可以处于的状态数量和代理人可以采取的行动数量是有限的。

Markov Decision Process

马尔科夫决策过程是 四个元素*(S*, A, Pa, Ra)组成的元组

  • S - 代表 的状态集。在每个时间步骤 t,代理人得到环境的状态 - St,其中 St∈S。
  • A - 代表代理人可以预见的 行动集合 。在每个时间步骤 t,根据收到的状态 St,代理人决定执行一个行动-- At,其中 At∈A(St)。 A(St) 代表状态 St中可能的行动的集合。
  • Pa - 代表了 概率 即在某个状态下的行动 s ,将在时间步骤 t, ,将在时间步骤 s' , t+1。

  • Ra - 或者更确切地说 Ra(s, s'), 代表 从状态s 到状态 s'后,由于行动 a而得到的预期奖励

正如我们所提到的,我们试图用MDP形式化的问题是我们为代理人寻求 最佳政策的问题 。政策被定义为函数 π,它将每个状态 s∈S,以及行动 a∈A(s),映射为在状态 s时采取行动a的概率 π(a|s) 。

使用政策函数 π,我们可以定义一个状态 s - *Vπ(s)*的价值,作为从状态 s 并遵循政策π时的 预期奖励 。更正式地,它可以这样写。

这个函数 Vπ(s) 被称为政策π的 状态价值函数 。与此类似,我们可以定义在政策π下的状态 a ,作为预期奖励,如果代理人从状态 s开始*,* 采取行动 a 并遵循政策π - *(s, a) 。*

2.Q-学习的直观性

Q-Learning 是所谓的强化学习的表格解决方案的一部分,或者更准确地说,它是一种 时间差 算法。

这些类型的算法不对整个环境进行建模,而是直接从环境动态中学习。除此之外,他们根据以前的估计更新他们的估计,所以他们不需要等待过程的最终结果。

2.1 时差学习

最简单的时差形式通常被表示为TD(0)。它的数学公式是这样的。

其中α是一个学习率。这意味着这种方法将等到下一个时间步骤t+1 ,并使用该时间步骤的奖励和估计值来更新时间步骤t的值。*TD(0)*是这样执行的。

  1. 从状态集S任意初始化 每个状态的值:
    V(s) = n, ∀s∈S。
  2. 从政策π为该状态定义的行动集A(s)挑选 行动a
  3. 执行 行动a
  4. 观察 奖励R和下一个状态s'
  5. 使用公式更新 该状态的值:
    V (s) ← V (s) + α [R + γV(s') - V (s)]
  6. 在每个时间步骤中重复 步骤2-5,直到达到终端状态。
  7. 对每个事件重复 第2-6步

Markov Decision Process

正如你所看到的,这种方法部分地在其他估计的基础上学习他们的估计。这就是更有经验的人工智能工程师喜欢称之为引导的 东西*。* 它指的是一种情况,即算法从一个猜测中学习一个 猜测。

这与Q-Learning有什么关系?嗯,Q-Learning是在时差学习的基础上更进一步。事实上,他们不仅仅是在学习如何从另一个猜测中猜测,而是在不考虑 政策的情况下做这件事。

2.1 Q-学习的基本原理

正如你所看到的,时差学习是基于其他估计值的估计。 Q学习 则更进一步,它是 在 政策π- q 下, 估计上述 在状态 s 下 采取行动 a 的价值 , 这就是它名字的由来*。* 基本上,这种方法的决策是基于对 状态-行动 对 的 估计 ,而不是 状态-价值 对。它的最简单的形式被称为一步式 Q学习 ,其定义是这样的。

一个特定的状态-动作组合的Q值可以被观察为从该状态采取的行动的质量。正如你所看到的,策略仍然决定了哪些状态-动作对被访问和更新,但仅此而已。这就是为什么Q-Learning有时被称为非政策性TD学习。

所有这些Q值都存储在Q表内Q表只是一个矩阵 ,其行代表状态,列代表行动。这个表由代理更新,看起来像这样。

Reinforcement Learning Q-Learning Table

让我们把Q-Learning分解成几个步骤。

  1. 初始化 Q表中的所有Q值为任意,终端状态的Q值为0:
    Q(s, a) = n, ∀s∈S,∀a∈A(s)
    Q(终端状态, -) = 0
  2. 从政策π为该状态A(s)定义的行动集合中挑选 行动a
  3. 执行 行动a
  4. 观察奖励R和下一个状态s'
  5. 对于所有可能的行动,从状态*s'*中选择一个具有最高 Q值的行动--a'。
  6. 使用公式更新 状态的值:
    Q(s, a) ← Q(s, a) + α [R + γQ(s', a') - Q(s, a)]
  7. 在每个时间步骤中重复 步骤2-5,直到达到终端状态。
  8. 对每个情节重复 步骤2-6

经过一段时间和足够的随机探索行动,Q值 倾向于收敛为我们的代理服务,作为我们之前提到的行动价值函数。需要注意的是,有时我们会添加额外的约束条件 ,以阻止过度拟合

基本上,我们使用epsilon值来定义我们是否会探索新的行动,也许会有更好的解决方案,或者我们会采用已经学到的路线。这个参数定义了探索 新方案和利用 已学方案之间的关系。

Reinforcement Learning with Q-Table

当然,Q-Learning的问题是扩展性。当我们谈论复杂的环境时,就像规划视频游戏一样,状态和行动的数量会增加。对于这个问题,表格成为一个复杂的 方法。这就是人工神经网络发挥作用的地方。然而,后面会有更多关于这个问题的内容。让我们首先用Python实现Q-Learning。

3.用Python实现Q-Learning

3.1 先决条件

为了运行这段代码,你必须 在你的机器上安装 Python 3 。在这个例子中,我们使用的是 Python 3.7。 此外,你还必须安装 Open AI Gym ,或者更具体地说 ,Atari Gym。你可以通过运行来安装它。

pip install gym[atari]

如果你使用的是Windows,那就不是这么简单了,所以你可以按照这篇文章来正确安装它。

Open AI Gym有它自己的API和它的工作方式。由于这完全是另一个话题,我们将不深入讨论如何从代码中与环境进行交互。我们会在接下来提到一些重要的话题,这些话题对于理解代码很重要。然而,我们强烈建议你,如果你不熟悉Open AI Gym的概念和API,可以看看这篇文章

3.2 OpenAI环境

我们将使用名为 Taxi-V2 的Gym环境 。这是一个 非常简单的 环境,几乎就像'Hello world'的例子。它的出现是为了说明分层强化学习的一些问题。从本质上讲, 环境中有 4个地点 ,目标是在一个地点接乘客,在另一个地点送他。代理人可以执行 6个动作 (南、北、西、东、接、送)。你可以 在这里 找到更多关于它的信息 。

让我们看看如何用Q-Learning来解决它。

3.3 用Python实现

我们将首先 导入 必要的库和模块。

import numpy as np
import random
from IPython.display import clear_output
import gym

正如你所看到的,我们正在导入 numpy 模块--Python的数值运算模块和 gym 模块--Open AI Gym库。除此以外,我们使用 随机IPython.display 进行简单的操作。然后,我们需要 创建 一个环境。这是这样做的。

enviroment = gym.make("Taxi-v2").env
enviroment.render()

print('Number of states: {}'.format(enviroment.observation_space.n))
print('Number of actions: {}'.format(enviroment.action_space.n))

我们使用make函数来实例化一个我们想要的环境对象 。在这个例子中,那就是Taxi-v2环境。我们可以用渲染方法显示环境和代理的当前状态。重要的是,我们可以用observation_space属性访问环境的所有状态,用action_space访问环境的所有动作。

这里我们有500个状态和6个可能的动作。除了这些方法之外,Open Gym API还有两个我们需要提到的方法。第一个是reset方法,它重设 环境并返回一个随机的初始状态。另一个是step方法,该方法使环境前进 了一个时间段并执行了 一个动作。

现在我们可以继续进行代理的训练了。让我们首先初始化必要的变量。

alpha = 0.1
gamma = 0.6
epsilon = 0.1
q_table = np.zeros([enviroment.observation_space.n, enviroment.action_space.n])

然后,我们使用前一章中提到的步骤进行训练。

num_of_episodes = 100000

for episode in range(0, num_of_episodes):
    # Reset the enviroment
    state = enviroment.reset()

    # Initialize variables
    reward = 0
    terminated = False
    
    while not terminated:
        # Take learned path or explore new actions based on the epsilon
        if random.uniform(0, 1) < epsilon:
            action = enviroment.action_space.sample()
        else:
            action = np.argmax(q_table[state])

        # Take action    
        next_state, reward, terminated, info = enviroment.step(action) 
        
        # Recalculate
        q_value = q_table[state, action]
        max_value = np.max(q_table[next_state])
        new_q_value = (1 - alpha) * q_value + alpha * (reward + gamma * max_value)
        
        # Update Q-table
        q_table[state, action] = new_q_value
        state = next_state
        
    if (episode + 1) % 100 == 0:
        clear_output(wait=True)
        print("Episode: {}".format(episode + 1))
        enviroment.render()

print("**********************************")
print("Training is done!\n")
print("**********************************")

注意 我们添加的epsilon 值,以便区分过期和探索。其余的实现方式基本是直截了当的。最后,我们可以评估我们训练的模型。

total_epochs = 0
total_penalties = 0
num_of_episodes = 100

for _ in range(num_of_episodes):
    state = enviroment.reset()
    epochs = 0
    penalties = 0
    reward = 0
    
    terminated = False
    
    while not terminated:
        action = np.argmax(q_table[state])
        state, reward, terminated, info = enviroment.step(action)

        if reward == -10:
            penalties += 1

        epochs += 1

    total_penalties += penalties
    total_epochs += epochs

print("**********************************")
print("Results")
print("**********************************")
print("Epochs per episode: {}".format(total_epochs / num_of_episodes))
print("Penalties per episode: {}".format(total_penalties / num_of_episodes))

我们可以看到,我们的代理没有出错,也就是说,它在好的地点接了100次乘客,并把他们掺了进去。

4.深度Q-Learning的直觉

深度Q-学习利用所谓的深度Q-网络来发挥深度学习的力量。这些是标准的**前馈神经网络**,用于计算Q值。在这种情况下,代理必须将以前的经验存储在本地存储器中,并使用神经网络的最大输出来获得新的Q值

Reinforcement Learning Deep-Q Learning

这里需要注意的是,深层Q网络不使用标准的**监督学习,只是因为我们没有标记的预期输出**。我们依赖于强化学习中的策略或价值函数,所以目标 在每次迭代中不断变化。

由于这个原因,代理不只使用一个神经网络,而是两个 。那么,这一切是如何结合起来的呢?第一个网络,称为Q-网络,在状态St下计算Q值,而另一个网络,称为目标网络,在状态St+1下计算Q值

更正式地讲*,* 给定当前状态 St,Q-网络检索行动值 Q(St,a)。同时,目标网络使用下一个状态 St+1来计算时差目标Q(St+1, a)

为了稳定 两个网络的训练,在每个N次迭代中,Q网络的参数被复制到 目标网络中。整个过程显示在下面的图片中。

Reinforcement Learning Deep-Q Learning Two Networks

我们已经提到,代理必须存储 以前的经验。Deep Q-Learning更进一步,利用一个更多的概念来提高代理的性能--经验重放。经验证明,当在随机 的一批以前的经验上进行训练时,神经网络的训练过程更加稳定。经验重放只不过是将这些经验以元组的形式存储起来的存储器 <s, s', a, r>.:

  • s- 代理人的状态
  • a- 代理人在该状态下采取的行动 s 所采取的行动
  • r- 在状态下收到的即时奖励 s 的奖励a
  • s'- 状态后代理人的下一个状态 s

两个网络都使用随机批次的 <s, s', a, r>。*来计算Q值,然后进行反向传播损失 的计算是使用目标* Q值预测 Q值之间的平方差。

请注意,这只是为Q网络训练 而进行的,而参数是在以后转移目标网络的。

总结一下,我们可以把整个深度Q-学习的过程分成几个步骤。

  1. 向代理提供环境的状态。代理人使用目标网络和Q网络来获得定义状态下所有可能行动的Q值
  2. 根据epsilon 值,挑选 行动a。意思是,要么选择一个随机行动(探索),要么选择具有最大Q值的行动(利用)。
  3. 执行 行动a
  4. 观察奖励r和下一个状态s'
  5. 这些信息存储 在经验回放存储器中<s, s', a, r>。
  6. 从经验回放存储器中抽取 随机批次,进行Q网络训练
  7. 每隔N次迭代, 权重值从Q-网络 复制到 目标网络中。
  8. 对每个情节重复 步骤2-7

5.用Python和TensorFlow实现深度Q-Learning

在这个例子中,我们使用与Q-Learning实现相同的环境。首先,我们导入所有必要的模块和库。

import numpy as np
import random
from IPython.display import clear_output
from collections import deque
import progressbar

import gym

from tensorflow.keras import Model, Sequential
from tensorflow.keras.layers import Dense, Embedding, Reshape
from tensorflow.keras.optimizers import Adam

注意,除了像numpytensorflowgym这样的标准库和模块,我们还从collection中导入了deque。我们将使用它来体验重放内存。在这之后,我们可以创建环境

enviroment = gym.make("Taxi-v2").env
enviroment.render()

print('Number of states: {}'.format(enviroment.observation_space.n))
print('Number of actions: {}'.format(enviroment.action_space.n))

我们使用make函数来实例化Taxi-v2环境的一个对象 。环境和代理的当前状态可以通过render方法来呈现。重要的是,我们可以使用observation_space属性访问环境的所有状态,使用action_space访问环境的所有动作。

这个环境有500个状态6个可能的动作。除了这些方法之外,Open Gym API还有两个我们需要提到的方法。第一个是reset方法,它重设 环境并返回一个随机的初始状态。另一个是step方法,该方法 环境分为一个时间步长并执行 一个动作。

在这之后,我们终于可以实现代理了。Deep Q-Learning代理是在代理类中实现的。下面是它的样子。

class Agent:
    def __init__(self, enviroment, optimizer):
        
        # Initialize atributes
        self._state_size = enviroment.observation_space.n
        self._action_size = enviroment.action_space.n
        self._optimizer = optimizer
        
        self.expirience_replay = deque(maxlen=2000)
        
        # Initialize discount and exploration rate
        self.gamma = 0.6
        self.epsilon = 0.1
        
        # Build networks
        self.q_network = self._build_compile_model()
        self.target_network = self._build_compile_model()
        self.alighn_target_model()

    def store(self, state, action, reward, next_state, terminated):
        self.expirience_replay.append((state, action, reward, next_state, terminated))
    
    def _build_compile_model(self):
        model = Sequential()
        model.add(Embedding(self._state_size, 10, input_length=1))
        model.add(Reshape((10,)))
        model.add(Dense(50, activation='relu'))
        model.add(Dense(50, activation='relu'))
        model.add(Dense(self._action_size, activation='linear'))
        
        model.compile(loss='mse', optimizer=self._optimizer)
        return model

    def alighn_target_model(self):
        self.target_network.set_weights(self.q_network.get_weights())
    
    def act(self, state):
        if np.random.rand() <= self.epsilon:
            return enviroment.action_space.sample()
        
        q_values = self.q_network.predict(state)
        return np.argmax(q_values[0])

    def retrain(self, batch_size):
        minibatch = random.sample(self.expirience_replay, batch_size)
        
        for state, action, reward, next_state, terminated in minibatch:
            
            target = self.q_network.predict(state)
            
            if terminated:
                target[0][action] = reward
            else:
                t = self.target_network.predict(next_state)
                target[0][action] = reward + self.gamma * np.amax(t)
            
            self.q_network.fit(state, target, epochs=1, verbose=0)

我们知道,这是个很大的代码。让我们把它分割开来,探索其中的一些重要部分。当然,整个代理是在构造函数中初始化的。

def __init__(self, enviroment, optimizer):      
  # Initialize atributes
  self._state_size = enviroment.observation_space.n
  self._action_size = enviroment.action_space.n
  self._optimizer = optimizer

  self.expirience_replay = deque(maxlen=2000)

  # Initialize discount and exploration rate
  self.gamma = 0.6
  self.epsilon = 0.1

  # Build networks
  self.q_network = self._build_compile_model()
  self.target_network = self._build_compile_model()
  self.alighn_target_model()

首先,我们根据传递给这个代理的环境对象,初始化状态行动空间的大小。我们还初始化了一个优化器 和经验回复存储器。然后,我们用_build_compile_model方法建立Q网络目标网络,并用alighn_target_model方法调整 其权重。_build_compile_model方法可能是整个实现中最有趣的一个,因为它包含了实现的核心 。让我们来偷看一下它。

def _build_compile_model(self):
    model = Sequential()
    model.add(Embedding(self._state_size, 10, input_length=1))
    model.add(Reshape((10,)))
    model.add(Dense(50, activation='relu'))
    model.add(Dense(50, activation='relu'))
    model.add(Dense(self._action_size, activation='linear'))

    model.compile(loss='mse', optimizer=self._optimizer)
    return model

我们看到,这个模型中使用的第一个层是嵌入层。这一层最常用于语言处理,所以你可能很好奇它在这里做什么。我们在Taxi-v2环境中面临的问题是,它为状态返回离散值(单一数字)。这意味着我们需要减少潜在值的数量。

嵌入 层中,参数input_dimensions指的是我们拥有的值的数量,output_dimensions指的是我们要减少的向量空间。总而言之,我们想用10个值来表示500个可能的状态,嵌入层正是用于此。在这一层之后,重塑 层为具有三个密集层的前馈神经网络准备 数据。

我们在前一章中提到的整个征用-探索的概念是在行为函数中完成的。基于epsilon值,我们要么调用Q-Network进行预测,要么挑选一个随机 动作。就像这样。

def act(self, state):
    if np.random.rand() <= self.epsilon:
        return enviroment.action_space.sample()

    q_values = self.q_network.predict(state)
    return np.argmax(q_values[0])

最后,让我们来看看重新训练的方法。在这个方法中,我们从经验回放存储器中挑选随机样本,训练Q-Network

def retrain(self, batch_size):
    minibatch = random.sample(self.expirience_replay, batch_size)

    for state, action, reward, next_state, terminated in minibatch:

        target = self.q_network.predict(state)

        if terminated:
            target[0][action] = reward
        else:
            t = self.target_network.predict(next_state)
            target[0][action] = reward + self.gamma * np.amax(t)

        self.q_network.fit(state, target, epochs=1, verbose=0)

现在,当我们意识到代理类的实现时,让我们创建一个它的对象并准备进行训练。

optimizer = Adam(learning_rate=0.01)
agent = Agent(enviroment, optimizer)

batch_size = 32
num_of_episodes = 100
timesteps_per_episode = 1000
agent.q_network.summary()

从我们这个代码样本的输出中,我们可以看到代理中的网络结构。

现在,让我们使用前一章中解释的步骤 来运行训练。

for e in range(0, num_of_episodes):
    # Reset the enviroment
    state = enviroment.reset()
    state = np.reshape(state, [1, 1])
    
    # Initialize variables
    reward = 0
    terminated = False
    
    bar = progressbar.ProgressBar(maxval=timesteps_per_episode/10, widgets=\
[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()])
    bar.start()
    
    for timestep in range(timesteps_per_episode):
        # Run Action
        action = agent.act(state)
        
        # Take action    
        next_state, reward, terminated, info = enviroment.step(action) 
        next_state = np.reshape(next_state, [1, 1])
        agent.store(state, action, reward, next_state, terminated)
        
        state = next_state
        
        if terminated:
            agent.alighn_target_model()
            break
            
        if len(agent.expirience_replay) > batch_size:
            agent.retrain(batch_size)
        
        if timestep%10 == 0:
            bar.update(timestep/10 + 1)
    
    bar.finish()
    if (e + 1) % 10 == 0:
        print("**********************************")
        print("Episode: {}".format(e + 1))
        enviroment.render()
        print("**********************************")

你可以注意到,这个过程与我们在前一章探讨的标准Q-Learning的训练过程相当相似

总结

在这篇文章中,我们探讨了深度Q-Learning。这是第一种利用神经网络的强化学习。通过这个方法,我们解决了标准Q-Learning的扩展问题,为更复杂的系统铺平了道路。

谢谢您的阅读!

Ultimate Guide to Machine Learning with Python

这套电子书是专门为 初学者设计的 。
从Python基础知识到机器学习算法在生产中的部署,一切都在一个地方。
今天就成为机器学习的超级英雄 吧!

Nikola M. Zivkovic

Nikola M. Zivkovic

Nikola M. Zivkovic是 书籍的作者 。 机器学习终极指南程序员的深度学习.他喜欢知识分享,他是一个经验丰富的演讲者。你可以看到他在 聚会、会议上发言 ,也可以在诺维萨德大学担任客座讲师。

Ultimate Guide to Machine Learning with Python

这套电子书是专门为 初学者设计的 。
从Python基础知识到机器学习算法在生产中的部署,所有内容都在一个地方。
今天就成为一个机器学习的超级英雄 吧!

分享。