原文:
annas-archive.org/md5/e3819a6747796b03b9288831f4e2b00c
译者:飞龙
协议:CC BY-NC-SA 4.0
在前几章中,我们研究了强化学习(RL)算法,从基于价值的方法到基于策略的方法,以及从无模型方法到基于模型的方法。在本章中,我们将提供另一种解决序列任务的方法,那就是使用一类黑盒算法——进化算法(EA)。EAs 由进化机制驱动,有时比强化学习(RL)更受青睐,因为它们不需要反向传播。它们还为 RL 提供了其他互补的好处。本章将从简要回顾强化学习(RL)算法开始,帮助你更好地理解 EA 如何融入这些问题解决方案中。接着,你将了解 EA 的基本构建模块及其工作原理。我们还将利用这个介绍,深入研究其中一种最著名的进化算法——进化策略(ES)。
由 OpenAI 开发的一种近期算法大大推动了进化策略(ES)在解决序列任务中的应用。它们展示了 ES 算法如何能够在多个 CPU 上进行大规模并行化并线性扩展,同时实现高性能。在解释了进化策略后,我们将更深入地探讨这个算法,并在 TensorFlow 中进行开发,这样你就可以将它应用于你关心的任务。
本章将涵盖以下主题:
超越强化学习(RL)
EAs 的核心
可扩展的进化策略
可扩展的进化策略应用于 LunarLander
强化学习(RL)算法通常是我们面对序列决策问题时的首选。通常,除了使用 RL,很难找到其他方法来解决这些任务。尽管有数百种不同的优化方法,但到目前为止,只有 RL 在序列决策问题上取得了良好的效果。但这并不意味着它是唯一的选择。
本章将从回顾强化学习(RL)算法的内在工作原理开始,并质疑其组件在解决序列任务中的有效性。这个简要总结将帮助我们介绍一种新的算法类型,该算法提供了许多优点(以及一些缺点),可以作为 RL 的替代方案。
在开始时,策略被随机初始化,并用来与环境交互,收集数据,交互可以是给定的步数或整个轨迹。在每次交互中,访问的状态、采取的行动和获得的奖励都会被记录下来。这些信息提供了代理在环境中影响的完整描述。然后,为了改进策略,基于损失函数的反向传播算法(为了将预测值移向更好的估计)计算网络每个权重的梯度。接着,这些梯度会通过随机梯度下降优化器进行应用。这个过程(从环境中收集数据并使用随机梯度下降(SGD)优化神经网络)会一直重复,直到满足收敛标准为止。
这里有两件重要的事情需要注意,它们在接下来的讨论中会非常有用:
时序信用分配:因为强化学习算法在每一步优化策略,所以需要对每个行动和状态分配质量。这是通过为每个状态-行动对分配一个值来完成的。此外,使用折扣因子来最小化远距离行动的影响,并给予最后行动更多的权重。这将帮助我们解决将信用分配给行动的问题,但也会引入系统中的不准确性。
探索:为了保持一定程度的探索,额外的噪声会被注入到强化学习算法的策略中。噪声注入的方式依赖于算法,通常情况下,行动是从一个随机分布中采样的。这样做的目的是,如果代理处于相同的情境两次,它可能会采取不同的行动,进而导致两条不同的路径。这种策略也能在确定性环境中鼓励探索。通过每次偏离路径,代理可能会发现不同的——甚至是更好的——解决方案。通过这种额外的噪声,且噪声渐进趋近于 0,代理最终能够收敛到一个更好且最终的确定性策略。
但是,反向传播、时序信用分配和随机行动,真的算是学习和构建复杂策略的前提条件吗?
这个问题的答案是否定的。
正如我们在第十章《使用 DAgger 算法的模仿学习》中所学到的那样,通过使用反向传播和随机梯度下降(SGD)将策略学习转化为模仿问题,我们可以通过专家学习一个判别模型,以预测下一步应采取的行动。不过,这仍然涉及反向传播,并且需要一个可能并不总是能获得的专家。
另一个用于全局优化的常见算法子集确实存在。它们被称为进化算法(EAs),并且不基于反向传播,也不需要另外两个原理,即时间信用分配和噪声行为。此外,正如我们在本章开头所说的,这些进化算法非常通用,可以应用于各种问题,包括顺序决策任务。
正如你可能猜到的,进化算法与强化学习算法在许多方面不同,并且主要受到生物进化的启发。进化算法包括许多类似的方法,如遗传算法、进化策略和遗传编程,它们在实现细节和表示的方式上有所不同。然而,它们都主要基于四个基本机制——繁殖、变异、交叉和选择——并通过一种猜测与检验的过程循环进行。随着我们本章的进展,我们将看到这些机制具体意味着什么。
进化算法被定义为黑箱算法。这些算法优化一个函数,![],相对于![],而不对![]做任何假设。因此,![]可以是你想要的任何东西。我们只关心![]的输出。这有许多优点,也有一些缺点。主要的优点是我们不需要关心![]的结构,我们可以自由地使用对我们和当前问题最合适的方法。另一方面,主要的缺点是这些优化方法无法解释,因此其机制无法被理解。在需要可解释性的情况下,这些方法就不太有吸引力了。
强化学习几乎一直被优先用于解决顺序任务,尤其是对于中等到困难的任务。然而,OpenAI 最近的一篇论文强调,进化策略(Evolutionary Strategy),一种进化算法,可以作为强化学习的替代方法。这一观点主要源于该算法所达到的渐近性能以及其在数千个 CPU 上扩展的惊人能力。
在我们了解这个算法如何能够在学习困难任务的优秀策略时良好扩展之前,让我们更深入地了解进化算法。
进化算法(EAs)受到生物进化的启发,采用模拟生物进化的技术和机制。这意味着进化算法通过多次试验来创建新的候选解种群。这些解也被称为个体(在强化学习问题中,候选解就是策略),它们比上一代更优,类似于自然界中的过程,只有最强者生存下来并有可能繁衍后代。
进化算法的一个优势是它们是无导数的方法,意味着它们不使用导数来寻找解。这使得进化算法能够很好地处理各种可微和不可微的函数,包括深度神经网络。这种结合在下图中进行了示意。请注意,每个个体都是一个独立的深度神经网络,因此在任何时刻,神经网络的数量与个体数量相同。在下图中,种群由五个个体组成:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/185767dc-22b5-4956-a2fe-f07e80085a75.png
图 11.1. 通过进化算法优化深度神经网络
每种进化算法的具体性有所不同,但它们的基本循环在所有进化算法中是共同的,其工作原理如下:
创建一个由个体组成的种群(也称为候选解或表型),每个个体都有一组不同的属性(称为染色体或基因型)。初始种群是随机初始化的。
每个候选解都通过一个适应度函数独立评估,该函数决定解的质量。适应度函数通常与目标函数相关,按照我们到目前为止使用的术语,适应度函数可以是智能体(即候选解)在其生命周期内累积的总奖励。
然后,从种群中选出适应性更强的个体,并修改它们的基因组,以便生成新一代个体。在某些情况下,适应性较差的候选解可以作为负面示例,帮助生成下一代。这个过程的具体步骤在不同算法中差异较大。一些算法,例如遗传算法,通过交叉和变异这两个过程来繁殖新个体,这些新个体被称为后代。其他算法,如进化策略,仅通过变异来繁殖新个体。我们将在本章稍后更深入地解释交叉和变异,但一般来说,交叉是将两个父代的基因信息结合的过程,而变异则仅改变后代中某些基因值。
重复整个过程,经过步骤 1-3,直到满足终止条件。在每次迭代中,创建的种群也称为代。
如下图所示,这一迭代过程在达到给定的适应度水平或生成了最大数量的世代后终止。如我们所见,种群是通过交叉和变异生成的,但正如我们已经解释过的,这些过程可能会有所不同,具体取决于使用的算法:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/f73e8a1d-c237-49b8-9e85-d6a9565eb061.png
图 11.2. 进化算法的主要循环
一般演化算法的主体非常简单,可以用几行代码来实现,如这里所示。概括来说,在每次迭代中,直到生成适应度合格的个体为止,会生成新的候选个体并进行评估。这些候选个体是由上一代中适应度最好的个体生成的:
solver = EvolutionaryAlgortihm()
while best_fitness < required_fitness:
candidates = solver.generate_candidates() # for example from crossover and mutation
fitness_values = []
for candidate in candidates:
fitness_values.append(evaluate(candidate))
solver.set_fitness_values(fitness_values)
best_fitness = solver.evaluate_best_candidate()
请注意,求解器的实现细节取决于所使用的算法。
进化算法的应用实际上广泛分布于多个领域和问题,从经济学到生物学,从计算机程序优化到蚁群优化。
由于我们主要关注的是进化算法在解决顺序决策任务中的应用,我们将解释两种最常见的进化算法,它们被用来解决这些类型的任务。它们分别被称为遗传算法(GAs)和进化策略(ESes)。随后,我们将进一步发展进化策略,开发其高度可扩展的版本。
遗传算法的思想非常直接——评估当前的代数,只使用表现最好的个体生成下一代候选解,并丢弃其他个体。如前面所示的图表所示,存活下来的个体通过交叉和变异生成下一代种群。这两个过程在以下图表中表示。交叉是通过在存活个体中选择两个解,并将它们的参数结合在一起进行的。变异则是通过改变后代基因型中的一些随机参数来实现的:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/40983c68-bd09-46a1-8955-2f6bb61edb4d.png
图 11.3. 变异和交叉的视觉示意图
交叉和变异可以采用多种不同的方式。在更简单的版本中,交叉是通过随机选择两个父母的部分进行的,变异则是通过向获得的解添加高斯噪声来实现的,噪声的标准差是固定的。通过只保留最优秀的个体并将它们的基因注入新生个体中,解会随着时间的推移不断改进,直到满足某一条件。然而,在复杂问题中,这种简单的解决方案容易陷入局部最优解(意味着解仅限于一个小的候选解集合)。在这种情况下,通常会选择更先进的遗传算法,如增强拓扑进化网络(NEAT)。NEAT 不仅改变网络的权重,还会改变其结构。
进化策略(ESes)比遗传算法(GAs)更简单,因为它们主要基于突变来创建新种群。
突变通过向基因型添加从正态分布中采样的值来执行。进化策略的一个非常简单的版本是通过在整个种群中选择表现最好的个体,并从具有固定标准差且均值等于最佳表现个体的正态分布中采样下一代。
在小规模问题之外,不推荐使用该算法。这是因为仅跟随一个领导者并使用固定的标准差可能会阻止潜在解探索更多样化的搜索空间。因此,该方法的解可能会陷入狭窄的局部最小值。一个直接且更好的策略是通过结合表现最好的候选解并按其适应度排名加权来生成后代。根据适应度值对个体进行排名称为适应度排名。该策略优于使用实际适应度值,因为它对目标函数的变换不变,并且能防止新一代过度偏向潜在的异常值。
协方差矩阵适应进化策略,简称CMA-ES,是一种进化策略算法。与更简单的进化策略版本不同,它根据多元正态分布来采样新的候选解。CMA 这个名字来源于这样一个事实:变量之间的依赖关系被保存在协方差矩阵中,并通过适应该矩阵来增加或减少下一代的搜索空间。
简而言之,当 CMA-ES 对周围空间有较高的信心时,它通过逐步减少协方差矩阵的值来缩小搜索空间。相反,当 CMA-ES 对空间的信心较低时,它增加协方差矩阵,从而扩大可能的搜索空间。
进化策略(ESes)是强化学习(RL)的一种有趣替代方法。然而,必须评估其优缺点,以便我们选择正确的方案。让我们简要了解一下进化策略的主要优势:
无导数方法:无需反向传播。只需执行前向传递来估算适应度函数(或等效地,累计奖励)。这为所有不可微分的函数打开了大门,例如:硬注意力机制。此外,通过避免反向传播,代码的效率和速度得到了提高。
非常通用:进化策略的通用性主要来自于它作为黑盒优化方法的特性。由于我们不关心智能体、其执行的动作或访问的状态,我们可以将这些内容抽象化,只专注于其评估。此外,进化策略可以在没有明确目标的情况下进行学习,并且能在极度稀疏的反馈下工作。进化策略也更为通用,因为它们能够优化更多样化的函数集合。
高度可并行且具有鲁棒性:正如我们即将看到的,进化策略比强化学习更容易并行化,计算可以分布到成千上万的工作节点上。进化策略的鲁棒性归功于其所需的少量超参数。例如,与强化学习相比,不需要指定轨迹的长度、lambda 值、折扣因子、跳过的帧数等。另外,进化策略对于具有非常长时间跨度的任务也非常具有吸引力。
另一方面,强化学习在以下几个关键方面更受偏爱:
样本效率:强化学习算法更有效地利用从环境中获得的信息,因此它们需要更少的数据和步骤来学习任务。
卓越的性能:总体而言,强化学习算法在性能上优于进化策略。
现在我们已经介绍了黑盒进化算法,特别是进化策略,我们准备将刚刚学到的内容付诸实践。OpenAI 的论文《进化策略作为强化学习的可扩展替代方案》对进化策略作为强化学习算法的替代方案的采用做出了重大贡献。
本文的主要贡献在于一种方法,该方法能够在多个 CPU 上极其有效地扩展进化策略。特别地,这种新方法使用了一种跨 CPU 的新型通信策略,仅涉及标量,因此能够在成千上万的并行工作节点之间进行扩展。
通常,进化策略(ES)需要更多的经验,因此效率低于强化学习(RL)。然而,通过将计算分布到如此多的工作节点(得益于采用这种新策略),任务可以在更少的墙钟时间内解决。例如,在论文中,作者使用 1,440 个 CPU 在仅 10 分钟内解决了 3D 人形行走模式,且 CPU 核心数呈线性加速。由于常规强化学习算法无法达到这种扩展性水平,它们需要几个小时才能解决相同的任务。
让我们看看它们是如何能够如此高效地扩展的。
在论文中,使用了一种版本的进化策略,旨在最大化平均目标值,具体如下:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/ba38e6a1-fdc3-4592-afec-231c17fd721c.png
它通过在种群中搜索,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/539e6611-0c4e-4075-9e74-35cce86c0178.png,并通过https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/3a36c710-4434-455b-8b98-03c3151da93e.png进行随机梯度上升。https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/051c0918-d493-43e6-a1d4-9de7f947e548.png是目标函数(或适应度函数),而https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/4d706f8e-4f4f-49a4-975c-6f02832c082f.png是演员的参数。在我们的问题中,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/3bc547ab-803d-49b4-ac20-452762b6b5e6.png仅仅是代理通过https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/0f404f12-ce92-410d-9d06-404c260e2f6a.png在环境中获得的随机回报。
种群分布,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/add68569-90f7-4ffd-bf1c-f2310e74ac9f.png,是一个多元高斯分布,均值为!,标准差为!,如图所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/6ac4b3a4-7bcc-4497-be9a-739357c40167.png
从这里开始,我们可以通过使用随机梯度估算来定义步长更新,如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/f4bc3a83-dad8-43d6-bc80-3e5846b68fd5.png
通过这个更新,我们可以使用来自种群的样本结果估算随机梯度(无需执行反向传播)。我们也可以使用一些著名的更新方法,比如 Adam 或 RMSProp,来更新参数。
很容易看出,如何将 ES 扩展到多个 CPU:每个工作者被分配到种群的一个独立候选解上。评估可以完全自主地进行,正如论文中所描述的,优化可以在每个工作者上并行进行,且每个 CPU 单元之间只共享少量标量。
具体来说,工作者之间唯一共享的信息是一个回合的标量回报,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/42692633-6bcf-401b-bded-d2cb8a1dabb8.png,以及用于采样的随机种子!。通过仅传输回报,我们可以进一步缩减数据量,但在这种情况下,每个工作者的随机种子必须与其他工作者同步。我们决定采用第一种技术,而论文使用的是第二种。在我们简单的实现中,差异可以忽略不计,且两种技术都需要极低的带宽。
另外有两种技术被用来提高算法的性能:
健身塑形 – 目标排名:我们之前讨论过这个技巧。它非常简单。与其直接使用原始回报来计算更新,不如使用排名变换。排名对于目标函数的变换是不可变的,因此在回报差异较大的情况下表现更好。此外,它还去除了异常值的噪声。
镜像噪声:这个技巧减少了方差,并且涉及到同时评估带有噪声的网络 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/c238b7ca-715c-4fe0-add9-7c75cc76cbd5.png 和 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/5fd782b2-9cad-48cc-959d-0ccafd86ee28.png;也就是说,对于每个个体,我们会有两种变异:https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/8374e454-8f2f-42b4-8157-0055e8b86858.png 和 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/9acbcfa7-181f-4d62-82a0-3399abb61d07.png。
结合所有这些特性的并行化进化策略总结如下伪代码:
---------------------------------------------------------------------------------
Parallelized Evolution Strategy
---------------------------------------------------------------------------------
Initialize parameters on each worker
Initialize random seed on each worker
for do:
for <https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/ebb094da-015f-4821-b5a7-6ee124759d3c.png> do:
Sample
Evaluate individuals and
Spread returns to each other worker
for do:
Compute normalized rank from the returns
Reconstruct from the random seeds of the other workers
(maybe using Adam)
现在,剩下的就是实现这个算法了。
为了简化实现,并使得并行化版本的 ES 能够在有限的工作者(和 CPU)数量下运行良好,我们将开发一个类似于以下图示的结构。主进程为每个 CPU 核心创建一个工作者,并执行主循环。在每次迭代时,它会等待直到指定数量的新候选个体被工作者评估。与论文中提供的实现不同,每个工作者在每次迭代中会评估多个代理。因此,如果我们有四个 CPU,则会创建四个工作者。然后,如果我们希望在每次主进程迭代时总批量大小大于工作者的数量,比如 40,则每个工作者每次会创建并评估 10 个个体。返回值和种子会被返回给主应用程序,主应用程序会等待所有 40 个个体的结果,然后继续执行后续代码行。
然后,这些结果会以批量的形式传播给所有工作者,工作者分别优化神经网络,按照公式 (11.2) 中提供的更新进行操作:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/fde043f4-e707-4c42-98ec-7bb6cc7d4855.png
图 11.4. 展示 ES 并行版本主要组件的示意图
根据我们刚才描述的,代码被分为三个主要部分:
创建并管理队列和工作者的主要过程。
定义工作者任务的函数。
此外,还有一些执行简单任务的函数,例如对回报进行排序和评估代理。
让我们解释一下主进程的代码,以便在深入了解工作者之前,您能够对整个算法有一个大致的了解。
这是在名为ES
的函数中定义的,该函数具有以下参数:Gym 环境的名称,神经网络隐藏层的大小,代数总数,工作者数量,Adam 学习率,批量大小和标准差噪声:
def ES(env_name, hidden_sizes=[8,8], number_iter=1000, num_workers=4, lr=0.01, batch_size=50, std_noise=0.01):
然后,我们设置一个初始种子,在所有工作者之间共享,以初始化参数并使权重保持一致。此外,我们计算每个工作者在每次迭代中需要生成并评估的个体数量,并创建两个 multiprocessing.Queue
队列。这些队列是传递给工作者以及从工作者传回的变量的进出口:
initial_seed = np.random.randint(1e7)
indiv_per_worker = int(batch_size / num_workers)
output_queue = mp.Queue(maxsize=num_workers*indiv_per_worker)
params_queue = mp.Queue(maxsize=num_workers)
接下来,实例化多进程multiprocessing.Process
。这些进程将以异步方式运行worker
函数,该函数作为第一个参数传递给Process
构造函数。传递给worker
函数的所有其他变量被分配到args
,这些变量与 ES 所接受的参数非常相似,唯一不同的是额外的两个队列。进程在调用start()
方法时开始运行:
processes = []
for widx in range(num_workers):
p = mp.Process(target=worker, args=(env_name, initial_seed, hidden_sizes, lr, std_noise, indiv_per_worker, str(widx), params_queue, output_queue))
p.start()
processes.append(p)
一旦并行工作者启动,我们就可以跨代进行迭代,直到所有个体在每个工作者中被生成并单独评估。请记住,每一代生成的个体总数是工作者数量num_workers
与每个工作者生成的个体数indiv_per_worker
的乘积。这种架构是我们实现的独特之处,因为我们只有四个 CPU 核心,而论文中的实现则利用了成千上万的 CPU。通常,每一代生成的人口数量通常在 20 到 1000 之间:
for n_iter in range(number_iter):
batch_seed = []
batch_return = []
for _ in range(num_workers*indiv_per_worker):
p_rews, p_seed = output_queue.get()
batch_seed.append(p_seed)
batch_return.extend(p_rews)
在前面的代码片段中,output_queue.get()
从output_queue
获取一个元素,该队列由工作者填充。在我们的实现中,output_queue.get()
返回两个元素。第一个元素,p_rews
,是使用p_seed
生成的智能体的适应度值(即返回值),它作为第二个元素给出。
当for
循环终止时,我们对返回值进行排序,并将批量返回值和种子放入params_queue
队列中,所有的工作者将读取该队列来优化智能体。代码如下所示:
batch_return = normalized_rank(batch_return)
for _ in range(num_workers):
params_queue.put([batch_return, batch_seed])
最后,当所有训练迭代执行完毕时,我们可以终止工作者:
for p in processes:
p.terminate()
这就完成了主函数。现在,我们需要做的就是实现工作者。
工作者的功能在worker
函数中定义,之前已作为参数传递给mp.Process
。我们不能逐行讲解所有代码,因为那会占用太多时间和篇幅,但我们会在这里解释核心部分。和往常一样,完整的实现代码可以在本书的 GitHub 仓库中找到。所以,如果你有兴趣深入了解,可以抽时间查看 GitHub 上的代码。
在worker
的前几行中,创建了计算图以运行策略并优化它。具体来说,策略是一个多层感知机,tanh
非线性激活函数用于激活层。在这种情况下,Adam 被用来应用根据(11.2)公式第二项计算出的预期梯度。
然后,agent_op(o)
和evaluation_on_noise(noise)
被定义。前者运行策略(或候选解)以获得给定状态或观测o
的行动,后者评估通过将扰动noise
(与策略形状相同)添加到当前策略的参数中获得的新候选解。
直接跳到最有趣的部分,我们通过指定最多可以依赖 4 个 CPU 来创建一个新的会话,并初始化全局变量。如果你没有 4 个 CPU 可用,也不用担心。将allow_soft_placement
设置为True
,会告诉 TensorFlow 只使用受支持的设备:
sess = tf.Session(config=tf.ConfigProto(device_count={'CPU': 4}, allow_soft_placement=True))
sess.run(tf.global_variables_initializer())
尽管使用了所有 4 个 CPU,但我们仅为每个工作线程分配一个。在计算图的定义中,我们设置了计算将在哪个设备上执行。例如,要指定工作线程仅使用 CPU 0,可以将图形放在with
语句中,从而定义要使用的设备:
with tf.device("/cpu:0"):
# graph to compute on the CPUs 0
回到我们的实现,我们可以无限循环,或者至少直到工作线程有任务可以处理。这个条件稍后会在while
循环内进行检查。
一个重要的注意事项是,因为我们在神经网络的权重上进行了很多计算,所以处理扁平化的权重要容易得多。因此,例如,我们不会处理形如[8,32,32,4]的列表,而是对一个长度为 83232*4 的一维数组进行计算。执行从前者到后者的转换以及反向转换的函数在 TensorFlow 中已经定义(如果你有兴趣了解是如何实现的,可以查看 GitHub 上的完整实现)。
此外,在开始while
循环之前,我们检索扁平化代理的形状:
agent_flatten_shape = sess.run(agent_variables_flatten).shape
while True:
在while
循环的第一部分,生成并评估候选解。候选解是通过向权重添加正态扰动构建的;也就是说,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/35368897-b2dd-4f34-9776-f797818d1a56.png。这是通过每次选择一个新的随机种子来完成的,该种子将唯一地从正态分布中采样扰动(或噪声),https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/acc67400-71b8-4b04-8fef-43469154d93a.png。这是算法的关键部分,因为稍后,其他工作线程将必须从相同的种子重新生成相同的扰动。之后,两个新后代(由于我们使用的是镜像采样,所以有两个)将被评估,并将结果放入output_queue
队列中:
for _ in range(indiv_per_worker):
seed = np.random.randint(1e7)
with temp_seed(seed):
sampled_noise = np.random.normal(size=agent_flatten_shape)
pos_rew= evaluation_on_noise(sampled_noise)
neg_rew = evaluation_on_noise(-sampled_noise)
output_queue.put([[pos_rew, neg_rew], seed])
请注意,以下代码片段(我们之前使用过的)只是用于在本地设置 NumPy 随机种子seed
的一种方式:
with temp_seed(seed):
..
在with
语句外,生成随机值所用的种子将不再是seed
。
while
循环的第二部分涉及获取所有返回值和种子,从这些种子中重建扰动,按照公式(11.2)计算随机梯度估计,并优化策略。params_queue
队列由主进程填充,正如我们之前看到的那样。它通过发送在第一阶段由工作线程生成的种群的归一化排名和种子来完成此操作。代码如下:
batch_return, batch_seed = params_queue.get()
batch_noise = []
# reconstruction of the perturbations used to generate the individuals
for seed in batch_seed:
with temp_seed(seed):
sampled_noise = np.random.normal(size=agent_flatten_shape)
batch_noise.append(sampled_noise)
batch_noise.append(-sampled_noise)
# Computation of the gradient estimate following the formula (11.2)
vars_grads = np.zeros(agent_flatten_shape)
for n, r in zip(batch_noise, batch_return):
vars_grads += n * r
vars_grads /= len(batch_noise) * std_noise
sess.run(apply_g, feed_dict={new_weights_ph:-vars_grads})
上述代码中的最后几行计算了梯度估计;也就是说,它们计算了公式(11.2)中的第二项:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/abe6a754-4493-48b2-a6a4-789975a1a0c0.png
这里,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/6fed24d8-5e14-41bd-809e-e74e3ba4eee5.png 是https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/5307ef79-2210-4c5d-96a4-4cbc4d08cb52.png 和https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/ae2228ad-b5e8-4148-8a27-d20fd14fd478.png 候选项的归一化排名以及它们的扰动。
apply_g
是应用 vars_grads
梯度(11.3)使用 Adam 的操作。请注意,我们传递 -var_grads
,因为我们希望进行梯度上升而不是梯度下降。
实施已完成。现在,我们必须将其应用于环境并进行测试,以查看其表现如何。
可扩展演化策略在 LunarLander 环境中的表现如何?让我们来看看吧!
您可能还记得,我们已经在第六章中对比了 LunarLander 与 A2C 和 REINFORCE,学习随机和 PG 优化。这个任务包括通过连续动作在月球上着陆。我们决定使用这个中等难度的环境来比较 ES 的结果与使用 A2C 获得的结果。
在这个环境中表现最佳的超参数如下:
超参数 | 变量名 | 值 |
---|---|---|
神经网络大小 | hidden_sizes |
[32, 32] |
训练迭代次数(或代数) | number_iter |
200 |
工作人数 | num_workers |
4 |
Adam 学习率 | lr |
0.02 |
每个工作人员的个体数 | indiv_per_worker |
12 |
标准差 | std_noise |
0.05 |
结果显示在以下图表中。立即引人注目的是曲线非常稳定平滑。此外,请注意,在约 250-300 万步后,它达到了平均分数约为 200。与在图 6.7 中使用 A2C 获得的结果进行比较,您会发现演化策略比 A2C 和 REINFORCE 多花了近 2-3 倍的步骤。
正如论文所示,通过大规模并行化(至少使用数百个 CPU),您应该能够在短短几分钟内获得非常好的策略。不幸的是,我们没有这样的计算能力。但是,如果您有的话,可以自行尝试:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/9ee4c3a1-b67b-4d59-918d-73e3d587e9f6.png
图 11.5 可扩展演化策略的性能
总体而言,结果非常好,显示出 ES 对于非常长的时间跨度问题和具有非常稀疏奖励的任务是一个可行的解决方案。
在本章中,你了解了进化算法(EAs),这是一类受生物进化启发的新型黑箱算法,可以应用于强化学习任务。与强化学习相比,进化算法从不同的角度解决这些问题。你看到,在设计强化学习算法时需要处理的许多特性,在进化方法中并不适用。它们的不同之处既体现在内在的优化方法上,也体现在基本假设上。例如,由于进化算法是黑箱算法,我们可以优化任何我们想要的函数,因为我们不再受限于使用可微分函数,这一点与强化学习时有所不同。正如我们在本章中看到的,进化算法有许多其他优点,但它们也有许多缺点。
接下来,我们研究了两种进化算法:遗传算法和进化策略。遗传算法更复杂,因为它通过交叉和变异从两个父母创建后代。进化策略从一个仅通过变异生成的种群中选择表现最好的个体。ES 的简单性是算法能够在成千上万个并行工作者之间实现巨大可扩展性的关键因素之一。OpenAI 的论文中展示了这种可扩展性,证明了 ES 能够在复杂环境中达到与 RL 算法相当的表现。
为了实践进化算法,我们实现了本章引用的论文中的可扩展进化策略。此外,我们还在 LunarLander 上进行了测试,发现 ES 能够以高性能解决该环境。尽管结果很棒,ES 的学习任务比 AC 和 REINFORCE 多用了两到三倍的步骤。这是 ES 的主要缺点:它们需要大量的经验。尽管如此,凭借其线性扩展到工作者数量的能力,在足够的计算能力支持下,你可能能够在比强化学习算法短得多的时间内解决这个任务。
在下一章,我们将回到强化学习,讨论一个被称为探索-利用困境的问题。我们将了解它是什么以及为什么它在在线设置中至关重要。接着,我们将使用一个潜在的解决方案来开发一个元算法,称为 ESBAS,它为每种情况选择最合适的算法。
有哪两种替代强化学习的算法可以解决序列决策问题?
进化算法中产生新个体的过程是什么?
进化算法(如遗传算法)的灵感来源是什么?
CMA-ES 如何演化进化策略?
进化策略的一个优点和一个缺点是什么?
在论文《进化策略作为强化学习的可扩展替代方法》中,使用了什么技巧来减少方差?
要阅读 OpenAI 提出的可扩展版本 ES 的原始论文,即Evolution Strategies as a Scalable Alternative to Reinforcement Learning论文,请访问arxiv.org/pdf/1703.03864.pdf
。
要阅读提出 NEAT 的论文,即通过增强拓扑演化神经网络,请访问nn.cs.utexas.edu/downloads/papers/stanley.ec02.pdf
。
到目前为止,你已经能够以系统化和简洁的方式处理 RL 问题。你能够为手头的问题设计和开发 RL 算法,并从环境中获得最大收益。此外,在前两章中,你学习了超越 RL 的算法,但这些算法也可以用来解决相同的任务。
在本章开始时,我们将提出一个在许多前几章中已经遇到过的困境:即探索与利用困境。我们已经在全书中提出了该困境的潜在解决方案(例如,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/9474f864-505d-4f4e-bab5-674b452546f7.png-贪心策略),但我们希望为你提供更全面的视角,并简洁地介绍解决该问题的算法。许多算法,如上置信界(UCB)算法,比我们迄今为止使用的简单启发式方法(例如,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/9474f864-505d-4f4e-bab5-674b452546f7.png-贪心策略)更加复杂和优秀。我们将通过一个经典问题——多臂强盗问题来说明这些策略。尽管它是一个简单的表格游戏,我们将以此为起点,展示这些策略如何应用于非表格型和更复杂的任务。
本文介绍了探索与利用困境,概述了许多最近的强化学习(RL)算法所采用的主要方法,用以解决非常困难的探索环境。我们还将提供一个更广泛的视角,探讨该困境在解决其他类型问题时的适用性。作为证明,我们将开发一个名为时代随机强盗算法选择(ESBAS)的元算法,该算法解决了 RL 背景下的在线算法选择问题。ESBAS 通过利用从多臂强盗问题中出现的思想和策略,选择出最能在每个回合中最大化预期回报的 RL 算法。
本章将涵盖以下主题:
探索与利用
探索方法
时代随机强盗算法选择
探索-利用困境或探索-利用问题影响着许多重要领域。实际上,它不仅限于强化学习的背景,还适用于日常生活。这个困境的核心思想是判断是选择已经知道的最优解,还是值得尝试新的选项。假设你正在买一本新书。你可以选择你最喜欢的作者的书,或者选择亚马逊推荐的同类书籍。在第一种情况下,你对自己选择的书充满信心,但在第二种情况下,你无法预测将会得到什么。然而,后者可能让你感到意外惊喜,读到一本非常好的书,甚至超越了你最喜欢作者写的书。
这种在利用已学知识和冒险探索新选项之间的冲突,在强化学习中也非常常见。智能体可能需要牺牲短期奖励,去探索一个新的空间,以便在未来获得更高的长期奖励。
这一切对你来说可能并不新鲜。事实上,当我们开发第一个强化学习算法时,就开始处理这个问题了。直到现在,我们主要采用了简单的启发式方法,如ε-greedy策略,或遵循随机策略来决定是探索还是利用。经验上,这些策略效果很好,但还有一些其他技术能够实现理论上的最优表现。
本章将从基础讲解探索-利用困境,并介绍一些在表格问题上实现近乎最优表现的探索算法。我们还将展示如何将相同的策略适应于非表格和更复杂的任务。
对于一个强化学习算法,最具挑战性的 Atari 游戏之一是《蒙特祖玛的复仇》,其截图如下。游戏的目标是通过收集宝石和击杀敌人来获得分数。主角需要找到所有的钥匙,以便在迷宫中的房间间穿行,并收集必要的工具来移动,同时避免障碍物。稀疏奖励、长期目标和与最终目标无关的部分奖励,使得这款游戏对每个强化学习算法都非常具有挑战性。事实上,这四个特点使得《蒙特祖玛的复仇》成为测试探索算法的最佳环境之一:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/e18a14e6-d25a-4dea-9db9-b5c8f31a1116.png
《蒙特祖玛的复仇》截图
让我们从基础开始,以便全面了解这一领域。
多臂老虎机问题是经典的强化学习问题,用来说明探索-利用的权衡困境。在这个困境中,代理必须从一组固定的资源中选择,以最大化预期奖励。多臂老虎机这个名称来源于赌徒玩多个老虎机,每个老虎机都有来自不同概率分布的随机奖励。赌徒必须学习最佳策略,以获得最高的长期奖励。
这种情况在以下图示中进行了说明。在这个特定的例子中,赌徒(幽灵)需要从五台不同的老虎机中选择一台,每台老虎机都有不同且未知的奖励概率,以便赢得最高金额:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/83901340-859b-4b80-987d-3940058a9ae5.png
五臂老虎机问题示例
如果你在想多臂老虎机问题与更有趣的任务(比如《蒙特祖玛的复仇》)有何关系,答案是它们都涉及到决定,在长期来看,当尝试新的行为(拉动新的杠杆)时,是否会获得最高奖励,还是继续做迄今为止做得最好的事情(拉动最知名的杠杆)。然而,多臂老虎机与《蒙特祖玛的复仇》之间的主要区别在于,后者每次都会改变代理的状态,而在多臂老虎机问题中,只有一个状态,并且没有顺序结构,这意味着过去的行为不会影响未来。
那么,如何在多臂老虎机问题中找到探索与利用的正确平衡呢?
简单来说,多臂老虎机问题,以及一般的每个探索问题,可以通过随机策略或者更智能的技术来解决。属于第一类的最臭名昭著的算法叫做https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/d0a4ebbd-c39f-438a-957b-fa97d7c0799e.png-贪婪;而乐观探索,如 UCB,以及后验探索,如汤普森采样,属于第二类。在本节中,我们将特别关注https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/d0a4ebbd-c39f-438a-957b-fa97d7c0799e.png-贪婪和 UCB 策略。
这完全是关于平衡风险与奖励。但我们如何衡量一个探索算法的质量呢?通过后悔。后悔被定义为在一步操作中失去的机会,即在时间https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/cdaec17b-6d89-475d-92b1-afe09f9a3159.png时的后悔,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/05ad64e7-c41b-4736-96b5-3e17d5266074.png 如下所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/0c3a8dae-8113-4f37-a2bd-50eb09ed9d16.png
这里,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/c95e2c63-0f9c-436d-891c-0c33d1cbe73d.png 表示最优值,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/9df02363-3999-4be9-a9e4-32dac4ba1ba6.png 表示 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/eda7adef-c75c-41fe-bf05-e3a71d475361.png 的行动值。
因此,目标是通过最小化所有行动的总后悔,找到探索与利用之间的折衷:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/c7159b28-8e5e-4a4b-a0c8-67f57c2d6bd6.png
请注意,总遗憾的最小化等同于累积奖励的最大化。我们将利用这一遗憾的概念来展示探索算法的表现。
我们已经扩展了https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/3fd4eed5-f797-441a-a7c3-820e65fd322d.png-贪心策略背后的思想,并将其应用于帮助我们在 Q 学习和 DQN 等算法中的探索。这是一种非常简单的方法,但它在非平凡的任务中也能达到非常高的性能。这是它在许多深度学习算法中广泛应用的主要原因。
为了帮助你回忆,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/5a4a8e7f-73b0-4c20-95dc-af5b4c0f9421.png-贪心大多数时候采取最佳行动,但偶尔会选择一个随机行动。选择随机行动的概率由https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/c59c569b-ad2e-41a2-9748-8105e758d504.png值决定,它的范围从 0 到 1。也就是说,具有https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/472e4698-ff84-43e0-a3b7-4e017b959cb3.png的概率,算法会利用最佳行动,而具有https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/389c51f4-4d79-4edd-8b85-b668df73d57a.png的概率,则会通过随机选择来探索其他可能性。
在多臂强盗问题中,行动值是根据过去的经验估计的,方法是对采取这些行动所获得的奖励进行平均:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/57550883-a938-4c7e-95b9-8c405d2ea421.png
在前述方程中,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/ebaad13b-1a8f-4e8f-ab4d-ecb67a4671c8.png表示https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/604173e8-d30e-4512-95ed-ae8975292239.png行动被选中的次数,而https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/f359ceae-5338-46da-b55b-676926e84c5a.png是一个布尔值,表示在时刻https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/8f99004d-90c0-4b56-9d58-9a9dfa0e0b67.png时,是否选择了行动https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/e5f44a63-e1ec-4d04-86bd-7c0db688d83b.png。然后,强盗会根据https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/ffa9e069-89e1-4464-af51-35562be61862.png-贪心算法采取行动,或通过选择随机行动来探索,或通过选择https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/d13df1cf-782c-41fb-aaf3-b89060846cd0.png行动来利用较高的https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/b2bdeff5-087e-4a20-ae71-bbda48c6c1e5.png值。
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/1d841b84-44bc-4b44-9395-7ef1e1147a78.png-贪心的一个缺点是它具有期望的线性遗憾。然而,根据大数法则,最优的期望总遗憾应该是与时间步数呈对数关系的。这意味着,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/1d841b84-44bc-4b44-9395-7ef1e1147a78.png-贪心策略并不是最优的。
达到最优的一种简单方法是使用一个https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/a4e357f5-9d4d-4712-ad9b-914fc01d6f05.png值,该值随着时间的推移逐渐衰减。通过这样做,探索的总体权重将逐渐消失,最终只会选择贪心行动。实际上,在深度强化学习算法中,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/5adc8777-a769-4ad0-81e6-94bc007ba882.png-贪心几乎总是与https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/ef61d4c1-93b8-4dd2-9de5-5691ffe5ed98.png的线性或指数衰减相结合。
也就是说,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/83a790d4-315e-44cc-b1ce-ee6317e811ff.png 及其衰减率很难选择,并且还有其他策略可以最优地解决多臂赌博机问题。
UCB 算法与一种称为“面对不确定性时的乐观原则”(optimism in the face of uncertainty)有关,这是一种基于大数法则的统计学原理。UCB 构建了一个乐观的猜测,基于奖励的样本均值,并根据奖励的上置信界估算。乐观的猜测决定了每个动作的期望回报,同时考虑了动作的不确定性。因此,UCB 始终能够通过平衡风险与回报,选择潜在回报更高的动作。然后,当当前动作的乐观估算低于其他动作时,算法会切换到另一个动作。
具体来说,UCB 通过 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/3eeee2ef-bd6a-43a8-b596-2bd8f67e44f9.png 跟踪每个动作的平均奖励,以及每个动作的 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/f5fed32f-f7ac-4f64-b5db-5609545a3077.png UCB(因此得名)。然后,算法选择最大化以下内容的动作:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/a0da43c2-5a19-4a3f-af6d-2ea26cbce366.png (12.1)
在这个公式中,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/523327c1-114e-4bfe-9b93-e5ddb595f6dd.png 的作用是提供一个附加的参数,作为考虑动作不确定性的平均奖励。
UCB1 属于 UCB 系列,其贡献在于选择 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/e065e9bf-7e8a-4c32-8e4c-07fe6eed0d99.png。
在 UCB1 中,UCB 通过跟踪某个动作(https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/a992c126-793e-4465-a30a-bdc48682554d.png)被选择的次数,以及 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/fc8c5d8c-c204-4688-9f0e-f780d7494478.png 和 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/c796f72d-4a04-4337-9a37-acc696f7db3d.png 这两个量的总和来计算,如下式所示:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/b920c393-fb72-4f8c-b8e1-1b600b2eae41.png (12.2)
一个动作的不确定性与它被选择的次数有关。如果你仔细想想,这也能解释清楚,因为根据大数法则,在无限次数的试验下,你可以对期望值有一个明确的了解。相反,如果你只尝试过某个动作几次,你会对期望的奖励感到不确定,只有通过更多的经验,你才能判断它是好是坏。因此,我们会激励探索那些只被选择过少数几次的动作,因为它们的不确定性较高。重点是,如果 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/3a2286d0-a84a-43ef-8f10-e66246cbbf08.png 很小,意味着这个动作只是偶尔被尝试,那么 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/cea73fe8-9af9-4380-846a-0657e093e516.png 会很大,从而带来较高的不确定估计。然而,如果 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/1da62787-139b-4dfa-80f9-8e79a925418e.png 很大,那么 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/cea73fe8-9af9-4380-846a-0657e093e516.png 就会很小,估计值也会更准确。然后,我们只会在 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/e808426c-badf-410c-9246-9bbc961c22ca.png 具有较高的平均奖励时才选择它。
与 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/db396bc1-261d-4231-9b85-6d4fa469c491.png-贪婪算法相比,UCB 的主要优势实际上在于对动作进行计数。事实上,多臂老虎机问题可以通过此方法轻松解决,方法是为每个被采取的动作保持一个计数器,以及它的平均奖励。这两个信息可以集成到公式(12.1)和公式(12.2)中,从而获得在时刻(https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/367c449a-fa0e-4781-9557-c694ed252114.png)应该采取的最佳动作;即:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/98fd9d22-427c-4e19-a048-41faf9767872.png (12.3)
UCB 是一个非常强大的探索方法,它在多臂老虎机问题上实现了对数期望总遗憾,从而达到了最优趋势。值得注意的是,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/e76d68d1-7fee-4a84-8f04-c37407e6900b.png-贪婪探索也可以获得对数遗憾,但它需要精心设计,并且需要细调指数衰减,因此在平衡上会更加困难。
UCB 还有一些变体,如 UCB2、UCB-Tuned 和 KL-UCB。
我们已经看到,UCB,特别是 UCB1,能够通过相对简单的算法降低总体的遗憾,并在多臂老虎机问题上实现最优收敛。然而,这仍然是一个简单的无状态任务。
那么,UCB 在更复杂的任务上表现如何呢?为了回答这个问题,我们可以将问题过于简化,并将所有问题分为以下三大类:
无状态问题:这些问题的一个实例就是多臂老虎机问题。在这种情况下,探索可以通过更复杂的算法来处理,如 UCB1。
中小型表格问题:作为基本规则,探索仍然可以通过更先进的机制来处理,但在某些情况下,总体收益较小,不值得增加额外的复杂性。
大型非表格化问题:我们现在处于更加复杂的环境中。在这些环境中,前景尚不明确,研究人员仍在积极努力寻找最佳的探索策略。其原因在于,随着复杂性的增加,像 UCB 这样的最优方法变得难以处理。例如,UCB 无法处理具有连续状态的问题。然而,我们不必抛弃一切,可以借鉴在多臂老虎机问题中研究的探索算法。也就是说,有许多方法能够逼近最优的探索策略,并且在连续环境中也能很好地发挥作用。例如,基于计数的方法,如 UCB,已经通过为相似状态提供相似的计数来适应了无限状态问题。这类算法在一些极其复杂的环境中也能显著提升性能,例如在《蒙特祖马的复仇》游戏中。尽管如此,在大多数强化学习应用场景中,这些更复杂方法所带来的额外复杂性是得不偿失的,简单的随机策略,如https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/39b9d07d-70b6-4ce6-87b6-e91698651dfd.png-贪婪策略,通常就足够了。
值得注意的是,尽管我们仅概述了基于计数的探索方法,如 UCB1,但实际上还有两种更复杂的方式可以处理探索问题,它们能在遗憾值上实现最优结果。第一种方法叫做后验采样(其中一个例子是汤普森采样),它基于后验分布;第二种方法叫做信息增益,它依赖于通过估计熵来测量不确定性。
探索策略在强化学习中的主要用途是帮助智能体进行环境探索。我们在 DQN 中看到了这种用例,使用了https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/1e16a747-c424-435e-b1e2-db30ddda9c2d.png-贪婪策略,而在其他算法中则通过向策略中注入额外的噪声来实现。然而,探索策略的使用方式不仅限于此。为了更好地理解到目前为止介绍的探索概念,并引入这些算法的另一种应用场景,我们将展示并开发一种名为 ESBAS 的算法。该算法首次出现在论文《强化学习算法选择》中。
ESBAS 是一种在线算法选择(AS)的元算法,适用于强化学习的上下文。它利用探索方法来选择在整个轨迹中使用的最佳算法,以最大化预期奖励。
为了更好地解释 ESBAS,我们将首先解释什么是算法选择,以及它在机器学习和强化学习中的应用。接着,我们将重点介绍 ESBAS,详细描述其内部工作原理,并提供其伪代码。最后,我们将实现 ESBAS 并在一个名为 Acrobot 的环境中进行测试。
为了更好地理解 ESBAS 的作用,我们首先来关注算法选择(AS)是什么。在普通设置中,针对给定任务开发并训练一个特定且固定的算法。问题在于,如果数据集随着时间变化,数据集发生过拟合,或者在某些限制性情境下另一个算法表现更好,就无法改变算法。选择的算法将永远保持不变。算法选择的任务就是解决这个问题。
AS(算法选择)是机器学习中的一个开放问题。它涉及设计一个叫做元算法的算法,该算法始终从一个不同选项的池中(称为投资组合)选择最适合当前需求的算法。以下图示展示了这一过程。AS 的假设是,投资组合中的不同算法在问题空间的不同部分会优于其他算法。因此,拥有具有互补能力的算法非常重要。
例如,在下面的图示中,元算法从可用的算法(或代理)中选择哪一个(如 PPO 和 TD3)将在给定时刻作用于环境。这些算法不是互补的,而是每个算法提供不同的优势,元算法可以选择其中一个,以便在特定情境中表现得更好:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/1b763684-8acb-465e-95bf-828348ec507a.png
强化学习中算法选择方法的表示
例如,如果任务是设计一个能够在各种地形上行驶的自动驾驶汽车,那么训练一个能够在道路、沙漠和冰面上表现出色的算法可能会很有用。然后,AS 可以智能地选择在每种情境下使用这三种版本中的哪一个。例如,AS 可能会发现,在雨天,训练过的冰面策略比其他策略更有效。
在强化学习(RL)中,策略变化的频率非常高,且数据集随时间不断增加。这意味着在起始点(代理处于初步状态)与代理处于高级状态时,最佳神经网络大小和学习率可能存在很大差异。例如,代理可能在学习初期使用较高的学习率,并随着经验的积累逐渐降低学习率。这突出显示了强化学习是一个非常有趣的算法选择平台。因此,这正是我们将在其中测试 AS 的地方。
提出 ESBAS 的论文,在批处理和在线设置中对算法进行了测试。然而,在本章的剩余部分,我们将主要集中讨论前者。这两个算法非常相似,如果你对纯在线版本感兴趣,可以在论文中找到进一步的解释。在真正的在线设置中,AS 被重新命名为滑动随机带算法(SSBAS),它从最新的选择的滑动窗口中学习。但我们先从基础开始。
关于 ESBAS,首先要说的是它基于 UCB1 策略,并使用这种带算法选择离策略算法,从固定的投资组合中进行选择。具体来说,ESBAS 可以分为三个主要部分,工作原理如下:
它循环遍历多个指数大小的 epoch。在每个 epoch 中,它首先做的是更新投资组合中所有可用的离策略算法。它使用的是迄今为止收集的数据(在第一个 epoch 时,数据集将为空)。另外,它还会重置元算法。
然后,在每个 epoch 中,元算法根据公式(12.3)计算乐观猜测,以选择将控制下一个轨迹的离策略算法(在投资组合中),从而最小化总的遗憾。然后,使用该算法运行轨迹。同时,轨迹中的所有转换都会被收集,并添加到数据集,这些数据稍后将由离策略算法用来训练策略。
当轨迹结束时,元算法使用从环境中获得的 RL 回报更新该特定离策略算法的平均奖励,并增加出现次数。平均奖励和出现次数将由 UCB1 用来计算 UCB,如公式(12.2)所示。这些值用于选择下一个离策略算法,该算法将执行下一个轨迹。
为了让你更好地理解算法,我们还在代码块中提供了 ESBAS 的伪代码,见下方:
---------------------------------------------------------------------------------
ESBAS
---------------------------------------------------------------------------------
Initialize policy for every algorithm in the portfolio
Initialize empty dataset
for do
for in do
Learn policy on with algortihm
Initialize AS variables: and for every :
for do > Select the best algorithm according to UCB1
Generate trajectory with policy and add transitions to
> Update the average return and the counter of
(12.4)
这里,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/d94da654-c2e9-4cb4-9b62-c1250b1b0df5.png 是一个超参数,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/a13c0281-321e-4f8a-9fa1-8100853436ce.png 是在 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/832ecce0-4106-40e3-878f-114347cd69a6.png 轨迹中获得的 RL 回报,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/1c4593cf-9daf-400b-b76b-c83821a22498.png 是算法 https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/9859b9d2-396a-4d17-b3ea-2d5742f00a81.png 的计数器,https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/eeb52e17-7842-4111-a50f-6224ed1b0cc0.png 是其平均回报。
正如论文中所解释的,在线 AS 解决了四个来自 RL 算法的实际问题:
样本效率:策略的多样化提供了额外的信息源,使 ESBAS 具有样本效率。此外,它结合了课程学习和集成学习的特性。
鲁棒性:投资组合的多样化提供了对不良算法的鲁棒性。
收敛性:ESBAS 保证最小化后悔值。
课程学习:AS 能够提供一种课程策略,例如一开始选择较简单、浅层的模型,最后选择较深的模型。
实现 ESBAS 很简单,因为它只需要添加几个组件。最关键的部分在于对投资组合的离策略算法的定义和优化。对于这些,ESBAS 并不限制算法的选择。本文中使用了 Q-learning 和 DQN。我们决定使用 DQN,以提供一个能够处理更复杂任务的算法,并且可以与具有 RGB 状态空间的环境一起使用。我们在第五章中详细讲解了 DQN,深度 Q 网络,对于 ESBAS,我们将使用相同的实现。
在开始实现之前,我们需要指定投资组合的构成。我们创建了一个多样化的投资组合,就神经网络架构而言,但你也可以尝试其他组合。例如,你可以将投资组合与具有不同学习率的 DQN 算法组合。
实现分为如下几个部分:
DQN_optimization
类构建计算图,并使用 DQN 优化策略。
UCB1
类定义了 UCB1 算法。
ESBAS
函数实现 ESBAS 的主要流程。
我们将提供最后两点的实现,但你可以在书的 GitHub 仓库中找到完整的实现:github.com/PacktPublishing/Reinforcement-Learning-Algorithms-with-Python
.
让我们首先了解ESBAS(..)
。除了 DQN 的超参数外,还有一个额外的xi
参数,代表https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/1f645c1c-9092-470b-9d46-c713a52cc18d.png超参数。ESBAS
函数的主要结构与之前给出的伪代码相同,因此我们可以快速浏览一遍。
在定义了所有参数的函数后,我们可以重置 TensorFlow 的默认图,并创建两个 Gym 环境(一个用于训练,另一个用于测试)。然后,我们可以通过为每个神经网络大小实例化一个DQN_optimization
对象并将它们添加到列表中来创建投资组合:
def ESBAS(env_name, hidden_sizes=[32], lr=1e-2, num_epochs=2000, buffer_size=100000, discount=0.99, render_cycle=100, update_target_net=1000, batch_size=64, update_freq=4, min_buffer_size=5000, test_frequency=20, start_explor=1, end_explor=0.1, explor_steps=100000, xi=16000):
tf.reset_default_graph()
env = gym.make(env_name)
env_test = gym.wrappers.Monitor(gym.make(env_name), "VIDEOS/TEST_VIDEOS"+env_name+str(current_milli_time()),force=True, video_callable=lambda x: x%20==0)
dqns = []
for l in hidden_sizes:
dqns.append(DQN_optimization(env.observation_space.shape, env.action_space.n, l, lr, discount))
现在,我们定义一个内部函数DQNs_update
,它以 DQN 的方式训练投资组合中的策略。请注意,投资组合中的所有算法都是 DQN,它们唯一的区别在于神经网络的大小。优化通过DQN_optimization
类的optimize
和update_target_network
方法完成:
def DQNs_update(step_counter):
if len(buffer) > min_buffer_size and (step_counter % update_freq == 0):
mb_obs, mb_rew, mb_act, mb_obs2, mb_done = buffer.sample_minibatch(batch_size)
for dqn in dqns:
dqn.optimize(mb_obs, mb_rew, mb_act, mb_obs2, mb_done)
if len(buffer) > min_buffer_size and (step_counter % update_target_net == 0):
for dqn in dqns:
dqn.update_target_network()
一如既往,我们需要初始化一些(不言自明的)变量:重置环境,实例化ExperienceBuffer
对象(使用我们在其他章节中使用的相同类),并设置探索衰减:
step_count = 0
batch_rew = []
episode = 0
beta = 1
buffer = ExperienceBuffer(buffer_size)
obs = env.reset()
eps = start_explor
eps_decay = (start_explor - end_explor) / explor_steps
我们终于可以开始遍历各个时期的循环了。至于前面的伪代码,在每个时期,以下事情会发生:
策略在经验缓冲区上进行训练
轨迹由 UCB1 选择的策略运行
第一步是通过调用我们之前定义的DQNs_update
来完成的,整个时期的长度(具有指数长度):
for ep in range(num_epochs):
# policies training
for i in range(2**(beta-1), 2**beta):
DQNs_update(i)
关于第二步,在轨迹运行之前,实例化并初始化了UCB1
类的新对象。然后,一个while
循环遍历指数大小的回合,其中,UCB1
对象选择运行下一条轨迹的算法。在轨迹过程中,动作由dqns[best_dqn]
选择:
ucb1 = UCB1(dqns, xi)
list_bests = []
beta += 1
ep_rew = []
while step_count < 2**beta:
best_dqn = ucb1.choose_algorithm()
list_bests.append(best_dqn)
g_rew = 0
done = False
while not done:
# Epsilon decay
if eps > end_explor:
eps -= eps_decay
act = eps_greedy(np.squeeze(dqns[best_dqn].act(obs)), eps=eps)
obs2, rew, done, _ = env.step(act)
buffer.add(obs, rew, act, obs2, done)
obs = obs2
g_rew += rew
step_count += 1
每次回合后,ucb1
会根据上次轨迹获得的强化学习回报进行更新。此外,环境被重置,当前轨迹的奖励被追加到列表中,以便跟踪所有奖励:
ucb1.update(best_dqn, g_rew)
obs = env.reset()
ep_rew.append(g_rew)
g_rew = 0
episode += 1
这就是ESBAS
函数的全部内容。
UCB1
由一个构造函数组成,该构造函数初始化计算所需的属性(见 12.3);一个choose_algorithm()
方法,返回当前投资组合中最佳的算法(如 12.3 所示);以及update(idx_algo, traj_return)
,它使用获得的最后一个奖励更新idx_algo
算法的平均奖励,如 12.4 所理解的那样。代码如下:
class UCB1:
def __init__(self, algos, epsilon):
self.n = 0
self.epsilon = epsilon
self.algos = algos
self.nk = np.zeros(len(algos))
self.xk = np.zeros(len(algos))
def choose_algorithm(self):
return np.argmax([self.xk[i] + np.sqrt(self.epsilon * np.log(self.n) / self.nk[i]) for i in range(len(self.algos))])
def update(self, idx_algo, traj_return):
self.xk[idx_algo] = (self.nk[idx_algo] * self.xk[idx_algo] + traj_return) / (self.nk[idx_algo] + 1)
self.nk[idx_algo] += 1
self.n += 1
有了代码,我们现在可以在一个环境中进行测试,并查看它的表现。
我们将在另一个 Gym 环境——Acrobot-v1
上测试 ESBAS。正如 OpenAI Gym 文档中所描述的,Acrobot 系统包括两个关节和两个链节,其中两个链节之间的关节是有驱动的。最初,链节垂直挂着,目标是将下链节的末端摆动到给定的高度。下图显示了 Acrobot 在简短的时间步长序列中的运动,从起始位置到结束位置:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/7ecd2d52-3dc8-4336-9506-0e369fa99e02.png
Acrobot 运动序列
投资组合包含三种不同大小的深度神经网络。一种小型神经网络,只有一个大小为 64 的隐藏层;一种中型神经网络,具有两个大小为 16 的隐藏层;以及一种大型神经网络,具有两个大小为 64 的隐藏层。此外,我们设置了超参数!(使用的值与论文中的一致)。
以下图表显示了结果。该图展示了 ESBAS 的学习曲线:较暗的阴影部分表示完整的组合(包括之前列出的三种神经网络);较浅的橙色部分则表示 ESBAS 仅使用一个表现最好的神经网络(一个深度神经网络,具有两个隐藏层,每层大小为 64)的学习曲线。我们知道,ESBAS 仅使用一种算法的组合并不能真正发挥元算法的潜力,但我们引入它是为了提供一个基准,以便对比结果。图表本身说明了问题,显示了蓝色线始终高于橙色线,从而证明 ESBAS 实际上选择了最佳可用选项。这个不寻常的形状是因为我们正在离线训练 DQN 算法:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/05e199cc-9517-4fb9-90bd-ace66f746543.png
ESBAS 在使用三种算法的组合时以较深的阴影显示,而仅使用一种算法时则以较浅的阴影显示。
有关本章中提到的所有颜色参考,请参见www.packtpub.com/sites/default/files/downloads/9781789131116_ColorImages.pdf
中的彩色图像包。
此外,您在训练开始时以及在约 20K、65K 和 131K 步时看到的尖峰,是策略训练和元算法重置的时刻。
我们现在可以问自己,ESBAS 在何时优先选择某个算法,而非其他算法。答案可以从以下图表中看到。在此图中,小型神经网络以值 0 表示,中型以值 1 表示,大型以值 2 表示。点表示每条轨迹上选择的算法。我们可以看到,在一开始,大型神经网络被优先选择,但随后立即转向中型神经网络,再到小型神经网络。大约 64K 步之后,元算法又切换回较大的神经网络:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/ee253c6f-e3bf-448f-9b96-bee234b106ce.png
该图展示了元算法的偏好。
从前面的图中,我们还可以看到,两个 ESBAS 版本最终都收敛到相同的值,但收敛速度非常不同。事实上,利用 AS 的真正潜力的 ESBAS 版本(即包含三种算法的组合)收敛得要快得多。两者都收敛到相同的值,因为从长远来看,最佳的神经网络是 ESBAS 版本中使用的那个单一选项(即深度神经网络,具有两个隐藏层,每层大小为 64)。
在本章中,我们讨论了探索与利用的困境。这个问题在之前的章节中已经有所提及,但当时只是以一种简单的方式,通过采用简单的策略进行探讨。本章中,我们更加深入地研究了这个困境,从著名的多臂老虎机问题开始。我们看到,更加复杂的基于计数的算法,如 UCB,实际上能够达到最优表现,并且具有期望的对数后悔值。
然后,我们使用了探索算法来解决 AS。AS 是探索性算法的一种有趣应用,因为元算法需要选择最适合当前任务的算法。AS 在强化学习中也有应用。例如,AS 可以用来选择在不同算法组合中训练出的最佳策略,以执行下一条轨迹。这也是 ESBAS 的作用。它通过采用 UCB1 来解决在线选择离策略强化学习算法的问题。我们深入研究并实现了 ESBAS。
现在,你已经掌握了设计和开发高性能强化学习算法所需的所有知识,这些算法能够平衡探索与利用。此外,在之前的章节中,你已经获得了必要的技能,能理解在许多不同的环境中应该使用哪个算法。然而,直到现在,我们还忽视了一些更高级的强化学习话题和问题。在下一章也是最后一章,我们将填补这些空白,讨论无监督学习、内在动机、强化学习的挑战以及如何提高算法的鲁棒性。我们还将看到如何利用迁移学习从仿真环境转向现实世界。此外,我们还会给出一些关于训练和调试深度强化学习算法的额外建议和最佳实践。
什么是探索与利用的困境?
我们在之前的强化学习算法中使用过的两种探索策略是什么?
什么是 UCB?
哪个问题更难解决:Montezuma 的复仇还是多臂老虎机问题?
ESBAS 是如何解决在线强化学习算法选择问题的?
要了解关于多臂老虎机问题的更全面的调查,请阅读在线实验设计的调查与随机多臂老虎机:arxiv.org/pdf/1510.00757.pdf
要阅读利用内在动机来玩 Montezuma 的复仇的论文,请参阅统一基于计数的探索与内在动机:arxiv.org/pdf/1606.01868.pdf
要阅读原始的 ESBAS 论文,请访问此链接:arxiv.org/pdf/1701.08810.pdf
。
本章中,我们将总结前几章中解释的深度强化学习(深度 RL)算法的部分概念,以便给你一个广泛的视角来了解它们的应用,并为选择最适合某一问题的算法制定一个通用的规则。此外,我们还将提出一些指导方针,帮助你开始开发自己的深度 RL 算法。这些指导方针展示了从开发开始时需要采取的步骤,使你可以轻松地进行实验,而不至于在调试过程中浪费太多时间。在同一节中,我们还列出了最重要的超参数调优以及需要处理的额外标准化过程。
接下来,我们将通过解决稳定性、效率和泛化等问题,探讨这一领域的主要挑战。我们将以这三个主要问题为转折点,过渡到更先进的强化学习技术,如无监督强化学习和迁移学习。无监督强化学习和迁移学习对于部署和解决要求高的强化学习任务至关重要,因为它们是解决我们之前提到的三个挑战的技术。
我们还将探讨如何将强化学习应用于实际问题,以及强化学习算法如何在弥合仿真与现实世界之间的差距方面发挥作用。
为了总结本章及整本书,我们将从技术和社会角度讨论强化学习的未来。
本章将涵盖以下主题:
深度强化学习的最佳实践
深度强化学习的挑战
高级技术
强化学习在现实世界中的应用
强化学习的未来及其对社会的影响
在整本书中,我们介绍了许多强化学习算法,其中一些仅是升级版(例如 TD3、A2C 等),而其他一些则与其他算法有根本性的不同(例如 TRPO 和 DPG),并提出了达成相同目标的替代方式。此外,我们还探讨了非强化学习优化算法,如模仿学习和进化策略,以解决序列决策任务。所有这些替代方案可能会让你感到困惑,你可能不确定哪种算法最适合某一特定问题。如果是这种情况,别担心,我们现在将介绍一些规则,帮助你决定在给定任务中使用最合适的算法。
此外,如果你在本书中实现了我们介绍的一些算法,可能会发现很难将所有部分整合起来,使算法正常工作。深度强化学习算法因调试和训练难度大而著称,而且训练时间非常长。因此,整个训练过程非常缓慢且艰难。幸运的是,有一些策略可以帮助你避免在开发深度强化学习算法时遇到一些可怕的头痛问题。但在讨论这些策略之前,我们先来看看如何选择合适的算法。
区分不同类型的强化学习(RL)算法的主要驱动力是样本效率和训练时间。
我们将样本效率视为一个智能体在学习任务时与环境交互的次数。我们提供的数字是算法效率的一个指标,是相对于其他算法在典型环境中的表现进行衡量的。
显然,还有其他参数会影响算法选择,但通常这些参数的影响较小,重要性较低。举个例子,其他需要评估的参数包括 CPU 和 GPU 的可用性、奖励函数的类型、可扩展性、算法的复杂度以及环境的复杂度。
在本次比较中,我们将考虑无梯度黑箱算法(如进化策略)、基于模型的 RL 算法(如 DAgger)以及无模型的 RL 算法。在后者中,我们将区分策略梯度算法(如 DDPG 和 TRPO)和基于价值的算法(如 DQN)。
以下图表展示了这四类算法的数据效率(注意,最左侧的方法在样本效率上低于最右侧的方法)。特别地,随着图表向右移动,算法的效率逐渐增加。因此,你可以看到,无梯度方法需要从环境中获取更多的数据点,其次是策略梯度方法、基于价值的方法,最后是基于模型的 RL,它们是最具样本效率的。
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/8c99a8da-3b3b-4316-8252-e88cb7fd277a.png
图 13.1:基于模型的 RL 方法、策略梯度算法、基于价值的算法和无梯度算法的样本效率比较(最左侧的方法效率低于最右侧的方法)。
相反,这些算法的训练时间与样本效率呈反比关系。这个关系在以下图表中总结(注意,最左侧的方法训练速度慢于最右侧的方法)。我们可以看到,基于模型的算法的训练速度远低于基于价值的算法,几乎慢了五倍,而基于策略梯度的算法则比无梯度方法慢约5 倍。
请注意,这些数字只是为了突出平均情况,训练时间仅与算法的训练速度相关,而与从环境中获取新过渡所需的时间无关:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/6faa04da-a432-46dd-989d-ab505bd60a14.png
图 13.2. 模型基础 RL 方法、策略梯度算法、值基算法和无梯度算法的训练时间效率比较(最左侧的方法训练速度比最右侧的慢)
我们可以看到,算法的样本效率与其训练时间是互补的,这意味着一个数据高效的算法训练起来很慢,反之亦然。因此,由于智能体的总体学习时间既考虑到训练时间,也考虑到环境的速度,你需要在样本效率和训练时间之间找到一个平衡点,以满足你的需求。事实上,基于模型的算法和更高效的无模型算法的主要目的是减少与环境的交互步骤,使得这些算法在实际世界中更容易部署和训练,因为实际世界中的交互速度通常比模拟器中的慢。
一旦你定义了最适合你需求的算法,无论它是一个广为人知的算法还是一个新的算法,你就需要开发它。正如本书所示,强化学习算法与监督学习算法没有太多共同之处。出于这个原因,有一些不同的方面值得注意,以便于调试、实验和调整算法:
从简单问题开始:最初,你可能会想尽快尝试一个可行版本的代码。然而,建议你逐步进行,逐渐增加环境的复杂度。这将大大帮助减少整体的训练和调试时间。让我举个例子。如果你需要一个离散环境,可以从 CartPole-v1 开始;如果需要一个连续环境,可以选择 RoboschoolInvertedPendulum-v1。接着,你可以进入一个中等复杂度的环境,例如 RoboschoolHopper-v1、LunarLander-v2,或者一个带有 RGB 图像的相关环境。在这个阶段,你应该已经拥有一份没有 bug 的代码,最终可以在你的最终任务上进行训练和调整。此外,你应该尽可能熟悉这些简单的任务,这样如果出现问题,你能够知道应该查找哪些方面。
训练很慢:训练深度强化学习算法需要时间,学习曲线可能呈现任何形状。正如我们在前几章中看到的,学习曲线(即相对于步数的轨迹累积奖励)可能类似于对数函数、双曲正切函数(如下图所示),或更复杂的函数。可能的形状取决于奖励函数、其稀疏性和环境的复杂性。如果你正在处理一个新环境,并且不知道会有什么结果,建议你保持耐心,直到你确定进展已停止为止。同时,训练过程中不要过于关注图表。
开发一些基准线:对于新任务,建议至少开发两个基准线,以便与它们比较你的算法。一个基准线可以是一个随机代理,另一个基准线可以是像 REINFORCE 或 A2C 这样的算法。这些基准线可以用作性能和效率的下限。
图表和直方图:为了监控算法的进展并帮助调试阶段,一个重要的因素是绘制并显示关键参数的直方图,如损失函数、累积奖励、动作(如果可能)、轨迹的长度、KL 惩罚、熵和价值函数。除了绘制均值外,你还可以添加最小值、最大值和标准差。在本书中,我们主要使用 TensorBoard 来可视化这些信息,但你可以使用任何你喜欢的工具。
使用多个种子:深度强化学习在神经网络和环境中都嵌入了随机性,这通常导致不同运行之间的结果不一致。因此,为了确保一致性和稳定性,最好使用多个随机种子。
归一化:根据环境的设计,归一化奖励、优势和观测值可能会有所帮助。优势值(例如,在 TRPO 和 PPO 中)可以在一个批次中进行归一化,使其均值为 0,标准差为 1。此外,观测值可以使用一组初始随机步骤进行归一化。奖励则可以通过折扣或未折扣奖励的均值和标准差的运行估计来归一化。
超参数调优:超参数根据算法的类别和类型变化很大。例如,基于值的方法与策略梯度方法相比有多个不同的超参数,但这些类别的实例,如 TRPO 和 PPO,也有许多独特的超参数。也就是说,对于本书中介绍的每一个算法,我们都指定了所使用的超参数以及最重要的调优参数。在这些参数中,至少有两个是所有强化学习算法都会用到的:学习率和折扣因子。前者在监督学习中稍微不那么重要,但仍然是调优的首要参数之一,因为它决定了我们是否能够得到一个有效的算法。折扣因子是强化学习算法特有的。引入折扣因子可能会引入偏差,因为它会修改目标函数。然而,在实际应用中,它能够生成更好的策略。因此,从某种程度上来说,时间跨度越短越好,因为它可以减少不稳定性:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/6c0e587b-2b78-49e9-a61f-e3454508efbb.png
图 13.3. 对数函数和双曲正切函数的示例
关于本章中提到的所有颜色参考,请参阅www.packtpub.com/sites/default/files/downloads/9781789131116_ColorImages.pdf
中的彩色图像包。
采用这些技术后,你将能够更轻松地训练、开发和部署算法。此外,你将拥有更加稳定和健壮的算法。
对深度强化学习的缺点有一个批判性的视角和理解,是推动强化学习算法发展的关键因素,这样才能设计出更好的最先进算法。在接下来的部分中,我们将以更简洁的方式呈现深度强化学习的主要挑战。
近年来,在强化学习算法的研究中投入的努力巨大。特别是深度神经网络作为函数逼近方法引入之后,进展和成果都非常突出。然而,一些主要问题仍未解决,这些问题限制了强化学习算法在更广泛和有趣任务中的应用。我们在这里讨论的是稳定性、可重复性、效率和泛化性问题,尽管可扩展性和探索问题也可以列入此清单。
稳定性和可重复性在某种程度上是相互关联的,因为目标是设计一个能够在多次运行中保持一致的算法,并且不会对微小的调整产生过大敏感性。例如,算法不应该对超参数值的变化过于敏感。
使深度强化学习算法难以复制的主要因素,源自深度神经网络的固有特性。这主要是因为深度神经网络的随机初始化和优化过程的随机性。此外,在强化学习中,这种情况因环境的随机性而加剧。综合来看,这些因素也不利于结果的可解释性。
稳定性还面临强化学习(RL)算法高不稳定性的考验,就像我们在 Q-learning 和 REINFORCE 中看到的那样。例如,在基于值的算法中,没有任何收敛的保证,算法会受到高偏差和不稳定性的困扰。DQN 使用了许多技巧来稳定学习过程,比如经验回放和目标网络更新的延迟。尽管这些策略可以缓解不稳定性问题,但它们并未完全消除这些问题。
为了克服算法在稳定性和可重复性方面的固有限制,我们需要在算法之外进行干预。为此,可以采用许多不同的基准测试和一些经验法则,以确保较高的可重复性和结果一致性。具体方法如下:
如果可能,应该在多个相似的环境中测试算法。例如,可以在 Roboschool 或 Atari Gym 等环境集上测试,其中任务在动作和状态空间上相似,但目标不同。
运行多个不同随机种子的实验。通过改变种子,结果可能会有显著差异。以下图示为例,展示了相同超参数的算法在不同种子下的两次运行,你可以看到差异很大。因此,根据你的目标,使用多个随机种子(一般为三到五个)可能会有帮助。例如,在学术论文中,通常的做法是对五次运行的结果进行平均,并考虑标准差。
如果结果不稳定,考虑使用更稳定的算法或采取进一步的策略。同时,请记住,超参数的变化对不同算法和环境的影响可能会有显著差异:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/a8b58095-2ae3-4764-b795-fde9589f58ab.png
图 13.4. 两次相同算法在不同随机种子下的性能对比
在上一节选择合适的算法中,我们看到算法之间的样本效率差异很大。此外,从前几章我们了解到,更高效的方法,如基于值的学习,仍然需要大量的环境交互才能学习。也许只有基于模型的强化学习才能解决数据匮乏的问题。不幸的是,基于模型的方法也有其他缺点,比如较低的性能上限。
因此,已经构建了混合的基于模型和无模型的方法。然而,这些方法在工程实现上较为困难,且不适用于现实世界中的问题。正如你所看到的,效率相关的问题非常难以解决,但同时也非常重要,需要解决这些问题才能将强化学习方法应用于现实世界。
有两种替代方法可以处理像物理世界这样非常缓慢的环境。一种方法是在最初使用低保真度的模拟器,然后在最终环境中微调智能体。另一种方法是直接在最终环境中训练智能体,但需要转移一些先前的相关知识,以避免从头开始学习任务。这就像是在你已经训练了自己的感官系统后学习驾驶。无论哪种方式,因为我们是在将知识从一个环境转移到另一个环境,所以我们讨论了一种叫做迁移学习的方法。我们将在高级技术部分进一步详细阐述这种方法。
泛化的概念涉及两个不同但又相关的方面。一般而言,强化学习中的泛化概念指的是算法在相关环境中获得良好表现的能力。例如,如果一个智能体已经接受了在泥泞道路上行走的训练,我们可能会期望该智能体在铺设的道路上表现良好。泛化能力越强,智能体在不同环境中的表现就越好。第二种较少使用的泛化方式是指算法在只能收集有限数据的环境中取得良好表现的特性。
在强化学习中,智能体可以自行选择要访问的状态,并且可以任意停留在这些状态上,从而可能会在某个特定问题空间上过拟合。然而,如果需要良好的泛化能力,就必须找到一种折中方法。如果允许智能体为环境收集潜在的无限数据,这种做法只在某种程度上是有效的,因为它会作为一种自我正则化方法。
尽管如此,为了帮助智能体在其他环境中实现泛化,它必须具备抽象推理的能力,从简单的状态-动作映射中辨别出任务,并使用多个因素来解释任务。抽象推理的例子可以在基于模型的强化学习、迁移学习以及使用辅助任务中找到。我们稍后会介绍后者,但简而言之,这是一种通过将辅助任务与主任务共同学习来改善泛化和样本效率的技术。
我们之前列出的挑战没有简单的解决方案。然而,已经有努力在尝试克服这些挑战,并提出新的策略来提高效率、泛化能力和稳定性。专注于效率和泛化的两种最广泛且有前景的技术是无监督强化学习和迁移学习。在大多数情况下,这些策略与我们在前几章中开发的深度强化学习算法是相辅相成的。
无监督强化学习与常规的无监督学习相关,因为两者都不使用任何监督来源。在无监督学习中,数据没有标签,而在强化学习的对等体中,奖励并没有给出。也就是说,在给定一个动作时,环境只返回下一个状态。奖励和完成状态都被移除。
无监督强化学习(Unsupervised RL)在许多场景中都有帮助,例如,当用手工设计的奖励对环境进行标注不可扩展,或者当一个环境可以服务于多个任务时。在后一种情况下,可以采用无监督学习,以便我们能够了解环境的动态。能够从无监督来源中学习的方法,也可以作为在奖励非常稀疏的环境中额外的信息来源。
我们如何设计一个能够在没有任何监督来源的情况下学习环境的算法?难道我们不能仅仅采用基于模型的学习吗?实际上,基于模型的强化学习仍然需要奖励信号来规划或推断下一个动作。因此,需要一个不同的解决方案。
一个潜在的公平替代方法是开发一个内在的奖励函数,这个函数是由智能体的信念独立控制的。这种方法接近新生儿学习所采用的方式。实际上,他们采用纯探索的范式,在没有直接利益的情况下探索世界。然而,所获得的知识可能在以后的生活中有所帮助。
内在奖励是一种基于对状态新颖性估计的探索奖励。一个状态越陌生,它的内在奖励就越高。因此,代理通过这种奖励被激励去探索环境中的新空间。到现在为止,可能已经清楚,内在奖励可以作为一种替代的探索策略。事实上,许多算法将内在奖励与外在奖励(即环境返回的常规奖励)结合使用,以增强在稀疏环境中的探索,例如《Montezuma’s Revenge》。然而,尽管估算内在奖励的方法与我们在第十二章《开发 ESBAS 算法》中研究的非常相似,用于激励策略探索(这些探索策略仍与外部奖励相关),但在这里,我们仅专注于纯粹的无监督探索方法。
两种主要的基于好奇心驱动的策略,它们能在未知状态下提供奖励并有效探索环境,分别是基于计数的策略和基于动态的策略:
基于计数的策略(也称为访问计数策略)旨在计数或估算每个状态的访问次数,并鼓励探索那些访问次数较少的状态,对这些状态分配较高的内在奖励。
基于动态的策略训练一个环境的动态模型,并与智能体的策略结合,计算内在奖励,通常基于预测误差、预测不确定性或预测改进。其基本思想是通过对已访问状态进行建模,新颖和未知的状态将具有更高的不确定性或估计误差。然后,这些值被用来计算内在奖励,并激励探索未知状态。
如果我们仅对常规环境应用好奇心驱动的方法,会发生什么?论文《好奇心驱动学习的大规模研究》提出了这个问题,并发现,在 Atari 游戏中,纯粹的好奇心驱动代理可以在没有任何外部奖励的情况下学习并掌握任务。此外,他们还注意到,在 Roboschool 中,步态行为完全是由这些基于内在奖励的无监督算法产生的。论文的作者还提出,这些发现是由于环境设计的方式。确实,在人类设计的环境中(如游戏),外部奖励通常与寻求新奇的目标是一致的。然而,在非游戏化的环境中,纯粹的好奇心驱动的无监督方法能够完全依靠自己探索并学习环境,而无需任何监督。或者,RL 算法也可以通过结合内在奖励与外在奖励,从而显著提高探索能力,并因此提升性能。
在两个环境之间迁移知识,尤其是当这些环境彼此相似时,是一项困难的任务。迁移学习策略旨在弥合知识差距,使得从初始环境到新环境的过渡尽可能平滑和容易。具体而言,迁移学习是将知识从源环境(或多个源环境)高效地迁移到目标环境的任务。因此,从一组源任务中获取的经验越多,并且迁移到新目标任务,智能体学习的速度就越快,在目标任务上的表现也会越好。
一般来说,当你想到一个尚未经过训练的智能体时,你需要想象一个完全没有任何信息的系统。相反,当你玩游戏时,你会使用大量的先验知识。例如,你可能会根据敌人的形状、颜色以及它们的动态来推测敌人的含义。这意味着,当敌人向你开火时,你能识别出敌人,就像下面的《太空侵略者》游戏截图所示。此外,你还可以轻松地猜测游戏的基本动态。然而,在训练的开始阶段,强化学习智能体什么都不知道。这个比较非常重要,因为它提供了关于在多个环境之间传递知识重要性的宝贵洞察。一个能够利用从源任务中获得的经验的智能体,在目标环境中可以更快地学习。例如,如果源环境是 Pong 而目标环境是 Breakout,那么许多视觉组件可以被重用,从而节省大量计算时间。为了准确理解其总体重要性,想象一下在更复杂的环境中获得的效率:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/89e22bd8-eb9f-445b-8bb4-2ff4300b3183.png
图 13.5. 《太空侵略者》的截图。你能推测出精灵的角色吗?
说到迁移学习时,我们通常提到 0-shot 学习、1-shot 学习,依此类推,这些术语指的是在目标领域中所需的尝试次数。例如,0-shot 学习意味着在源领域上训练的策略可以直接应用到目标领域,而无需进一步训练。在这种情况下,智能体必须具备强大的泛化能力,以便适应新任务。
存在多种类型的迁移学习,其使用取决于具体情况和需求。一个区分点与源环境的数量有关。显然,你训练智能体的源环境越多,它的多样性就越大,能够在目标领域使用的经验也就越多。从多个源领域迁移学习被称为多任务学习。
单任务学习或称为迁移学习,是在一个领域上训练策略并将其迁移到另一个领域的任务。可以采用三种主要技术来实现这一目标,具体如下:
微调:这涉及对目标任务上学到的模型进行优化。如果你参与过机器学习,尤其是在计算机视觉或自然语言处理领域,你可能已经使用过这种技术。不幸的是,在强化学习中,微调并不像在上述领域那样容易,因为它需要更精细的工程设计,并且通常带来的收益较小。其原因在于,一般而言,两个强化学习任务之间的差距比两个不同图像领域之间的差距要大。例如,猫和狗的分类差异较小,而 Pong 和 Breakout 之间的差异则较大。然而,微调仍然可以在强化学习中使用,调整最后几层(或者在动作空间完全不同的情况下替换它们)可能会带来更好的泛化能力。
领域随机化:这一方法基于这样一个思想,即源领域的动态多样化可以增强策略在新环境中的鲁棒性。领域随机化通过操控源领域来实现,例如,通过改变仿真器的物理特性,使得在多个随机修改的源领域上训练的策略足够鲁棒,能够在目标领域中表现良好。这种策略对于训练需要应用于现实世界的代理更加有效。在这种情况下,策略更具鲁棒性,仿真不必与物理世界完全相同,仍然能够提供所需的性能水平。
领域适应:这是另一个常用的过程,尤其用于将仿真源领域的策略映射到目标物理世界。领域适应的核心是将源领域的数据分布调整为与目标领域匹配。它主要应用于基于图像的任务,模型通常使用生成对抗网络(GANs)将合成图像转化为真实图像。
在多任务学习中,代理已训练的环境数量越多,代理在目标环境上的多样性和性能就会越好。多个源任务可以由一个或多个代理来学习。如果只有一个代理被训练,那么将其部署到目标任务上很容易。否则,如果多个代理学习了不同的任务,那么得到的策略可以作为一个集成模型使用,并对目标任务的预测进行平均,或者使用一个名为蒸馏的中间步骤,将多个策略合并为一个。具体来说,蒸馏过程将多个模型的知识压缩成一个,便于部署且推理速度更快。
到目前为止,在本章中,我们介绍了开发深度强化学习算法的最佳实践和强化学习背后的挑战。我们还看到无监督强化学习和元学习如何缓解低效和泛化不良的问题。现在,我们想向你展示在将强化学习智能体应用于真实世界时需要解决的问题,以及如何弥合模拟环境中的差距。
设计一个能够在真实世界中执行动作的智能体是非常具有挑战性的。但大多数强化学习应用需要在现实世界中部署。因此,我们必须了解在面对物理世界的复杂性时所面临的主要挑战,并考虑一些有用的技术。
除了样本效率和泛化能力方面的重大问题之外,在处理真实世界时,我们还需要面对诸如安全性和领域约束等问题。事实上,由于安全性和成本约束,智能体通常不能自由地与世界进行交互。一种解决方案可能来自使用约束算法,例如 TRPO 和 PPO,这些算法被嵌入系统机制中,以限制在训练过程中行动的变化。这可以防止智能体行为的剧烈变化。不幸的是,在高度敏感的领域,这还不够。例如,如今,你不能直接在道路上开始训练自动驾驶汽车。政策可能需要经过数百或数千个周期才能理解从悬崖上掉下来会导致不良结果,并学会避免这种情况。先在模拟中训练政策的替代方案是可行的。然而,当应用到城市环境时,必须做出更多与安全相关的决策。
正如我们刚才提到的,模拟优先的解决方案是一种可行的方法,根据实际任务的复杂性,它可能会带来良好的性能。然而,模拟器必须尽可能地模仿真实世界的环境。例如,如果下图左侧的模拟器与右侧的真实世界相似,那么该模拟器就无法使用。真实世界与模拟世界之间的差距被称为现实差距:
https://github.com/OpenDocCN/freelearn-dl-pt3-zh/raw/master/docs/hsn-rl-algo-py/img/0687367a-cd9f-4f80-b4ab-570182383d94.png
图 13.6. 人工世界与物理世界的比较
另一方面,使用高度准确和现实的环境可能也不可行。瓶颈现在是模拟器所需的计算能力。这个限制可以通过从一个速度更快、精度更低的模拟器开始,并逐步增加保真度以缩小现实差距来部分克服。最终,这将牺牲速度,但此时,代理应该已经学习了大部分任务,可能只需要少量的迭代来进行微调。然而,开发高度准确的模拟器来模拟物理世界是非常困难的。因此,在实践中,现实差距将依然存在,改善泛化的技术将有责任处理这种情况。
为了从模拟到现实世界无缝过渡,从而克服现实差距,我们之前提出的一些泛化技术,例如领域自适应和领域随机化,可以被使用。例如,在论文《学习灵巧的手内操作》中,作者通过领域随机化训练了一个类人机器人,利用惊人的灵巧性操作物理物体。该策略通过许多不同的平行模拟进行训练,这些模拟旨在提供具有随机物理和视觉属性的多样化体验。这种偏向于泛化而非现实的机制至关重要,考虑到系统在部署时展示了一系列丰富的手内灵巧操作策略,其中许多策略也被人类使用。
出于教育目的,在本书中,我们主要使用了适合我们需求的快速且小规模的任务。然而,现有许多模拟器可以用于运动任务(如 Gazebo、Roboschool 和 Mujoco)、机械工程、运输、自动驾驶汽车、安全等。这些现有环境种类繁多,但并不是每个应用都有现成的模拟器。因此,在某些情况下,你可能需要自己创建环境。
奖励函数本身很难设计,但它是强化学习(RL)中的关键部分。如果奖励函数设置错误,环境可能无法解决,代理可能会学到错误的行为。在第一章《强化学习的全景》中,我们举了一个赛船游戏的例子,其中船通过绕圈子来最大化奖励,捕捉重新生成的目标,而不是尽可能快地朝着轨迹终点行驶。这些就是在设计奖励函数时需要避免的行为。
设计奖励函数的一般建议(适用于任何环境)是使用正奖励来激励探索,并通过负奖励来抑制终止状态,或者如果目标是尽可能快速地达到终止状态,则使用负奖励。奖励函数的形状是一个重要的考虑因素。在本书中,我们曾多次警告稀疏奖励的问题。一个理想的奖励函数应该提供平滑且密集的反馈。
如果由于某些原因,奖励函数非常难以用公式表示,可以通过两种额外方式提供监督信号:
使用模仿学习或逆强化学习展示任务。
使用人类偏好来提供关于智能体行为的反馈。
后者仍然是一种新颖的方法,如果你对此感兴趣,可以阅读论文《从依赖策略的人类反馈中进行深度强化学习》(arxiv.org/abs/1902.04257
),这将是一本有趣的读物。
人工智能的最初基础建立于 50 多年前,但直到最近几年,人工智能所带来的创新才作为主流技术传播到世界各地。这一波创新的浪潮主要得益于深度神经网络在监督学习系统中的演变。然而,人工智能的最新突破涉及强化学习,特别是深度强化学习。在围棋和 Dota 游戏中取得的成果突显了强化学习算法的卓越质量,这些算法能够进行长期规划、展现团队协作能力,并发现新的游戏策略,甚至是人类难以理解的策略。
在模拟环境中取得的显著成果开启了强化学习在物理世界中的新应用浪潮。我们才刚刚开始,但许多领域正在并将继续受到影响,带来深刻的变革。嵌入日常生活中的强化学习智能体可以通过自动化繁琐的工作、解决全球性挑战、发现新药物等方式提升生活质量——这些只是一些可能性。然而,这些将在我们世界和生活中广泛应用的系统需要安全可靠。目前我们尚未达到这一点,但我们在朝着正确的方向迈进。
AI 的伦理使用已经成为广泛关注的问题,比如在使用自主武器时。随着技术的快速发展,政策制定者和民众很难在这些问题上进行开放讨论。许多有影响力和有声望的人也认为 AI 是对人类的潜在威胁。但未来是无法预测的,且技术还有很长的路要走,才能开发出具备与人类相当能力的代理。我们有创造力、情感和适应性,这些现在是强化学习无法模拟的。
通过细心的关注,强化学习带来的短期益处可以显著超过其负面影响。但是,要将复杂的强化学习代理嵌入到物理环境中,我们需要解决之前提到的强化学习挑战。这些问题是可以解决的,一旦解决,强化学习有可能减少社会不平等,改善我们的生活质量以及地球的质量。
在本书中,我们学习并实现了许多强化学习算法,但所有这些不同的算法在选择时可能会让人感到困惑。因此,在最后一章中,我们提供了一个经验法则,帮助你选择最适合你问题的强化学习算法类别。它主要考虑算法的计算时间和样本效率。此外,我们还提供了一些技巧,以帮助你更好地训练和调试深度强化学习算法,从而使这个过程更容易。
我们还讨论了强化学习中的隐性挑战:稳定性与可复现性、效率和泛化能力。这些是必须克服的主要问题,以便将强化学习代理应用于物理世界。事实上,我们详细介绍了无监督强化学习和迁移学习,这两种策略可以大大提高泛化能力和样本效率。
此外,我们详细阐述了强化学习可能对我们的生活产生的最关键的开放性问题,以及它在文化和技术方面的影响。
我们希望这本书能让你对强化学习有一个全面的了解,并激发你对这个迷人领域的兴趣。
你会如何根据样本效率来排名 DQN、A2C 和 ES?
如果根据训练时间并且提供 100 个 CPU,他们的排名会如何?
你会在调试强化学习算法时从 CartPole 还是 MontezumaRevenge 开始?
为什么在比较多个深度强化学习算法时,使用多个种子更好?
内在奖励是否有助于环境探索?
什么是迁移学习?
如果你对在 Atari 游戏中使用纯粹的好奇心驱动方法感兴趣,可以阅读这篇论文 Large-scale study of curiosity-driven learning (arxiv.org/pdf/1808.04355.pdf
)。
关于将领域随机化应用于学习灵巧的手内操作,阅读论文 学习灵巧的手内操作 (arxiv.org/pdf/1808.00177.pdf
)。
关于展示如何将人类反馈作为奖励函数的替代方法的工作,阅读论文 基于策略依赖的人类反馈的深度强化学习 (arxiv.org/pdf/1902.04257.pdf
)。
第三章
什么是随机策略?
如何用下一个时间步的回报来定义回报?
为什么贝尔曼方程如此重要?
DP 算法的限制因素是什么?
什么是策略评估?
策略迭代和价值迭代有什么区别?
第四章
RL 中使用的 MC 方法的主要特点是什么?
为什么蒙特卡洛(MC)方法是离线的?
TD 学习的两大主要思想是什么?
MC 和 TD 有什么不同?
为什么探索在 TD 学习中如此重要?
为什么 Q 学习是脱离策略的?
第五章
死亡三元组问题的产生原因是什么?
DQN 如何克服不稳定性?
什么是移动目标问题?
DQN 是如何减轻移动目标问题的?
DQN 中使用的优化过程是什么?
状态-动作优势值函数的定义是什么?
第六章
PG 算法如何最大化目标函数?
PG 算法背后的主要直觉是什么?
为什么在 REINFORCE 中引入基准仍然保持无偏?
REINFORCE 属于哪个更广泛的算法类别?
AC 方法中的评论员(critic)与 REINFORCE 中作为基准使用的价值函数有何不同?
如果你需要为一个必须学会移动的代理开发算法,你会选择 REINFORCE 还是 AC?
你可以使用 n 步演员-评论员算法作为 REINFORCE 算法吗?
第七章
策略神经网络如何控制一个连续的代理?
什么是 KL 散度?
TRPO 背后的主要思想是什么?
KL 散度在 TRPO 中是如何使用的?
PPO 的主要优点是什么?
PPO 是如何实现良好的样本效率的?
第八章
Q 学习算法的主要限制是什么?
为什么随机梯度算法样本效率低?
确定性策略梯度是如何克服最大化问题的?
DPG 是如何保证足够的探索的?
DDPG 代表什么?它的主要贡献是什么?
TD3 提出了哪些问题以进行最小化?
TD3 采用了哪些新机制?
第九章
如果你只有 10 局棋的时间来训练你的智能体玩跳棋,你会选择基于模型的算法还是无模型的算法?
基于模型的算法有哪些缺点?
如果环境的模型未知,如何学习该模型?
为什么要使用数据聚合方法?
ME-TRPO 如何稳定训练过程?
为什么一组模型可以改善策略学习?
第十章
模仿学习是否被视为强化学习技术?
你会使用模仿学习来构建一个不可战胜的围棋智能体吗?
DAgger 的全名是什么?
DAgger 的主要优势是什么?
在什么情况下你会使用 IRL 而不是 IL?
第十一章
有哪两种强化学习的替代算法可以解决顺序决策问题?
在进化算法中,哪些过程会产生新的个体?
启发式算法,如遗传算法,的灵感来源于什么?
CMA-ES 如何进化进化策略?
进化策略的一个优点和一个缺点是什么?
在“进化策略作为可扩展的强化学习替代方案”论文中,采用了什么技巧来减少方差?
第十二章
什么是探索-开发困境?
我们在之前的 RL 算法中使用过哪两种探索策略?
什么是 UCB?
是 Montezuma’s Revenge 还是多臂老虎机问题更难解决?
ESBAS 如何解决在线 RL 算法选择的问题?
第十三章
如何根据样本效率对 DQN、A2C 和 ES 进行排名?
如果按训练时间和可用的 100 个 CPU 排名,它们的排名会是多少?
你会在 CartPole 还是 MontezumaRevenge 上开始调试一个 RL 算法?
为什么在比较多个深度 RL 算法时,使用多个种子会更好?
内在奖励是否有助于环境的探索?
什么是迁移学习?