TensorFlow 2.0深度强化学习指南

2023-11-04

在本教程中,我将通过实施Advantage Actor-Critic(演员-评论家,A2C)代理来解决经典的CartPole-v0环境,通过深度强化学习(DRL)展示即将推出的TensorFlow2.0特性。虽然我们的目标是展示TensorFlow2.0,但我将尽最大努力让DRL的讲解更加平易近人,包括对该领域的简要概述。

事实上,由于2.0版本的焦点是让开发人员的生活变得更轻松,所以我认为现在是使用TensorFlow进入DRL的好时机,本文用到的例子的源代码不到150行!代码可以在这里或者这里获取。

建立

由于TensorFlow2.0仍处于试验阶段,我建议将其安装在独立的虚拟环境中。我个人比较喜欢Anaconda,所以我将用它来演示安装过程:

> conda create -n tf2 python=3.6
> source activate tf2
> pip install tf-nightly-2.0-preview # tf-nightly-gpu-2.0-preview for GPU version

让我们快速验证一切是否按能够正常工作

>>> import tensorflow as tf
>>> print(tf.__version__)
1.13.0-dev20190117
>>> print(tf.executing_eagerly())
True

不要担心1.13.x版本,这只是意味着它是早期预览这里要注意的是我们默认处于eager模式

>>> print(tf.reduce_sum([1, 2, 3, 4, 5]))
tf.Tensor(15, shape=(), dtype=int32)

如果你还不熟悉eager模式,那么实质上意味着计算是在运行时被执行的,而不是通过预编译的图(曲线图)来执行。你可以在TensorFlow文档中找到一个很好的概述。

深度化学

一般而言,强化学习是解决连续决策问题的高级框架。RL通过基于某些agent进行导航观察环境,并且获得奖励。大多数RL算法通过最大化代理在一轮游戏期间收集的奖励总和来工作。

基于RL的算法的出通常是policy(策略)-将状映射到函数有效的策略中,有效的策略可以像硬编码的无操作作一样简单。在某些状下,随机策略表示的条件概率分布。

61aff31e7638c235a2c51ff1b5b07b4ca4c5de3b

评论家方(Actor-Critic Methods)

RL算法通常基于它们优化的目标函数进行分组。Value-based诸如DQN之类的方法通过减少预期的状态-动作值的误差来工作。

策略梯度(Policy Gradients)方法通过调整其参数直接优化策略本身,通常通过梯度下降完成的。完全计算梯度通常是难以处理的,因此通常要通过蒙特卡罗方法估算它们。

最流行的方法是两者的混合:actor-critic方法,其中代理策略通过策略梯度进行优化,而基于值的方法用作预期值估计的引导。

深度演-方法

虽然很多基础的RL理论是在表格案例中开发的,但现代RL几乎完全是用函数逼近器完成的,例如人工神经网络。具体而言,如果策略和值函数用深度神经网络近似,则RL算法被认为是“深度”。

83552e48fe15d56d18af4cf118096bef34180ac4

异步优势-评论家(actor-critical)

多年来,为了提高学习过程的样本效率和稳定性,技术发明者已经进行了一些改进。

首先,梯度加权回报:折现的未来奖励,这在一定程度上缓解了信用分配问题,并以无限的时间步长解决了理论问题。

其次,使用优势函数代替原始回报。优势在收益与某些基线之间的差异之间形成,并且可以被视为衡量给定值与某些平均值相比有多好的指标。

第三,在目标函数中使用额外的熵最大化项以确保代理充分探索各种策略。本质上,熵以均匀分布最大化来测量概率分布的随机性。

最后,并行使用多个工人加速样品采集,同时在训练期间帮助它们去相关。

将所有这些变化与深度神经网络相结合,我们得出了两种最流行的现代算法:异步优势演员评论家(actor-critical)算法,简称A3C或者A2C。两者之间的区别在于技术性而非理论性:顾名思义,它归结为并行工人如何估计其梯度并将其传播到模型中。

f52c30a089f7f8d00d97f1a6723f0a8681ed470e

有了这个,我将结束我们的DRL方法之旅,因为博客文章的重点更多是关于TensorFlow2.0的功能。如果你仍然不了解该主题,请不要担心,代码示例应该更清楚。如果你想了解更多,那么一个好的资源就可以开始Deep RL中进行Spinning Up

使用TensorFlow 2.0优势-评论

让我们看看实现现代DRL算法的基础是什么:演员评论家代理(actor-critic agent。如前一节所述,为简单起见,我们不会实现并行工作程序,尽管大多数代码都会支持它,感兴趣的读者可以将其用作锻炼机会。

作为测试平台,我们将使用CartPole-v0环境。虽然它有点简单,但它仍然是一个很好的选择开始。在实现RL算法时,我总是依赖它作为一种健全性检查。

Keras Model API实现的策略和价值

首先,让我们在单个模型类下创建策略和价值估计NN:

import numpy as np
import tensorflow as tf
import tensorflow.keras.layers as kl

class ProbabilityDistribution(tf.keras.Model):
    def call(self, logits):
        # sample a random categorical action from given logits
        return tf.squeeze(tf.random.categorical(logits, 1), axis=-1)

class Model(tf.keras.Model):
    def __init__(self, num_actions):
        super().__init__('mlp_policy')
        # no tf.get_variable(), just simple Keras API
        self.hidden1 = kl.Dense(128, activation='relu')
        self.hidden2 = kl.Dense(128, activation='relu')
        self.value = kl.Dense(1, name='value')
        # logits are unnormalized log probabilities
        self.logits = kl.Dense(num_actions, name='policy_logits')
        self.dist = ProbabilityDistribution()

    def call(self, inputs):
        # inputs is a numpy array, convert to Tensor
        x = tf.convert_to_tensor(inputs, dtype=tf.float32)
        # separate hidden layers from the same input tensor
        hidden_logs = self.hidden1(x)
        hidden_vals = self.hidden2(x)
        return self.logits(hidden_logs), self.value(hidden_vals)

    def action_value(self, obs):
        # executes call() under the hood
        logits, value = self.predict(obs)
        action = self.dist.predict(logits)
        # a simpler option, will become clear later why we don't use it
        # action = tf.random.categorical(logits, 1)
        return np.squeeze(action, axis=-1), np.squeeze(value, axis=-1)

验证我们验证模型是否按预期工作

import gym
env = gym.make('CartPole-v0')
model = Model(num_actions=env.action_space.n)
obs = env.reset()
# no feed_dict or tf.Session() needed at all
action, value = model.action_value(obs[None, :])
print(action, value) # [1] [-0.00145713]

这里要注意的事项:

  • 模型层和执行路径是分开定义的;
  • 没有输入图层,模型将接受原始numpy数组;
  • 可以通过函数API在一个模型中定义两个计算路径;
  • 模型可以包含一些辅助方法,例如动作采样;
  • 在eager的模式下,一切都可以从原始的numpy数组中运行;

随机代理

现在我们可以继续学习一些有趣的东西A2CAgent类。首先,让我们添加一个贯穿整集的test方法并返回奖励总和。

class A2CAgent:
    def __init__(self, model):
        self.model = model
    def test(self, env, render=True):
        obs, done, ep_reward = env.reset(), False, 0
        while not done:
            action, _ = self.model.action_value(obs[None, :])
            obs, reward, done, _ = env.step(action)
            ep_reward += reward
            if render:
                env.render()
        return ep_reward

让我们看看我们的模型在随机初始化权重下得分多少

agent = A2CAgent(model)
rewards_sum = agent.test(env)
print("%d out of 200" % rewards_sum) # 18 out of 200

离最佳转台还有很远,接下来是训练部分!

损失/函数

正如我在DRL概述部分所描述的那样,代理通过基于某些损失(目标)函数的梯度下降来改进其策略。在演员评论家中,我们训练了三个目标:用优势加权梯度加上熵最大化来改进策略,并最小化价值估计误差。

import tensorflow.keras.losses as kls
import tensorflow.keras.optimizers as ko
class A2CAgent:
    def __init__(self, model):
        # hyperparameters for loss terms
        self.params = {'value': 0.5, 'entropy': 0.0001}
        self.model = model
        self.model.compile(
            optimizer=ko.RMSprop(lr=0.0007),
            # define separate losses for policy logits and value estimate
            loss=[self._logits_loss, self._value_loss]
        )

    def test(self, env, render=True):
        # unchanged from previous section
        ...

    def _value_loss(self, returns, value):
        # value loss is typically MSE between value estimates and returns
        return self.params['value']*kls.mean_squared_error(returns, value)

    def _logits_loss(self, acts_and_advs, logits):
        # a trick to input actions and advantages through same API
        actions, advantages = tf.split(acts_and_advs, 2, axis=-1)
        # polymorphic CE loss function that supports sparse and weighted options
        # from_logits argument ensures transformation into normalized probabilities
        cross_entropy = kls.CategoricalCrossentropy(from_logits=True)
        # policy loss is defined by policy gradients, weighted by advantages
        # note: we only calculate the loss on the actions we've actually taken
        # thus under the hood a sparse version of CE loss will be executed
        actions = tf.cast(actions, tf.int32)
        policy_loss = cross_entropy(actions, logits, sample_weight=advantages)
        # entropy loss can be calculated via CE over itself
        entropy_loss = cross_entropy(logits, logits)
        # here signs are flipped because optimizer minimizes
        return policy_loss - self.params['entropy']*entropy_loss

我们完成了目标函数!请注意代码的紧凑程度:注释行几乎比代码本身多。

代理训练

最后,还有训练回路本身,它相对较长,但相当简单:收集样本,计算回报和优势,并在其上训练模型。

class A2CAgent:
    def __init__(self, model):
        # hyperparameters for loss terms
        self.params = {'value': 0.5, 'entropy': 0.0001, 'gamma': 0.99}
        # unchanged from previous section
        ...
        
   def train(self, env, batch_sz=32, updates=1000):
        # storage helpers for a single batch of data
        actions = np.empty((batch_sz,), dtype=np.int32)
        rewards, dones, values = np.empty((3, batch_sz))
        observations = np.empty((batch_sz,) + env.observation_space.shape)
        # training loop: collect samples, send to optimizer, repeat updates times
        ep_rews = [0.0]
        next_obs = env.reset()
        for update in range(updates):
            for step in range(batch_sz):
                observations[step] = next_obs.copy()
                actions[step], values[step] = self.model.action_value(next_obs[None, :])
                next_obs, rewards[step], dones[step], _ = env.step(actions[step])

                ep_rews[-1] += rewards[step]
                if dones[step]:
                    ep_rews.append(0.0)
                    next_obs = env.reset()

            _, next_value = self.model.action_value(next_obs[None, :])
            returns, advs = self._returns_advantages(rewards, dones, values, next_value)
            # a trick to input actions and advantages through same API
            acts_and_advs = np.concatenate([actions[:, None], advs[:, None]], axis=-1)
            # performs a full training step on the collected batch
            # note: no need to mess around with gradients, Keras API handles it
            losses = self.model.train_on_batch(observations, [acts_and_advs, returns])
        return ep_rews

    def _returns_advantages(self, rewards, dones, values, next_value):
        # next_value is the bootstrap value estimate of a future state (the critic)
        returns = np.append(np.zeros_like(rewards), next_value, axis=-1)
        # returns are calculated as discounted sum of future rewards
        for t in reversed(range(rewards.shape[0])):
            returns[t] = rewards[t] + self.params['gamma'] * returns[t+1] * (1-dones[t])
        returns = returns[:-1]
        # advantages are returns - baseline, value estimates in our case
        advantages = returns - values
        return returns, advantages
    def test(self, env, render=True):
        # unchanged from previous section
        ...
    def _value_loss(self, returns, value):
        # unchanged from previous section
        ...

    def _logits_loss(self, acts_and_advs, logits):
        # unchanged from previous section
        ...

训练和

我们现在已经准备好在CartPole-v0上训练我们的单工A2C代理了!训练过程不应超过几分钟,训练完成后,你应该看到代理成功达到200分中的目标。

rewards_history = agent.train(env)
print("Finished training, testing...")
print("%d out of 200" % agent.test(env)) # 200 out of 200

fe57bd94e74ec6673c03baee707695fa5be7d788

在源代中,我包含了一些外的帮助程序,可以打印出运行的励和失,以及rewards_history的基本绘图仪

18a85961a67286eb9c626bed849396ef1843e657

态计

有了所有这种渴望模式的成功的喜悦,你可能想知道静态图形执行是否可以。当然!此外,我们还需要多一行代码来启用它!

with tf.Graph().as_default():
    print(tf.executing_eagerly()) # False
    model = Model(num_actions=env.action_space.n)
    agent = A2CAgent(model)
    rewards_history = agent.train(env)
    print("Finished training, testing...")
    print("%d out of 200" % agent.test(env)) # 200 out of 200

有一点需要注意,在静态图形执行期间,我们不能只有Tensors,这就是为什么我们在模型定义期间需要使用CategoricalDistribution的技巧。事实上,当我在寻找一种在静态模式下执行的方法时,我发现了一个关于通过Keras API构建的模型的一个有趣的低级细节。

还有一件事

还记得我说过TensorFlow默认是运行在eager模式下吧,甚至用代码片段证明它吗?好吧,我错了。

如果你使用Keras API来构建和管理模型,那么它将尝试将它们编译为静态图形。所以你最终得到的是静态计算图的性能,具有渴望执行的灵活性。

你可以通过model.run_eagerly标志检查模型的状态,你也可以通过设置此标志来强制执行eager模式变成True,尽管大多数情况下你可能不需要这样做。但如果Keras检测到没有办法绕过eager模式,它将自动退出。

为了说明它确实是作为静态图运行,这里是一个简单的基准测试:

# create a 100000 samples batch
env = gym.make('CartPole-v0')
obs = np.repeat(env.reset()[None, :], 100000, axis=0)

Eager基准

%%time
model = Model(env.action_space.n)
model.run_eagerly = True
print("Eager Execution:  ", tf.executing_eagerly())
print("Eager Keras Model:", model.run_eagerly)
_ = model(obs)
######## Results #######
Eager Execution:   True
Eager Keras Model: True
CPU times: user 639 ms, sys: 736 ms, total: 1.38 s

基准

%%time
with tf.Graph().as_default():
    model = Model(env.action_space.n)
    print("Eager Execution:  ", tf.executing_eagerly())
    print("Eager Keras Model:", model.run_eagerly)
    _ = model.predict(obs)
######## Results #######
Eager Execution:   False
Eager Keras Model: False
CPU times: user 793 ms, sys: 79.7 ms, total: 873 ms

基准

%%time
model = Model(env.action_space.n)
print("Eager Execution:  ", tf.executing_eagerly())
print("Eager Keras Model:", model.run_eagerly)
_ = model.predict(obs)
######## Results #######
Eager Execution:   True
Eager Keras Model: False
CPU times: user 994 ms, sys: 23.1 ms, total: 1.02 s

正如你所看到的,eager模式是静态模式的背后,默认情况下,我们的模型确实是静态执行的。

结论

希望本文能够帮助你理解DRL和TensorFlow2.0。请注意,TensorFlow2.0仍然只是预览版本,甚至不是候选版本,一切都可能发生变化。如果TensorFlow有什么东西你特别不喜欢,让它的开发者知道

人们可能会有一个挥之不去的问题:TensorFlow比PyTorch好吗?也许,也许不是。它们两个都是伟大的库,所以很难说这样谁好,谁不好。如果你熟悉PyTorch,你可能已经注意到TensorFlow 2.0不仅赶上了它,而且还避免了一些PyTorch API的缺陷。

在任何一种情况下,对于开发者来说,这场竞争都已经为双方带来了积极的结果,我很期待看到未来的框架将会变成什么样。

本文由阿里云云栖社区组织翻译。

文章原标题《Deep Reinforcement Learning with TensorFlow 2.0

译者:乌拉乌拉,审校:袁虎。

文章为简译,更为详细的内容,请查看原文

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TensorFlow 2.0深度强化学习指南 的相关文章

随机推荐

  • C++实现——卡特兰数列及其应用

    卡特兰数列的原理及其应用场景 令h 1 1 catalan数满足递归式 h n h 1 h n 1 h 2 h n 2 h n 1 h 1 其中n gt 2 该递推关系的解为 h n c 2n 2 n 1 n n 1 2 3 1 1 2 5
  • 什么是Java中的公平锁?

    一直想分析下公平锁和非公平锁在Java中的实现 公平锁 Fair 加锁前检查是否有排队等待的线程 优先排队等待的线程 先来先得非公平锁 Nonfair 加锁时不考虑排队等待问题 直接尝试获取锁 获取不到自动到队尾等待 首先Java中的Ree
  • springboot+mybatis自动生成插件+echars小练习

    概述 通过ajax异步从后台读取数据 用 eachars 在thymeleaf当中显示 建表用的是navicat12 支持正版 软件网盘地址 https pan baidu com s 1brJFVrdDdkP3XwkWND3 mA 1 建
  • unity webGL:collisionMeshData couldn’t be created because the mesh has been marked as non-accessible

    因为Unity从外部导入的fbx文件需要开启Read Write 功能 在webGL中才能进行MeshCollider的相关操作 如添加PointerEnter等 解决 在Inspector面板开启预置体的Read Write Enable
  • cmake 编译boost库遇到的坑

    错误 CMakeFiles main dir main cpp o In function boost asio detail posix event posix event usr local include boost asio det
  • ChatGPT将抢占谁的工作,未来如何应对

    AI人工智能领域里程碑式应用 ChatGPT影响力已经越来越大 激起大家强烈好奇心的同时 也让一些人发出了 感觉自己快要失业了 的焦虑 今天先说一下哪些人的工作会受到 ChatGPT等AI人工智能影响 从工业时代到数字时代这100多年的发展
  • LeetCode之最值问题系列问题求解

    最值系列题目求解 这类型题目的特点就是一个数组 或者字符串 给的条件是连续或者不连续 或者给定限定条件进行求解的情况 解题的关键 采用两个变量 一个变量记录前面的条件 或者最后一个不满足题意的index 或者最小值 比如股票题目当中j 或者
  • 【工具类】使用阿里oss实现图片、视频、文档上传

    使用阿里oss实现图片 视频 文档上传 一 背景描述 二 引入依赖 三 配置文件 四 接口实现 一 背景描述 功能是想实现图片 视频和文档的上传 项目技术栈 springboot 2 1 5 RELEASE 二 引入依赖
  • “火柴棒等式”【题解】

    火柴棒等式 的题目 题目 题目描述 给你n根火柴棍 你可以拼出多少个形如 A B C 的等式 等式中的A B C是用火柴棍拼出的整数 若该数非零 则最高位不能是0 用火柴棍拼数字0 9的拼法如图所示 注意 1 加号与等号各自需要两根火柴棍
  • 斐讯K1、K2、K2P 刷机、刷入Breed@重庆网吧电竞酒店维护小哥

    支持的版本 官方固件版本 K1 V22 4 XX XX K1S V22 3 XX XX K2 V22 2 XX XX V22 3 XX XX V22 4 XX XX V22 5 XX XX V22 6 XX XX K2P V22 8 5 1
  • Java反射之Method的invoke方法实现

    使用reflect 反射 包下面的Field和Method类获得类的属性和方法 并对属性和方法进行操作 在框架中经常会会用到method invoke 方法 用来执行某个的对象的目标方法 以前写代码用到反射时 总是获取先获取Method 然
  • NotImplementedError: Could not run ‘torchvision::nms‘ with arguments from the ‘CUDA‘ backend解决办法

    NotImplementedError Could not run torchvision nms with arguments from the CUDA backend This could be because the operato
  • [项目管理-22]:项目中开环、闭环、安全、监控四种沟通模型:UDP/TCP/SCTP/PID模型

    目录 前言 第1章 项目中闭环沟通模型 1 1 沟通模型 1 2 开环沟通 1 3 闭环沟通 1 4 闭环监控式沟通 第2章 TCP UDP SCTP通信模型在项目管理中的应用 2 1 UDP模式沟通 2 2 TCP模式沟通 2 3 SCT
  • GB28181智慧可视化指挥控制系统之执法记录仪设计探讨

    什么是智慧可视化指挥控制系统 智慧可视化指挥控制平台通过4G 5G网络 WIFI实时传输视音频数据至指挥中心 特别是在有突发情况时 可以指定一台执法仪为现场视频监控器 实时传输当前画面到指挥中心 指挥中心工作人员可通过麦克风向现场执法人员下
  • golang高精度十进制数扩展包decimal用法

    在Go语言中 没有内置的十进制数 decimal 类型或相关的标准库 然而 有一些第三方包可用于处理十进制数 其中比较常用的是decimal包 decimal包提供了一个big Float的子类型decimal Decimal 可以用于表示
  • 快捷指令url大全

    支付宝付款码 alipay platformapi startapp appId 20000056 支付宝健康码 alipays platformapi startapp appId 20000067 chInfo ch desktop u
  • 两个有序链表的合并(超详细)

    不知道大家有没有做过一道经典的题目 两个长度为15的有序链表的合并 大家先看题目 那么这道题该如何做尼 首先我们用比较笨的办法 用链表做 首先我们创建两个链表 那么该如何将两个链表合并尼 只需要创建两个指针 指向两个链表 然后比较两个链表中
  • Git的一些命令行

    1 创建一个分支git branch 分支名字 2 提交git commit 3 换主支git checkout 要换到的名字那儿 4合并git merge 分支名字 合并到当前那个支上 且那个支会指向两个父节点 5 git rebase取
  • 南溪的远程桌面软件使用笔记

    1 介绍 远程桌面软件可以让我们远程操作另一个主机的用户界面 Note TeamViewer付费一次后 就会强制自动续费一年 如果取消订阅需要提前续订日期前至少28天 28天的提前期实在太长了 TeamViewer这个公司十分黑心 以后注意
  • TensorFlow 2.0深度强化学习指南

    在本教程中 我将通过实施Advantage Actor Critic 演员 评论家 A2C 代理来解决经典的CartPole v0环境 通过深度强化学习 DRL 展示即将推出的TensorFlow2 0特性 虽然我们的目标是展示Tensor