提交 3fa4a4ef 编写于 作者: W wizardforcel

2021-01-21 17:23:08

上级 dcbbae7a
......@@ -26,7 +26,7 @@
“第 5 章”,“样式迁移”,演示了执行样式迁移任务的过程,其中将两个图像作为输入来创建新图像,并使用来自两个输入图像的元素。
“第 6 章”,“使用 RNN 分析数据序列”,更详细地探讨了循环神经网络。 在本章中,使用顺序数据作为输入解决了三个流行的数据问题。
“第 6 章”,“使用 RNN 分析数据序列”,更详细地探讨了循环神经网络。 在本章中,使用序列数据作为输入解决了三个流行的数据问题。
## 约定
......
......@@ -546,7 +546,7 @@ for i in range(100):
要切片 pandas `DataFrame`,请使用 pandas 的`iloc`方法。 要了解有关此方法的更多信息,请访问[这里](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html)。
4. 定义模型的架构,并将其存储在名为`model`的变量中。 记住要创建一个单层模型。
5. 定义要使用的损失函数。 在这种情况下,请使用 MSE 损失功能
5. 定义要使用的损失函数。 在这种情况下,请使用 MSE 损失函数
6. 定义模型的优化器。 在这种情况下,请使用 Adam 优化器,并将学习率设为`0.01`。
7. 对 100 次迭代运行优化,保存每次迭代的损失值。 每 10 次迭代打印一次损失值。
8. 绘制线图以显示每个迭代步骤的损耗值。
......
......@@ -682,4 +682,4 @@ style_features = features_extractor(style_img, model, \
通过最小化总损耗的值来创建目标图像,这可以通过更新与目标图像有关的参数来完成。 尽管可以使用预先训练的网络,但获得理想目标图像的过程可能需要进行数千次迭代和相当多的时间。
在下一章中,将说明不同的网络架构,以便使用文本数据序列解决数据问题。 RNN 是保存内存的神经网络架构,允许它们处理顺序数据。 它们通常用于解决与人类语言理解有关的问题。
\ No newline at end of file
在下一章中,将说明不同的网络架构,以便使用文本数据序列解决数据问题。 RNN 是保存内存的神经网络架构,允许它们处理序列数据。 它们通常用于解决与人类语言理解有关的问题。
\ No newline at end of file
......@@ -8,7 +8,7 @@
在前面的章节中,介绍了不同的网络架构-从可以同时解决分类和回归问题的传统 ANN 到主要用于通过执行对象分类,定位,检测和分段任务来解决计算机视觉问题的 CNN 。
在最后一章中,我们将探讨 RNN 的概念并解决顺序数据问题。 这些网络架构能够保存上下文至关重要的顺序数据,这要归功于它们能够保存来自先前预测的信息(称为内存)。 这意味着,例如,当逐个单词分析句子时,RNN 在处理最后一个单词时可以保留有关该单词第一个单词的信息。
在最后一章中,我们将探讨 RNN 的概念并解决序列数据问题。 这些网络架构能够保存上下文至关重要的序列数据,这要归功于它们能够保存来自先前预测的信息(称为内存)。 这意味着,例如,当逐个单词分析句子时,RNN 在处理最后一个单词时可以保留有关该单词第一个单词的信息。
本章将探讨 LSTM 网络架构,它是一种 RNN,可以同时存储长期和短期内存,并且对于处理长数据序列(例如视频剪辑)特别有用。
......@@ -122,9 +122,9 @@
![Figure 6.9: Input and target variables for a sequenced data problem ](img/B15778_06_09.jpg)
图 6.9:顺序数据问题的输入变量和目标变量
图 6.9:序列数据问题的输入变量和目标变量
## 练习 6.01:为顺序数据问题创建输入和目标变量
## 练习 6.01:为序列数据问题创建输入和目标变量
在本练习中,您将使用虚拟数据集学习如何创建可用于解决排序数据问题的输入和目标变量。 请按照以下步骤完成此练习:
......
......@@ -75,7 +75,7 @@
![Figure 1.4: Loss function throughout the training process ](img/B15778_01_04.jpg)
图 1.4:整个训练过程中的损失功能
图 1.4:整个训练过程中的损失函数
这意味着训练过程能够使损失函数最小化,这意味着结果模型将可能能够绘制出市民对城市服务的满意度与他们对行政管理是否满意之间的关系。
......
......@@ -123,7 +123,7 @@
尽管对比损失函数是学习判别特征的一种好方法,但是在连体网络架构的其他修改版本中,对比损失函数不能非常清楚地学习决策边界。 在这种情况下,我们可以使用称为**三重损失**的新损失函数,该函数可帮助架构获得更好的结果。
# 三重损失功能
# 三重损失函数
三重态损失函数是对比损失函数的替代方法。 与对比损失函数相比,它具有收敛优势。
......
......@@ -403,7 +403,7 @@ class WriteHead(Memory):
* 全连接控制器
* 读写磁头
* 记忆体参数
* 在无法训练的内存上运行的实用程序功能
* 在无法训练的内存上运行的工具功能
```py
class NTM(nn.Module):
......
......@@ -134,7 +134,7 @@ pip install torchvision
# 工作原理
在本秘籍中,我们开始使用`torchvision``torchvision`中有实用程序来支持与视觉有关的任务。 有一个名为`transforms`的模块可以帮助完成许多图像预处理任务。 对于我们正在处理的特殊情况,一个由`28 x 28`灰度像素组成的图像,我们首先需要从图像中读取并使用`transforms.ToTensor()`变换将其转换为张量。 然后,我们分别将像素值的平均值和标准差设为 0.5 和 0.5,以便模型更易于训练; 为此,我们使用`transforms.Normalize((0.5,),(0.5,))`。 我们将所有转换与`transform.Compose()`结合在一起。
在本秘籍中,我们开始使用`torchvision``torchvision`中有工具来支持与视觉有关的任务。 有一个名为`transforms`的模块可以帮助完成许多图像预处理任务。 对于我们正在处理的特殊情况,一个由`28 x 28`灰度像素组成的图像,我们首先需要从图像中读取并使用`transforms.ToTensor()`变换将其转换为张量。 然后,我们分别将像素值的平均值和标准差设为 0.5 和 0.5,以便模型更易于训练; 为此,我们使用`transforms.Normalize((0.5,),(0.5,))`。 我们将所有转换与`transform.Compose()`结合在一起。
准备好转换后,我们定义了合适的批量大小。 较高的批量大小意味着该模型具有较少的训练步骤并且学习速度更快,而较高的批量大小会导致对内存的高要求。
......
......@@ -350,7 +350,7 @@ PyTorch 无法直接处理图像像素,需要将其内容作为张量。 为
另一个重要任务是填充图像以匹配特定尺寸。 为此,我们使用`Pad()`方法。 我们将填充大小作为整数表示,用于在所有面上进行均等大小的填充,或者将序列作为由两个元素组成的序列,用于填充大小分别对应于左/右和上/下。 此外,我们可以将左侧,顶部,右侧和底部的填充大小作为由四个元素组成的序列传递。 然后,我们将填充值作为整数提供,如果它是三个元素的元组,则分别用作 R,G 和 B 通道的填充值。 除此之外,`Pad()`方法还具有`padding_mode`参数,该参数具有以下可能性:
* `constant`:提供填充值的打击垫
* `constant`:提供填充值的填充
* `edge`:在图像边缘填充数值
* `reflect`:带有图像反射的填充,边缘像素除外
* `symmetric`:带有图像反射的焊盘,包括边缘像素
......
# 用于 NLP 的循环神经网络
在本章中,我们将处理**循环神经网络****RNNs**),这是一种专门处理顺序数据或时变数据的神经网络。 利用卷积神经网络,我们处理在空间上彼此相关的数据点,其中一组像素值保存有关图像的信息。 但是请考虑一下节奏,节奏是由一段时间内一系列变化的声音信号形成的。 数据点彼此之间具有时间关系。 在循环神经网络中,神经元之间的连接在时间序列上形成有向图,表现出时间动态行为。 传统的前馈网络不存储先前的输入; 但是,RNN 使用存储单元来记住先前的输入,因此根据到目前为止的输入顺序来处理当前输入。
在本章中,我们将处理**循环神经网络****RNNs**),这是一种专门处理序列数据或时变数据的神经网络。 利用卷积神经网络,我们处理在空间上彼此相关的数据点,其中一组像素值保存有关图像的信息。 但是请考虑一下节奏,节奏是由一段时间内一系列变化的声音信号形成的。 数据点彼此之间具有时间关系。 在循环神经网络中,神经元之间的连接在时间序列上形成有向图,表现出时间动态行为。 传统的前馈网络不存储先前的输入; 但是,RNN 使用存储单元来记住先前的输入,因此根据到目前为止的输入顺序来处理当前输入。
在本章中,我们将介绍以下秘籍:
......@@ -112,7 +112,7 @@ pip install torchtext
# 创建字段
在本秘籍中,我们将探索字段,这些字段与`torchvision`中可用的实用程序一样,使处理自然语言数据变得容易。 字段让我们定义数据类型,并通过指定要对数据执行的一组操作来帮助我们从文本数据中创建张量。 `Field`类使我们可以执行常见的文本处理任务,并掌握手边的数据词汇。
在本秘籍中,我们将探索字段,这些字段与`torchvision`中可用的工具一样,使处理自然语言数据变得容易。 字段让我们定义数据类型,并通过指定要对数据执行的一组操作来帮助我们从文本数据中创建张量。 `Field`类使我们可以执行常见的文本处理任务,并掌握手边的数据词汇。
在本秘籍中,我们将研究如何使用`Field`类定义各种文本处理任务。
......@@ -166,7 +166,7 @@ pip install torchtext
# 工作原理
在此秘籍中,我们根据手头的特定任务,使用`field`类对给定的输入文本执行了各种文本处理任务。 在审阅分类的示例中,在`review`字段中,我们将`sequential`参数设置为`True`,因为它是顺序数据。 对于标签字段,我们将其设置为`False`,因为它们不是顺序的。 我们可以将文本设置为小写,这样就不会根据标记的大小写为相同的单词分配单独的标记 ID。 在评论分类的情况下,这不会影响含义; 这可以通过将`lower`设置为`True`来实现。
在此秘籍中,我们根据手头的特定任务,使用`field`类对给定的输入文本执行了各种文本处理任务。 在审阅分类的示例中,在`review`字段中,我们将`sequential`参数设置为`True`,因为它是序列数据。 对于标签字段,我们将其设置为`False`,因为它们不是顺序的。 我们可以将文本设置为小写,这样就不会根据标记的大小写为相同的单词分配单独的标记 ID。 在评论分类的情况下,这不会影响含义; 这可以通过将`lower`设置为`True`来实现。
对于数字字段,我们将`use_vocab`设置为`False`,这是我们为审阅标签所做的,因为我们假设标签的负数值为`0`,正数的值为`1`。 我们从分词部分传递了`tokenizer`函数作为`tokenize`参数; 我们甚至可以通过设置`tokenize="spacy"`使用`spacy`的标记器。 对于某些任务,例如,使用`Sequence`对模型进行排序,我们可能需要特殊的标记来指示序列的开始和结束。 可以通过设置`init_token``eos_token`参数轻松完成。 这对于序列到序列的模型是正确的,并且如果在模型评估期间用于训练模型的词汇表中不存在令牌(词汇表外),则可以使用自定义令牌来替换这些令牌, 设置`unk_token`参数。
......
......@@ -159,11 +159,11 @@ return model
# 实现模型测试
在此秘籍中,我们将定义一个函数以在一个时期内根据验证数据测试模型。 此功能还将测试指标记录到 TensorBoard 上。 我们还将添加实用程序功能,通过绘制图像并以可读的方式标记这些图像来记录模型中的一些错误分类。
在此秘籍中,我们将定义一个函数以在一个时期内根据验证数据测试模型。 此功能还将测试指标记录到 TensorBoard 上。 我们还将添加工具功能,通过绘制图像并以可读的方式标记这些图像来记录模型中的一些错误分类。
# 操作步骤
在本秘籍中,我们将实现模型测试以及实用程序功能:
在本秘籍中,我们将实现模型测试以及工具功能:
1. 首先,我们将定义一个将张量转换为图像的函数:
......
......@@ -6,7 +6,7 @@ RL 是**人工智能**(**AI**)的领域,与我们在前面各章中介绍
在本章中,我们将介绍以下秘籍:
* OpenAI Gym简介– CartPole
* OpenAI Gym 简介– CartPole
* 引入 DQN
* 实现 DQN 类
* 训练 DQN
......@@ -28,7 +28,7 @@ RL 解决方案涉及将反复试验的结果存储在查找表中,当环境
深度学习是 RL 最近取得突破的背后。 它们展现了代表性的功能,效率,灵活性,并为眼前的问题提供了简化的解决方案。
# OpenAI Gym简介 – CartPole
# OpenAI Gym 简介 – CartPole
在本秘籍中,我们将实现两种不同的 RL 算法。 我们将需要一个环境来运行我们的算法,以便我们创建的模型将获得最大的回报。
......@@ -36,7 +36,7 @@ RL 解决方案涉及将反复试验的结果存储在查找表中,当环境
杆子是一个倒立的摆锤,其重心高于其枢轴点。 为了控制倒立摆的不稳定位置,我们必须将枢轴点移动到质心下方。 目的是施加适当的力,以使柱杆在枢轴点上保持平衡。
下图显示了 OpenAI Gym的 Cartpole:
下图显示了 OpenAI Gym 的 Cartpole:
![](img/20943d9b-be6d-4bb1-b4df-0dc04bf896ed.png)
......@@ -133,7 +133,7 @@ pip install gym
# 另见
您可以在[这个页面](http://gym.openai.com/docs/)上了解有关 OpenAI Gym的更多信息。
您可以在[这个页面](http://gym.openai.com/docs/)上了解有关 OpenAI Gym 的更多信息。
# DQN 介绍
......
......@@ -16,7 +16,7 @@
第 4 章,“计算机视觉”是迄今为止深度学习最成功的结果,它讨论了成功背后的关键思想,并贯穿了使用最广泛的视觉算法– **卷积神经网络(CNN)**。 我们将逐步实现 CNN 以了解其工作原理,然后使用 PyTorch 的`nn`包中预定义的 CNN。 本章可帮助您制作简单的 CNN 和基于高级 CNN 的视觉算法,称为语义分割。
第 5 章,“序列数据处理”着眼于循环神经网络,它是目前最成功的顺序数据处理算法。 本章向您介绍主要的 RNN 组件,例如**长短期记忆****LSTM**)网络和**门控循环单元****GRU**)。 然后,在探索循环神经网络之前,我们将经历 RNN 实现中的算法更改,例如双向 RNN,并增加层数。 为了理解递归网络,我们将使用斯坦福大学 NLP 小组的著名示例(堆栈增强的解析器-解释器神经网络(SPINN)),并将其在 PyTorch 中实现。
第 5 章,“序列数据处理”着眼于循环神经网络,它是目前最成功的序列数据处理算法。 本章向您介绍主要的 RNN 组件,例如**长短期记忆****LSTM**)网络和**门控循环单元****GRU**)。 然后,在探索循环神经网络之前,我们将经历 RNN 实现中的算法更改,例如双向 RNN,并增加层数。 为了理解递归网络,我们将使用斯坦福大学 NLP 小组的著名示例(堆栈增强的解析器-解释器神经网络(SPINN)),并将其在 PyTorch 中实现。
第 6 章,“生成网络”,简要讨论了生成网络的历史,然后解释了各种生成网络。 在这些不同的类别中,本章向我们介绍了自回归模型和 GAN。 我们将研究作为自动回归模型一部分的 PixelCNN 和 WaveNet 的实现细节,然后详细研究 GAN。
......
......@@ -248,11 +248,11 @@ RNN 是最常见的深度学习算法之一,它们席卷全球。 我们现在
图 1.13:循环网络中单词的向量表示
#### 循环神经网络
#### 递归神经网络
顾名思义,循环神经网络是树状网络,用于了解序列数据的层次结构。 递归网络已在**自然语言处理**应用中大量使用,尤其是 Salesforce 首席科学家 Richard Socher 及其团队。
顾名思义,递归神经网络是树状网络,用于了解序列数据的层次结构。 递归网络已在**自然语言处理**应用中大量使用,尤其是 Salesforce 首席科学家 Richard Socher 及其团队。
词向量,我们将在第 5 章,“序列数据处理”中很快看到,它们能够将词的含义有效地映射到向量空间中,但是涉及到含义 在整个句子中,没有像 word2vec 这样的单词适合的解决方案。 循环神经网络是此类应用最常用的算法之一。 递归网络可以创建一个解析树和组成向量,并映射其他层次关系,这反过来又帮助我们找到了结合单词和句子的规则。 **斯坦福自然语言推断**小组发现了一种著名的且使用良好的算法,称为 **SNLI**,这是递归网络使用的一个很好的例子。
词向量,我们将在第 5 章,“序列数据处理”中很快看到,它们能够将词的含义有效地映射到向量空间中,但是涉及到含义 在整个句子中,没有像 word2vec 这样的单词适合的解决方案。 递归神经网络是此类应用最常用的算法之一。 递归网络可以创建一个解析树和组成向量,并映射其他层次关系,这反过来又帮助我们找到了结合单词和句子的规则。 **斯坦福自然语言推断**小组发现了一种著名的且使用良好的算法,称为 **SNLI**,这是递归网络使用的一个很好的例子。
![Recursive neural networks](img/B09475_01_14.jpg)
......
......@@ -101,11 +101,11 @@ weight -= lr * loss
图 2.2:学习率低而学习率高
## 手模型
## 手模型
现在,我们将建立一个手,类似于 NumPy 的模型,而不使用任何 PyTorch 特定的方法。 然后,在下一个会话中,我们将把相同的模型转换为 PyTorch 的方法。 如果您来自 NumPy,那么您会感到宾至如归,但是如果您是使用其他框架的高级深度学习从业者,请随意跳过本节。
现在,我们将建立一个手,类似于 NumPy 的模型,而不使用任何 PyTorch 特定的方法。 然后,在下一个会话中,我们将把相同的模型转换为 PyTorch 的方法。 如果您来自 NumPy,那么您会感到宾至如归,但是如果您是使用其他框架的高级深度学习从业者,请随意跳过本节。
### 自动毕业
### Autograd
因此,既然我们知道张量应该为类型,就可以根据从`get_numpy_data()`获得的 NumPy 数组创建 PyTorch 张量。
......@@ -129,7 +129,7 @@ b2 = torch.zeros(1, output_size, requires_grad=True, device=device, dtype=dtype)
这是反向模式自动微分的关键特征之一。 这有助于 PyTorch 动态化,因为无论用户在向前传递中作为操作编写的内容都可以写入磁带,并且在反向传播开始时,Autograd 可以在磁带上向后移动并随梯度一起移动,直到到达最外层 父母
磁带或内存的写操作可忽略不计,PyTorch 通过将操作写到磁带上并在向后遍历后销毁磁带来利用每次正向遍历中的行为。 尽管我会在本书中尽量避免使用尽可能多的数学方法,但是有关自动毕业如何工作的数学示例绝对可以为您提供帮助。 在下面的两个图中,说明了反向传播算法和使用链规则的 Autograd 的方法。 下图中我们有一个小型网络,其中有一个乘法节点和一个加法节点。 乘法节点获取输入张量和权重张量,将其传递到加法节点以进行加法运算。
磁带或内存的写操作可忽略不计,PyTorch 通过将操作写到磁带上并在向后遍历后销毁磁带来利用每次正向遍历中的行为。 尽管我会在本书中尽量避免使用尽可能多的数学方法,但是有关 Autograd 如何工作的数学示例绝对可以为您提供帮助。 在下面的两个图中,说明了反向传播算法和使用链规则的 Autograd 的方法。 下图中我们有一个小型网络,其中有一个乘法节点和一个加法节点。 乘法节点获取输入张量和权重张量,将其传递到加法节点以进行加法运算。
```py
output = X * W + B
......@@ -139,7 +139,7 @@ output = X * W + B
![Autograd](img/B09475_02_03.jpg)
图 2.3:自动毕业的工作方式
图 2.3:Autograd 的工作方式
![Autograd](img/B09475_02_04.jpg)
......@@ -228,7 +228,7 @@ for epoch in range(epochs):
前面的代码段与在第 1 章,“深度学习演练和 PyTorch 简介”中看到的相同,其中解释了静态和动态计算图,但在这里我们来看一下 从另一个角度看代码:模型说明。 它从循环遍历每个时期的批量开始,并使用我们正在构建的模型处理每个批量。 与基于静态计算图的框架不同,我们尚未构建图。 我们刚刚定义了超参数,并根据我们的数据制作了张量。
##### 构建图
##### 构建图
我们正在构建该图,如下图所示:
......@@ -247,7 +247,7 @@ print(a2.grad, a2.grad_fn, a2)
**Softmax**:让 Sigmoid 曲面吐出分类问题的预测是很不寻常的,但是我们将其保留下来,因为这样会使我们的模型易于理解,因为它重复了第一层。 通常,分类问题由 softmax 层和交叉熵损失处理,这会增加一类相对于另一类的概率。 由于所有类别的概率加在一起,因此增加一个类别的概率会降低其他类别的概率,这是一个不错的功能。 在以后的章节中将对此进行更多介绍。
##### 查找错误
##### 查找误差
是时候找出了,我们的模型在 Fizz 嗡嗡声中的预测效果如何。 我们使用最基本的回归损失,称为**均方误差****MSE**)。 最初,我们发现批量中每个元素的预测与输出之间的差异(还记得我们为每个输入数据点创建的大小为 4 的向量吗?)。 然后我们对所有差异求平方,并将所有差异求和在一起,以获得一个单一值。 如果您不熟悉损失函数,则不必担心被 2.0 除。 这样做是为了使数学在进行反向传播时保持整洁。
......@@ -364,7 +364,7 @@ class FizBuzNet(nn.Module):
我们定义了`FizBuzNet`的结构,并将其包装在从`torch.nn.Module`继承的 Python 类中。 PyTorch 中的`nn`模块是用于访问深度学习世界中所有流行层的高级 API。 让我们逐步进行。
#### nn.Module
#### `nn.Module`
允许用户编写其他高级 API 的高级 API 是`nn.Module`。 您可以将网络的每个可分离部分定义为单独的 Python 类,并继承自`nn.Module`。 例如,假设您想建立一个深度学习模型来交易加密货币。 您已经从某个交易所收集了每种硬币的交易数据,并将这些数据解析为可以传递到网络的某种形式。 现在您处于两难境地:如何对每个硬币进行排名? 一种简单的方法是对硬币进行一次热编码,然后将其传递给神经元,但是您对此并不满意。 另一种相当简单的方法是制作另一个小模型来对硬币进行排名,您可以将该排名从该小模型传递到您的主模型作为输入。 啊哈! 这看起来很简单而且很聪明,但是您又该怎么做呢? 让我们看一下下图:
......@@ -480,7 +480,7 @@ net = nn.Sequential(
nn.Sigmoid())
```
### 功能模块
### `functional`模块
`nn.functional`模块附带我们需要将网络节点连接在一起的操作。 在我们的模型中,我们使用`functional`模块中的 Sigmoid 作为非线性激活。 `functional`模块具有更多功能,例如您正在执行的所有数学函数都指向`functional`模块。 在下面的示例中,乘法运算符从`functional`模块调用`mul`运算符:
......@@ -523,9 +523,9 @@ tensor([[1]], dtype=torch.uint8)
`FizBuzNet``forward`函数内部,我们有两个线性层和两个非线性激活层。 通常,`forward`函数的输出返回是代表概率分布的对数,其中正确的类获得较高的值,但是在我们的模型中,我们从 Sigmoid 返回输出。
### 损失功能
### 损失函数
现在我们有了`FizBuzNet`返回的预测,我们需要找出模型预测的水平,然后反向传播该错误。 我们调用损失函数来查找错误。 社区中普遍存在不同的损失函数。 PyTorch 带有`nn`模块中内置的所有流行损失函数。 损失函数接受对数和实际值,并在其上应用损失功能以查找损失得分。 此过程给出了错误率,该错误率代表了模型预测的好坏。 在新手模型中,我们使用了基本的 MSE 损失,已在`nn`模块中将其定义为`MSELoss()`
现在我们有了`FizBuzNet`返回的预测,我们需要找出模型预测的水平,然后反向传播该错误。 我们调用损失函数来查找错误。 社区中普遍存在不同的损失函数。 PyTorch 带有`nn`模块中内置的所有流行损失函数。 损失函数接受对数和实际值,并在其上应用损失函数以查找损失得分。 此过程给出了错误率,该错误率代表了模型预测的好坏。 在新手模型中,我们使用了基本的 MSE 损失,已在`nn`模块中将其定义为`MSELoss()`
```py
loss = nn.MSELoss()
......
......@@ -4,7 +4,7 @@
PyTorch 最初是由 Facebook 实习生作为研究框架开始的,现已发展到由超级优化的 Caffe2 核心支持后端的阶段。 因此,简而言之,PyTorch 可以用作研究或原型框架,同时可以用来编写带有服务模块的有效模型,并且还可以部署到单板计算机和移动设备上。
典型的深度学习工作流程始于围绕问题陈述的构想和研究,这是架构设计和模型决策发挥作用的地方。 然后使用原型对理论模型进行实验。 这包括尝试不同的模型或技术(例如跳连接),或决定不尝试什么。 同样,选择合适的数据集进行原型设计并将数据集的无缝集成添加到管道中对于此阶段至关重要。 一旦实现了模型并通过训练和验证集对其进行了验证,则可以针对生产服务优化该模型。 下图描述了一个五阶段的深度学习工作流程:
典型的深度学习工作流程始于围绕问题陈述的构想和研究,这是架构设计和模型决策发挥作用的地方。 然后使用原型对理论模型进行实验。 这包括尝试不同的模型或技术(例如跳连接),或决定不尝试什么。 同样,选择合适的数据集进行原型设计并将数据集的无缝集成添加到管道中对于此阶段至关重要。 一旦实现了模型并通过训练和验证集对其进行了验证,则可以针对生产服务优化该模型。 下图描述了一个五阶段的深度学习工作流程:
![Deep Learning Workflow](img/B09475_03_01.jpg)
......@@ -87,20 +87,20 @@ for batch in dataloader:
`num_worker`参数决定应该操作多少个并行线程来获取数据。 这有助于避免 CPU 瓶颈,以便 CPU 可以赶上 GPU 的并行操作。 数据加载器允许用户指定是否使用固定的 CUDA 内存,这会将数据张量复制到 CUDA 的固定的内存中,然后再返回给用户。 使用固定内存是设备之间快速数据传输的关键,因为数据是由数据加载程序本身加载到固定内存中的,而无论如何,这都是由 CPU 的多个内核完成的。
大多数情况下,尤其是在进行原型制作时,开发人员可能无法使用自定义数据集,在这种情况下,自定义数据集必须依赖现有的开放数据集。 处理开放数据集的好处是,大多数数据集免于许可负担,成千上万的人已经尝试过对其进行预处理,因此社区将提供帮助。 PyTorch 提出了针对所有三种类型的数据集的实用程序包,这些程序包具有经过预训练的模型,经过预处理的数据集以及与这些数据集一起使用的实用程序功能。
大多数情况下,尤其是在进行原型制作时,开发人员可能无法使用自定义数据集,在这种情况下,自定义数据集必须依赖现有的开放数据集。 处理开放数据集的好处是,大多数数据集免于许可负担,成千上万的人已经尝试过对其进行预处理,因此社区将提供帮助。 PyTorch 提出了针对所有三种类型的数据集的工具包,这些程序包具有经过预训练的模型,经过预处理的数据集以及与这些数据集一起使用的工具功能。
### 实用程序
### 工具
该社区针对视觉(`torchvision`),文本(`torchtext`)和音频(`torchaudio`)制作了三种不同的实用程序包。 它们针对不同的数据域都解决了相同的问题,并且使用户不必担心用户可能拥有的几乎所有用例中的数据处理和清理问题。 实际上,所有实用程序包都可以轻松地插入到可能理解或不理解 PyTorch 数据结构的任何类型的程序中。
该社区针对视觉(`torchvision`),文本(`torchtext`)和音频(`torchaudio`)制作了三种不同的工具包。 它们针对不同的数据域都解决了相同的问题,并且使用户不必担心用户可能拥有的几乎所有用例中的数据处理和清理问题。 实际上,所有工具包都可以轻松地插入到可能理解或不理解 PyTorch 数据结构的任何类型的程序中。
#### TorchVision
#### `torchvision`
```py
pip install torchvision
```
`torchvision`是 PyTorch 中最成熟,使用最多的实用程序包,它由数据集,预先训练的模型和预先构建的转换脚本组成。 `torchvision`具有功能强大的 API,使用户能够轻松进行数据的预处理,并且在原型阶段(甚至可能无法使用数据集)特别有用。
`torchvision`是 PyTorch 中最成熟,使用最多的工具包,它由数据集,预先训练的模型和预先构建的转换脚本组成。 `torchvision`具有功能强大的 API,使用户能够轻松进行数据的预处理,并且在原型阶段(甚至可能无法使用数据集)特别有用。
`torchvision`的功能分为三类:预加载的,可下载的数据集,用于几乎所有类型的计算机视觉问题; 流行的计算机视觉架构的预训练模型; 以及用于计算机视觉问题的常见转换函数。 另外一个好处是,`torchvision`软件包的功能 API 的简单性使用户可以编写自定义数据集或转换函数。 以下是`torchvision`程序包中可用的所有当前数据集的表格及其说明:
......@@ -178,7 +178,7 @@ Dataset MNIST
PyTorch 的 Python API 允许冻结用户决定使其不可训练的模型部分。 前面的代码中给出了一个示例。 循环访问`resnet18`的第 1 层参数的循环可访问每个参数的`requires_grad`属性,这是 Autograd 在反向传播以进行梯度更新时所寻找的。 将`requires_grad`设置为`False`会屏蔽`autograd`中的特定参数,并使权重保持冻结状态。
`torchvision``transforms`模块是另一个主要参与者,它具有用于数据预处理和数据扩充的实用程序模块。 `transforms`模块为常用的预处理功能(例如填充,裁切,灰度缩放,仿射变换,将图像转换为 PyTorch 张量等)提供了开箱即用的实现,以及一些实现数据扩充,例如翻转,随机裁剪和色彩抖动。 `Compose`实用程序将多个转换组合在一起,以形成一个管道对象。
`torchvision``transforms`模块是另一个主要参与者,它具有用于数据预处理和数据扩充的工具模块。 `transforms`模块为常用的预处理功能(例如填充,裁切,灰度缩放,仿射变换,将图像转换为 PyTorch 张量等)提供了开箱即用的实现,以及一些实现数据扩充,例如翻转,随机裁剪和色彩抖动。 `Compose`工具将多个转换组合在一起,以形成一个管道对象。
```py
transform = transforms.Compose(
......@@ -200,20 +200,20 @@ def __call__(self, img):
return img
```
转换带有很多实用程序,并且它们在不同的情况下都非常有用。 最好阅读不断完善的`torchvision`文档,以详细了解更多功能。
转换带有很多工具,并且它们在不同的情况下都非常有用。 最好阅读不断完善的`torchvision`文档,以详细了解更多功能。
#### 火炬文本
#### `torchtext`
```py
pip install torchtext
```
与其他两个实用程序包不同,`torchtext`保留自己的 API 结构,该结构与`torchvision``torchaudio`完全不同。 `torchtext`是一个非常强大的库,可以为**自然语言处理****NLP**)数据集执行所需的预处理任务。 它带有一组用于常见 NLP 任务的数据集,但是与`torchvision`不同,它没有可供下载的预训练网络。
与其他两个工具包不同,`torchtext`保留自己的 API 结构,该结构与`torchvision``torchaudio`完全不同。 `torchtext`是一个非常强大的库,可以为**自然语言处理****NLP**)数据集执行所需的预处理任务。 它带有一组用于常见 NLP 任务的数据集,但是与`torchvision`不同,它没有可供下载的预训练网络。
`torchtext`可以插入输入或输出端的任何 Python 包中。 通常,spaCy 或 NLTK 是帮助`torchtext`进行预处理和词汇加载的好选择。 `torchtext`提供 Python 数据结构作为输出,因此可以连接到任何类型的输出框架,而不仅仅是 PyTorch。 由于`torchtext`的 API 与`torchvision``torchaudio`不相似,并且不如其他人简单明了,因此下一个部分将通过一个示例演示`torchtext`在 NLP 中的主要作用。
`torchtext`本身是一个包装器实用程序,而不是支持语言操作,因此这就是我在以下示例中使用 spaCy 的原因。 例如,我们使用**文本检索会议****TREC**)数据集,它是一个问题分类器。
`torchtext`本身是一个包装器工具,而不是支持语言操作,因此这就是我在以下示例中使用 spaCy 的原因。 例如,我们使用**文本检索会议****TREC**)数据集,它是一个问题分类器。
| 文本 | 标签 |
| --- | --- |
......@@ -331,9 +331,9 @@ print(next(iter(test_iter)))
| UDPOS | 序列标记 |
| CoNLL2000Chunking | 序列标记 |
#### 火炬音频
#### `torchaudio`
音频实用程序可能是 PyTorch 所有实用程序包中最不成熟的程序包。 无法安装在`pip`之上的事实证明了这一主张。 但是,`torchaudio`涵盖了音频域中任何问题陈述的基本用例。 此外,PyTorch 还向内核添加了一些方便的功能,例如**逆快速傅里叶变换****IFFT**)和**稀疏快速傅里叶变换****SFFT**) ,显示 PyTorch 在音频领域的进步。
音频工具可能是 PyTorch 所有工具包中最不成熟的程序包。 无法安装在`pip`之上的事实证明了这一主张。 但是,`torchaudio`涵盖了音频域中任何问题陈述的基本用例。 此外,PyTorch 还向内核添加了一些方便的功能,例如**逆快速傅里叶变换****IFFT**)和**稀疏快速傅里叶变换****SFFT**) ,显示 PyTorch 在音频领域的进步。
`torchaudio`依赖于跨平台音频格式更改器**声音交换****SoX**)。 一旦安装了依赖项,就可以使用 Python 设置文件从源文件中安装。
......@@ -342,7 +342,7 @@ python setup.py install
```
`torchaudio`带有两个预先构建的数据集,一些转换以及一个用于音频文件的加载和保存实用程序。 让我们深入探讨其中的每一个。 加载和保存音频文件总是很麻烦,并且依赖于其他几个软件包。 `torchaudio`通过提供简单的加载和保存功能 API 使其变得更加容易。 `torchtext`可以加载任何常见的音频文件并将其转换为 PyTorch 张量。 它还可以对数据进行规范化和非规范化,以及以任何通用格式写回磁盘。 保存的 API 接受文件路径,并从文件路径推断输出格式,然后将其转换为该格式,然后再将其写回磁盘。
`torchaudio`带有两个预先构建的数据集,一些转换以及一个用于音频文件的加载和保存工具。 让我们深入探讨其中的每一个。 加载和保存音频文件总是很麻烦,并且依赖于其他几个软件包。 `torchaudio`通过提供简单的加载和保存功能 API 使其变得更加容易。 `torchtext`可以加载任何常见的音频文件并将其转换为 PyTorch 张量。 它还可以对数据进行规范化和非规范化,以及以任何通用格式写回磁盘。 保存的 API 接受文件路径,并从文件路径推断输出格式,然后将其转换为该格式,然后再将其写回磁盘。
```py
>>> data, sample_rate = torchaudio.load('foo.mp3')
......@@ -376,11 +376,11 @@ transform = transforms.Compose(
毕竟,实现模型是我们开发流程中最重要的一步。 在某种程度上,我们为此步骤构建了整个管道。 除了构建网络架构之外,我们还需要考虑许多细节来优化实现(在工作量,时间以及代码效率方面)。
在本次会议中,我们将讨论 PyTorch 软件包本身和`ignite`(PyTorch 的推荐训练者实用程序)中提供的性能分析和瓶颈工具。 第一部分介绍了瓶颈和性能分析实用程序,当模型开始表现不佳并且您需要知道哪里出了问题时,这是必不可少的。 本课程的第二部分介绍了训练器模块`ignite`
在本次会议中,我们将讨论 PyTorch 软件包本身和`ignite`(PyTorch 的推荐训练者工具)中提供的性能分析和瓶颈工具。 第一部分介绍了瓶颈和性能分析工具,当模型开始表现不佳并且您需要知道哪里出了问题时,这是必不可少的。 本课程的第二部分介绍了训练器模块`ignite`
训练器网络并不是真正必需的组件,但它是一个很好的帮助程序实用程序,可以节省大量时间来编写样板文件和修复错误。 有时,它可以将程序的行数减少一半,这也有助于提高可读性。
训练器网络并不是真正必需的组件,但它是一个很好的帮助程序工具,可以节省大量时间来编写样板文件和修复错误。 有时,它可以将程序的行数减少一半,这也有助于提高可读性。
#### 瓶颈和性能分析
#### 瓶颈和表现分析
PyTorch 的 Python 优先方法阻止核心团队在的第一年建立一个单独的探查器,但是当模块开始转向 C/C++ 内核时,就很明显需要在 Python 的 cProfiler 上安装一个独立的探查器,这就是 `autograd.profiler`故事的开始。
......@@ -414,7 +414,7 @@ print(prof.table('cpu_time'))
图 3.4:`autograd.profiler`输出转换为 chrometrace
但是,如果用户需要结合使用`autograd.profiler`和 cProfiler(这将使我们在多个节点操作之间实现简洁的关联),或者用户仅需要调用另一个实用程序而不是更改用于获取配置文件的源代码, 信息是瓶颈。 瓶颈是 Torch 实用程序,可以从命令行作为 Python 模块执行:
但是,如果用户需要结合使用`autograd.profiler`和 cProfiler(这将使我们在多个节点操作之间实现简洁的关联),或者用户仅需要调用另一个工具而不是更改用于获取配置文件的源代码, 信息是瓶颈。 瓶颈是 Torch 工具,可以从命令行作为 Python 模块执行:
```py
python -m torch.utils.bottleneck /path/to/source/script.py [args]
......@@ -439,7 +439,7 @@ python -m torch.utils.bottleneck /path/to/source/script.py [args]
尽管工作流实际上以将深度模型的部署到生产中而结束,但我们已经到达深度学习工作的最后一步,我们将在第 8 章和“PyTorch 投入生产”。 在完成所有预处理和模型构建之后,现在我们必须训练网络,测试准确率并验证可靠性。 在开源世界(甚至在本书中)中,我们看到的大多数现有代码实现都使用直接方法,在该方法中,我们明确编写了训练,测试和验证所需的每一行,以提高可读性,因为 可以避免样板的特定工具会增加学习曲线,尤其是对于新手。 很显然,对于那些每天都在使用神经网络的程序员来说,可以避免样板的工具将是一个救生员。 因此,PyTorch 社区构建的不是一个而是两个工具:Torchnet 和 Ignite。 本次会议仅与点燃有关,因为它被发现比 Torchnet 更为有用和抽象,但两者都是积极开发的工具,有可能在不久的将来合并。
### 点燃
### Ignite
Ignite 是一种神经网络训练工具,可将某些样板代码抽象出来,以使代码简洁明了。 Ignite 的核心是`Engine`模块。 该模块非常强大,因为:
......@@ -447,7 +447,7 @@ Ignite 是一种神经网络训练工具,可将某些样板代码抽象出来
* 它可以接受处理程序和指标,并对其执行操作。
* 它可以创建触发器并执行回调。
#### 引擎
#### `Engine`
`Engine`接受一个训练器函数,该函数实质上是用于训练神经网络算法的典型循环。 它包括循环遍历,循环遍历,将现有梯度值归零,使用批量调用模型,计算损失以及更新梯度。 以下示例显示了这一点,该示例取自第 2 章和“简单神经网络”:
......@@ -498,7 +498,7 @@ evaluator.run(val_loader)
那很有趣,但仍然缺少一些片段。 如果用户需要在每个时期之后运行`evaluator`,或者如果用户需要训练器将模型的精度打印到终端,或者将其绘制到 Visdom,Turing 或 Network 图上,该怎么办? 在前面的设置中,有没有办法让知道验证准确率是什么? 您可以通过覆盖`Engine`的默认记录器来完成大部分操作,该记录器本质上是保存在`trainer_logger`变量中的 Python 记录器,但实际的答案是事件。
#### 活动
#### 事件
Ignite 打开了一种通过事件或触发器与循环进行交互的特殊方式。 当事件发生并执行用户在功能中定义的操作时,每个设置功能都会触发。 这样,用户就可以灵活地设置任何类型的事件,并且通过避免将那些复杂的事件写入循环中并使循环变得更大且不可读,从而使用户的生活变得更加轻松。 `Engine`中当前可用的事件是:
......@@ -632,7 +632,7 @@ if engine.state.iteration % self.save_interval !=0:
同样,在开发的早期阶段拥有工作流本身将使您的冲刺稳定且可预测。 最后,工作流中各个步骤之间的划分有助于定义团队成员的角色,为每个步骤设置截止日期,尝试有效地将每个步骤容纳在 sprint 中以及并行执行这些步骤。
PyTorch 社区正在制作不同的工具和实用程序包以整合到工作流中。 `ignite``torchvision``torchtext``torchaudio`等是这样的示例。 随着行业的发展,我们可以看到很多此类工具的出现,可以将其安装到此工作流的不同部分中,以帮助我们轻松地对其进行迭代。 但最重要的部分是:从一个开始。
PyTorch 社区正在制作不同的工具和工具包以整合到工作流中。 `ignite``torchvision``torchtext``torchaudio`等是这样的示例。 随着行业的发展,我们可以看到很多此类工具的出现,可以将其安装到此工作流的不同部分中,以帮助我们轻松地对其进行迭代。 但最重要的部分是:从一个开始。
在下一章中,我们将探讨计算机视觉和 CNN。
......
......@@ -51,7 +51,7 @@ CNN 通过两种机制实现位置不变:跨步和合并。 步幅值决定了
PyTorch 为计算机视觉提供了几个便捷功能,其中包括卷积层和池化层。 PyTorch 在`torch.nn`包下提供`Conv1d``Conv2d``Conv3d`。 听起来,`Conv1d`处理一维卷积,`Conv2d`处理带有图像之类输入的二维卷积,`Conv3d`处理诸如视频之类的输入上的三维卷积。 显然,这很令人困惑,因为指定的尺寸从未考虑输入的深度。 例如,`Conv2d`处理四维输入,其中第一维将是批量大小,第二维将是图像的深度(在 RGB 通道中),最后两个维将是图像的高度和宽度。 图片。
除了用于计算机视觉的高层功能之外,`torchvision`还具有一些方便的实用程序功能来建立网络。 在本章中,我们将探讨其中的一些。
除了用于计算机视觉的高层功能之外,`torchvision`还具有一些方便的工具功能来建立网络。 在本章中,我们将探讨其中的一些。
本章使用两个神经网络应用说明 PyTorch:
......@@ -93,7 +93,7 @@ def normalize(image, mean, std):
`get_data()`返回经过测试的可迭代迭代器和火车装载器。 现在数据已经准备好了,我们需要像建立 *FizBuzz* 网络时那样,设置模型,损失函数和优化器。
##### 型号
##### 模型
`SimpleCNNModel`是从 PyTorch 的`nn.Module`继承的模型类。 这是使用其他自定义类和 PyTorch 类来设置架构的父类。
......@@ -316,7 +316,7 @@ LinkNet 利用自编码器的思想,该思想曾经是一种数据压缩技术
LinkNet 由一个初始块,一个最终块,一个带有四个卷积模块的编码器块以及一个带有四个解卷积模块的解码器组成。 初始块使用跨步卷积和最大池化层对输入图像进行两次下采样。 然后,编码器模块中的每个卷积模块都会以大步卷积对输入进行一次下采样。 然后将编码后的输出传递到解码器块,该解码器块会在每个反卷积块中使用步进反卷积对输入进行上采样; 反卷积将在以下部分中说明。
然后,解码器模块的输出通过最终模块,该模块将上采样两次,就像初始模块下采样两次一样。 还有更多:与其他语义分割模型相比,LinkNet 通过使用跳连接的思想可以减少架构中的参数数量。
然后,解码器模块的输出通过最终模块,该模块将上采样两次,就像初始模块下采样两次一样。 还有更多:与其他语义分割模型相比,LinkNet 通过使用跳连接的思想可以减少架构中的参数数量。
在每个卷积块之后,编码器块与解码器块进行通信,这使编码器块在正向传播之后会忘记某些信息。 由于编码器模块的输出不必保留该信息,因此参数的数量可能比其他现有架构的数量少得多。 实际上,该论文的作者使用 ResNet18 作为编码器,并且仍然能够以惊人的性能获得最新的结果。 下面是 LinkNet 的架构:
......@@ -342,11 +342,11 @@ LinkNet 由一个初始块,一个最终块,一个带有四个卷积模块的
图 4.9:反卷积工作
##### 跳连接
##### 跳连接
LinkNet 架构中编码器和解码器之间的平行水平线是跳过连接表示。 跳过连接有助于网络在编码过程中忘记某些信息,并在解码时再次查看。 由于网络解码和生成图像所需的信息量相对较低,因此这减少了网络所需的参数数量。 可以通过不同的操作来实现跳过连接。 使用跳过连接的另一个优点是,梯度梯度流可以容易地流过相同的连接。 LinkNet 将隐藏的编码器输出添加到相应的解码器输入,而另一种语义分割算法 Tiramisu [4]将两者连接在一起,将其发送到下一层。
LinkNet 架构中编码器和解码器之间的平行水平线是跳跃连接表示。 跳跃连接有助于网络在编码过程中忘记某些信息,并在解码时再次查看。 由于网络解码和生成图像所需的信息量相对较低,因此这减少了网络所需的参数数量。 可以通过不同的操作来实现跳跃连接。 使用跳跃连接的另一个优点是,梯度梯度流可以容易地流过相同的连接。 LinkNet 将隐藏的编码器输出添加到相应的解码器输入,而另一种语义分割算法 Tiramisu [4]将两者连接在一起,将其发送到下一层。
#### 型号
#### 模型
语义分割模型的编码器是我们在第一个会话中构建的 SimpleCNN 模型的扩展,但具有更多的卷积模块。 我们的主类使用五个次要组件/模块来构建前面描述的架构:
......@@ -356,9 +356,9 @@ LinkNet 架构中编码器和解码器之间的平行水平线是跳过连接表
* `EncoderBlock`
* `DecoderBlock`
正如在较早的会话中看到的那样,我们通过`forward()`调用主类的`__init__()`中的主类,并像链接一样链接每个主类,但是在这里,我们需要实现一个跳连接。 我们使用编码器层的输出,并通过将其与正常输入添加到解码器的方式将其传递到解码器层。
正如在较早的会话中看到的那样,我们通过`forward()`调用主类的`__init__()`中的主类,并像链接一样链接每个主类,但是在这里,我们需要实现一个跳连接。 我们使用编码器层的输出,并通过将其与正常输入添加到解码器的方式将其传递到解码器层。
##### 转换区
##### 卷积
```py
class ConvBlock(nn.Module):
......@@ -416,9 +416,9 @@ class ConvBlockWithoutSequential(nn.Module):
return self.bn_r
```
##### DeconvBlock
##### 反卷积块
解卷积块是 LinkNet 中解码器的构建块。 就像我们如何制作卷积块一样,解卷积块由三个基本模块组成:转置卷积,`BatchNorm`和 ReLU。 在那种情况下,卷积块和解卷积块之间的唯一区别是将`torch.nn.Conv2d`替换为`torch.nn.ConvTranspose2d`。 正如我们之前所见,转置卷积与卷积执行相同的操作,但给出相反的结果。
反卷积块是 LinkNet 中解码器的构建块。 就像我们如何制作卷积块一样,反卷积块由三个基本模块组成:转置卷积,`BatchNorm`和 ReLU。 在那种情况下,卷积块和反卷积块之间的唯一区别是将`torch.nn.Conv2d`替换为`torch.nn.ConvTranspose2d`。 正如我们之前所见,转置卷积与卷积执行相同的操作,但给出相反的结果。
```py
class DeconvBlock(nn.Module):
......@@ -438,7 +438,7 @@ class DeconvBlock(nn.Module):
`DeconvBlock`的前向调用不使用`torch.nn.Sequential`,并且与`ConvBlock`中对`Conv2d`所做的工作相比,还做了其他工作。 我们将期望的`output_size`传递给转置卷积的前向调用,以使尺寸稳定。 使用`torch.nn.Sequential`将整个反卷积块变成单个变量,可以防止我们将变量传递到转置卷积中。
##### 合并
##### 池化
PyTorch 有几个用于池化操作的选项,我们从其中选择使用`MaxPool`。 正如我们在`SimpleCNN`示例中看到的那样,这是一个显而易见的操作,我们可以通过仅从池中提取突出的特征来减少输入的维数。 `MaxPool2d`接受类似于`Conv2d`的参数来确定内核大小,填充和步幅。 但是除了这些参数之外,`MaxPool2d`接受两个额外的参数,即返回索引和`ciel`。 返回索引返回最大值的索引,可在某些网络架构中进行池化时使用。 `ciel`是布尔参数,它通过确定尺寸的上限或下限来确定输出形状。
......@@ -513,7 +513,7 @@ class DecoderBlock(nn.Module):
这样,我们的 LinkNet 模型设计就完成了。 我们将所有构造块放在一起以创建 LinkNet 模型,然后在开始训练之前使用`torchvision`预处理输入。 `__init__`将初始化整个网络架构。 它将创建初始块和最大池层,四个编码器块,四个解码器块和两个包装另一个`conv`块的`deconv`块。 四个解码器块对图像进行升采样,以补偿由四个编码器完成的降采样。 编码器块(其中四个)之前的大步卷积和最大池层也对图像进行了下采样两次。 为了弥补这一点,我们有两个`DeconvBlocks`,其中放置在`DeconvBlock`之间的`ConvBlock`完全不影响尺寸。
前向调用只是将所有初始化变量链接在一起,但是需要注意的部分是`DecoderBlock`。 我们必须将预期的输出传递给`DecoderBlock`,然后将其传递给`torch.nn.ConvTranspose2d`。 同样,我们将编码器输出的输出添加到下一步的解码器输入中。 这是我们之前看到的跳连接。 由于我们将编码器输出直接传递给解码器,因此我们传递了一些重建图像所需的信息。 这就是 LinkNet 即使在不影响速度的情况下也能如此出色运行的根本原因。
前向调用只是将所有初始化变量链接在一起,但是需要注意的部分是`DecoderBlock`。 我们必须将预期的输出传递给`DecoderBlock`,然后将其传递给`torch.nn.ConvTranspose2d`。 同样,我们将编码器输出的输出添加到下一步的解码器输入中。 这是我们之前看到的跳连接。 由于我们将编码器输出直接传递给解码器,因此我们传递了一些重建图像所需的信息。 这就是 LinkNet 即使在不影响速度的情况下也能如此出色运行的根本原因。
```py
class SegmentationModel(nn.Module):
......
# 第 5 章。顺序数据处理
# 第 5 章。序列数据处理
神经网络今天试图解决的主要挑战是处理,理解,压缩和生成顺序数据。 顺序数据可以被模糊地描述为任何依赖于上一个数据点和下一个数据点的东西。 尽管可以概括基本方法,但是处理不同类型的顺序数据需要不同的技术。 我们将探讨顺序数据处理单元的基本构建模块,以及常见问题及其广泛接受的解决方案。
神经网络今天试图解决的主要挑战是处理,理解,压缩和生成序列数据。 序列数据可以被模糊地描述为任何依赖于上一个数据点和下一个数据点的东西。 尽管可以概括基本方法,但是处理不同类型的序列数据需要不同的技术。 我们将探讨序列数据处理单元的基本构建模块,以及常见问题及其广泛接受的解决方案。
在本章中,我们将研究顺序数据。 人们用于顺序数据处理的规范数据是自然语言,尽管时间序列数据,音乐,声音和其他数据也被视为顺序数据。 **自然语言处理****NLP**)和理解已被广泛探索,并且它是当前活跃的研究领域。 人类的语言异常复杂,我们整个词汇的可能组合超过了宇宙中原子的数量。 但是,深层网络通过使用诸如嵌入和注意之类的某些技术可以很好地处理此问题。
在本章中,我们将研究序列数据。 人们用于序列数据处理的规范数据是自然语言,尽管时间序列数据,音乐,声音和其他数据也被视为序列数据。 **自然语言处理****NLP**)和理解已被广泛探索,并且它是当前活跃的研究领域。 人类的语言异常复杂,我们整个词汇的可能组合超过了宇宙中原子的数量。 但是,深层网络通过使用诸如嵌入和注意之类的某些技术可以很好地处理此问题。
## 循环神经网络简介
**循环神经网络****RNN**)是顺序数据处理的实际实现。 顾名思义,RNN 重新遍历上一次运行中保存的信息的数据,并试图像人类一样找到序列的含义。
**循环神经网络****RNN**)是序列数据处理的实际实现。 顾名思义,RNN 重新遍历上一次运行中保存的信息的数据,并试图像人类一样找到序列的含义。
尽管原始 RNN(在输入中为每个单元展开一个简单的 RNN 单元)是一个革命性的想法,但未能提供可用于生产的结果。 主要障碍是长期依赖问题。 当输入序列的长度增加时,网络到达最后一个单元时将无法从初始单位(单词,如果是自然语言)中记住信息。 我们将在接下来的部分中看到 RNN 单元包含的内容以及如何将其展开。
......@@ -16,9 +16,9 @@
嵌入是通过比较单词在单词簇中的分布来找到单词的概念含义的另一种革命性思想。 嵌入保持单词之间的关系,并将这种关系(它从单词簇中的单词分布中找到)转换为一组浮点数。 嵌入大大减少了输入大小,并极大地提高了性能和准确率。 我们将使用 word2vec 进行实验。
数据处理是序列数据(尤其是自然语言)的主要挑战之一。 PyTorch 提供了一些实用程序包来处理该问题。 我们将使用预处理后的数据来简化实现,但是我们将遍历实用程序包以了解它们的工作原理。 与这些实用程序包一起,我们将使用`torchtext`,它消除了处理输入数据时将面临的许多困难。
数据处理是序列数据(尤其是自然语言)的主要挑战之一。 PyTorch 提供了一些工具包来处理该问题。 我们将使用预处理后的数据来简化实现,但是我们将遍历工具包以了解它们的工作原理。 与这些工具包一起,我们将使用`torchtext`,它消除了处理输入数据时将面临的许多困难。
尽管本章全都是关于顺序数据的,但我们将专注于顺序数据的一个子集,这是自然语言。 特定于自然语言的一些研究人员认为,我们使用 LSTM 或 GRU 处理输入的方式不是应该如何处理自然语言。 自然语言在单词之间保持树状的层次关系,我们应该加以利用。 **栈式增强型解析器-解释器神经网络****SPINN**)[2]是来自 Stanford NLP 组的一种此类实现。 这种处理树状结构序列数据的特殊类型的网络是*递归神经网络*(与循环神经网络不同)。 在本章的最后一部分中,我们将详细介绍 SPINN。
尽管本章全都是关于序列数据的,但我们将专注于序列数据的一个子集,这是自然语言。 特定于自然语言的一些研究人员认为,我们使用 LSTM 或 GRU 处理输入的方式不是应该如何处理自然语言。 自然语言在单词之间保持树状的层次关系,我们应该加以利用。 **栈式增强型解析器-解释器神经网络****SPINN**)[2]是来自 Stanford NLP 组的一种此类实现。 这种处理树状结构序列数据的特殊类型的网络是*递归神经网络*(与循环神经网络不同)。 在本章的最后一部分中,我们将详细介绍 SPINN。
## 问题
......@@ -128,7 +128,7 @@ inputs.vocab.load_vectors('glove.6B.300d')
我们将 SNLI 数据集分为`training``dev``test`集,并将它们作为参数传递给`build_vocab`函数。 `build_vocab`函数遍历给定的数据集,并找到单词,频率和其他属性的数字,并创建`vocab`对象。 该`vocab`对象公开了`load_vectors` API,以接受预先训练的模型来进行迁移学习。
#### RNNCell
#### `RNNCell`
接下来,我们将开始构建网络的最小基础构建块,即 RNN 单元。 它的工作方式是一个 RNN 单元能够一一处理句子中的所有单词。 最初,我们将句子中的第一个单词传递到单元格,该单元格生成输出和中间状态。 此状态是序列的运行含义,由于在完成对整个序列的处理之前不会输出此状态,因此将其称为隐藏状态。
......@@ -183,7 +183,7 @@ class RNNCell(nn.Module):
现在,我们已准备好网络中最小的组件。 下一个任务是创建循环遍历序列的更高级别的组件,并使用`RNNCell`处理序列中的每个单词以生成隐藏状态。 我们称这个`Encoder`节点,它用词汇量大小和隐藏大小初始化`RNNCell`。 请记住,`RNNCell`需要用于嵌入层的词汇量和用于生成隐藏状态的隐藏大小。 在`forward`函数中,我们获得输入作为自变量,这将是一个小批量的序列。 在这种特殊情况下,我们遍历`torchtext``BucketIterator`,它识别相同长度的序列并将它们分组在一起。
#### 实用程序
#### 工具
如果我们不使用`BucketIterator`怎么办,或者如果我们根本没有相同长度的序列怎么办? 我们有两种选择:要么逐个执行序列,要么将除最长句子之外的所有句子填充为零,以使所有句子的长度与最长序列相同。
......@@ -191,9 +191,9 @@ class RNNCell(nn.Module):
尽管如果在 PyTorch 中一个接一个地传递序列长度,我们不会遇到不同序列长度的问题,但是如果我们的框架是基于静态计算图的框架,则会遇到麻烦。 在静态计算图中,甚至序列长度也必须是静态的,这就是基于静态图的框架与基于 NLP 的任务极不兼容的原因。 但是,像 TensorFlow 这样的高度复杂的框架通过为用户提供另一个名为`dynamic_rnn`的 API 来处理此问题。
第一种方法似乎很好用,因为我们每次分别为每个句子处理一个单词。 但是,小批量的输入要比一次处理一个数据输入更有效,以使我们的损失函数收敛到全局最小值。 做到这一点的明显有效的方法是填充。 用零填充输入(或输入数据集中不存在的任何预定义值)有助于我们解决此特定问题。 但是,当我们尝试手动执行操作时,它变得很繁琐,并且变得多余,因为每次处理顺序数据时都必须这样做。 PyTorch 在`torch.nn`下有一个单独的实用程序包,其中包含我们 RNN 所需的实用程序
第一种方法似乎很好用,因为我们每次分别为每个句子处理一个单词。 但是,小批量的输入要比一次处理一个数据输入更有效,以使我们的损失函数收敛到全局最小值。 做到这一点的明显有效的方法是填充。 用零填充输入(或输入数据集中不存在的任何预定义值)有助于我们解决此特定问题。 但是,当我们尝试手动执行操作时,它变得很繁琐,并且变得多余,因为每次处理序列数据时都必须这样做。 PyTorch 在`torch.nn`下有一个单独的工具包,其中包含我们 RNN 所需的工具
##### 打击垫顺序
##### 填充序列
函数`pad_sequence`听起来很像:在标识批量中最长的序列后,将序列用零填充,然后将其他所有句子填充到该长度:
......@@ -214,7 +214,7 @@ class RNNCell(nn.Module):
在给定的示例中,我们具有三个具有三个不同长度的序列,其中最长的序列的长度为三个。 PyTorch 填充其他两个序列,以使它们现在的长度均为三。 `pad_sequence`函数接受一个位置参数,该位置参数是序列的排序序列(即最长序列(`a`)在前和最短序列(`c`)在后)和一个关键字参数,该参数决定用户是否 希望它是否为`batch_first`
##### 装箱顺序
##### 打包序列
您是否看到用零填充输入并使用 RNN 处理输入的问题,特别是在我们如此关心最后一个隐藏状态的情况下? 批量中包含一个非常大的句子的简短句子最终将填充很多零,并且在生成隐藏状态时,我们也必须遍历这些零。
......@@ -224,7 +224,7 @@ class RNNCell(nn.Module):
图 5.4:具有零的句子也具有针对零计算的隐藏状态
将零添加到输入将污染结果,这是非常不希望的。 打包序列是为了避免这种影响。 PyTorch 完全具有实用程序功能`pack_sequence`
将零添加到输入将污染结果,这是非常不希望的。 打包序列是为了避免这种影响。 PyTorch 完全具有工具功能`pack_sequence`
```py
>>> import torch.nn.utils.rnn as rnn_utils
......@@ -264,7 +264,7 @@ class Encoder(nn.Module):
#### 分类器
我们网络的最后一个组成部分是分类器。 因此,我们手头有两个句子,经过编码器,我们得到了两个句子的最终隐藏状态。 现在是时候定义损失功能了。 一种方法是从两个句子中找出高维隐藏状态之间的距离。 可以按以下方式处理损失:
我们网络的最后一个组成部分是分类器。 因此,我们手头有两个句子,经过编码器,我们得到了两个句子的最终隐藏状态。 现在是时候定义损失函数了。 一种方法是从两个句子中找出高维隐藏状态之间的距离。 可以按以下方式处理损失:
1. 如果需要的话,将损失最大化到一个很大的正值。
2. 如果存在矛盾,请将损失最小化为较大的负值。
......@@ -358,7 +358,7 @@ opt = optim.Adam(model.parameters(), lr=lr)
### 高级 RNN
对于基于 LSTM 和 GRU 的网络,高级可能是一个模糊的术语,因为默认情况下,这些是在所有顺序数据处理网络中使用的网络架构。 与 1990 年代提出的 LSTM 网络相比,GRU 网络是一个相对较新的设计。 两种网络都是门控循环网络的不同形式,其中 LSTM 网络建立的架构比 GRU 网络复杂。 这些架构被概括为门控循环网络,因为它们具有用于处理通过网络的输入/梯度流的门。 门从根本上是激活,例如 Sigmoid,以决定要流经的数据量。 在这里,我们将详细研究 LSTM 和 GRU 的架构,并了解 PyTorch 如何提供对 LSTM 和 GRU 的 API 的访问。
对于基于 LSTM 和 GRU 的网络,高级可能是一个模糊的术语,因为默认情况下,这些是在所有序列数据处理网络中使用的网络架构。 与 1990 年代提出的 LSTM 网络相比,GRU 网络是一个相对较新的设计。 两种网络都是门控循环网络的不同形式,其中 LSTM 网络建立的架构比 GRU 网络复杂。 这些架构被概括为门控循环网络,因为它们具有用于处理通过网络的输入/梯度流的门。 门从根本上是激活,例如 Sigmoid,以决定要流经的数据量。 在这里,我们将详细研究 LSTM 和 GRU 的架构,并了解 PyTorch 如何提供对 LSTM 和 GRU 的 API 的访问。
##### LSTM
......@@ -405,7 +405,7 @@ class Encoder(nn.Module):
ht, ct = self.rnn(word, (ht, ct))
```
##### LSTMCell 和 GRUCell
##### `LSTMCell`和`GRUCell`
`LSTMCell``GRUCell`的函数式 API 绝对相似,这也正是定制`RNNCell`的方式。 它们接受输入大小和初始化程序的隐藏大小。 `forward`调用接受具有输入大小的微型输入批量,并为该实例创建单元状态和隐藏状态,然后将其传递给下一个执行输入。 在静态图框架中实现这种的实现非常困难,因为该图在整个执行期间都是预先编译的并且是静态的。 循环语句也应作为图节点作为图的一部分。 这需要用户学习那些额外的操作节点或其他在内部处理循环的函数式 API。
......@@ -495,9 +495,9 @@ SPINN 将输入的句子编码为固定长度的向量,就像基于 RNN 的编
静态计算图之上构建的框架不能实现 SPINN 这样的网络架构,而不会造成混乱。 这可能是所有流行框架围绕其核心实现构建动态计算图包装的原因,例如 TensorFlow 的热切需求,MXNet,CNTK 的 Gluon API 等。 我们将看到 PyTorch 的 API 对实现任何类型的条件或循环到计算图中的 API 有多么直观。 SPINN 是展示这些的完美示例。
#### 减少
#### 简化
约简网络将最左边的单词,最右边的单词和句子上下文作为输入,并在`forward`调用中生成单个约简的输出。 句子上下文由另一个称为`Tracker`的深度网络给出。 `Reduce`不在乎网络中正在发生的事情; 它总是接受三个输入,并由此减少输出。 树 LSTM 是标准 LSTM 的变体,用于与`bundle``unbundle`等其他辅助功能一起批量`Reduce`网络中发生的繁重操作。
简化网络将最左边的单词,最右边的单词和句子上下文作为输入,并在`forward`调用中生成单个约简的输出。 句子上下文由另一个称为`Tracker`的深度网络给出。 `Reduce`不在乎网络中正在发生的事情; 它总是接受三个输入,并由此减少输出。 树 LSTM 是标准 LSTM 的变体,用于与`bundle``unbundle`等其他辅助功能一起批量`Reduce`网络中发生的繁重操作。
```py
class Reduce(nn.Module):
......@@ -551,7 +551,7 @@ class Tracker(nn.Module):
return unbundle(self.state), None
```
#### 旋转
#### `SPINN`
`SPINN`模块是所有小型组件的包装器类。 `SPINN`的初始化程序与一样简单,包括组件模块`Reduce``Tracker`的初始化。 内部节点之间的所有繁重工作和协调都通过 SPINN 的`forward`调用进行管理。
......@@ -609,11 +609,11 @@ def forward(self, buffers, transitions):
## 总结
顺序数据是深度学习中最活跃的研究领域之一,尤其是因为自然语言数据是顺序的。 但是,顺序数据处理不仅限于此。 时间序列数据本质上是我们周围发生的一切,包括声音,其他波形等等,实际上都是顺序的。
序列数据是深度学习中最活跃的研究领域之一,尤其是因为自然语言数据是顺序的。 但是,序列数据处理不仅限于此。 时间序列数据本质上是我们周围发生的一切,包括声音,其他波形等等,实际上都是顺序的。
处理序列数据中最困难的问题是长期依赖性,但是序列数据要复杂得多。 RNN 是序列数据处理领域的突破。 研究人员已经探索了成千上万种不同的 RNN 变体,并且它仍然是一个活跃的领域。
在本章中,我们介绍了顺序数据处理的基本构建块。 尽管我们只使用英语,但是我们在这里学到的技术通常适用于任何类型的数据。 对于初学者来说,了解这些构建模块至关重要,因为随后的所有操作都基于它们。
在本章中,我们介绍了序列数据处理的基本构建块。 尽管我们只使用英语,但是我们在这里学到的技术通常适用于任何类型的数据。 对于初学者来说,了解这些构建模块至关重要,因为随后的所有操作都基于它们。
即使我没有详细解释高级主题,本章中给出的解释也应该足以进入更高级的解释和教程。 存在不同的 RNN 组合,甚至存在 RNN 与 CNN 的组合以用于序列数据处理。 了解本书给出的概念将使您开始探索人们尝试过的不同方法。
......
......@@ -61,7 +61,7 @@ PixelCNN 由 DeepMind 引入,并且是 DeepMind 引入的三种自回归模型
PixelCNN 一次生成一个像素,并使用该像素生成下一个像素,然后使用前两个像素生成下一个像素。 在 PixelCNN 中,有一个概率密度模型,该模型可以学习所有图像的密度分布并从该分布生成图像。 但是在这里,我们试图通过采用所有先前预测的联合概率来限制在所有先前生成的像素上生成的每个像素。
与 PixelRNN 不同,PixelCNN 使用卷积层作为接收场,从而缩短了输入的读取时间。 考虑一下图像被某些东西遮挡了; 假设我们只有一半的图像。 因此,我们有一半的图像,并且我们的算法需要生成后半部分。 在 PixelRNN 中,网络需要像图像中的单词序列一样逐个获取每个像素,并生成一半的图像,而 PixelCNN 则通过卷积层一次获取图像。 但是,无论如何,PixelCNN 的生成都必须是顺序的。 您可能想知道只有一半的图像会进行卷积。 答案是屏蔽卷积,我们将在后面解释。
与 PixelRNN 不同,PixelCNN 使用卷积层作为接收场,从而缩短了输入的读取时间。 考虑一下图像被某些东西遮挡了; 假设我们只有一半的图像。 因此,我们有一半的图像,并且我们的算法需要生成后半部分。 在 PixelRNN 中,网络需要像图像中的单词序列一样逐个获取每个像素,并生成一半的图像,而 PixelCNN 则通过卷积层一次获取图像。 但是,无论如何,PixelCNN 的生成都必须是顺序的。 您可能想知道只有一半的图像会进行卷积。 答案是遮罩卷积,我们将在后面解释。
“图 6.5”显示了如何对像素集应用卷积运算以预测中心像素。 与其他模型相比,自回归模型的主要优点是联合概率学习技术易于处理,可以使用梯度下降进行学习。 没有近似值,也没有解决方法。 我们只是尝试在给定所有先前像素值的情况下预测每个像素值,并且训练完全由反向传播支持。 但是,由于生成始终是顺序的,因此我们很难使用自回归模型来实现可伸缩性。 PixelCNN 是一个结构良好的模型,在生成新像素的同时,将各个概率的乘积作为所有先前像素的联合概率。 在 RNN 模型中,这是默认行为,但是 CNN 模型通过使用巧妙设计的遮罩来实现此目的,如前所述。
......@@ -102,9 +102,9 @@ net = nn.Sequential(
前面的代码段是完整的 PixelCNN 模型,该模型包装在顺序单元中。 它由一堆`MaskedConv2d`实例组成,这些实例继承自`torch.nn.Conv2d`,并使用了`torch.nn``Conv2d`的所有`*args``**kwargs`。 每个卷积单元之后是批量规范层和 ReLU 层,这是与卷积层成功组合的。 作者决定不在普通层上使用线性层,而是决定使用普通的二维卷积,事实证明,该方法比线性层更好。
##### 屏蔽卷积
##### 遮罩卷积
PixelCNN 中使用了屏蔽卷积,以防止在训练网络时信息从将来的像素和当前的像素流向生成任务。 这很重要,因为在生成像素时,我们无法访问将来的像素或当前像素。 但是,有一个例外,之前已描述过。 当前绿色通道值的生成可以使用红色通道的预测,而当前蓝色通道的生成可以使用绿色和红色通道的预测。
PixelCNN 中使用了遮罩卷积,以防止在训练网络时信息从将来的像素和当前的像素流向生成任务。 这很重要,因为在生成像素时,我们无法访问将来的像素或当前像素。 但是,有一个例外,之前已描述过。 当前绿色通道值的生成可以使用红色通道的预测,而当前蓝色通道的生成可以使用绿色和红色通道的预测。
通过将所有不需要的像素清零来完成屏蔽。 将创建一个与张量相等的掩码张量,其值为 1 和 0,对于所有不必要的像素,其值为 0。 然后,在进行卷积运算之前,此掩码张量与权重张量相乘。
......@@ -262,7 +262,7 @@ causalconv = torch.nn.Conv1d(
bias=False)
```
WaveNet 的完整架构建立在膨胀卷积网络和卷积后门控激活的基础之上。 WaveNet 中的数据流从因果卷积运算开始,这是一种正常的一维卷积,然后传递到膨胀的卷积节点。 WaveNet 图片中的每个白色圆圈(“图 6.9”)是一个扩展的卷积节点。 然后,将正常卷积的数据点传递到膨胀的卷积节点,然后将其独立地通过 Sigmoid 门和 tanh 激活。 然后,两个运算的输出通过逐点乘法运算符和`1x1`卷积进行。 WaveNet 使用剩余连接和跳连接来平滑数据流。 与主流程并行运行的剩余线程通过加法运算与`1x1`卷积的输出合并。
WaveNet 的完整架构建立在膨胀卷积网络和卷积后门控激活的基础之上。 WaveNet 中的数据流从因果卷积运算开始,这是一种正常的一维卷积,然后传递到膨胀的卷积节点。 WaveNet 图片中的每个白色圆圈(“图 6.9”)是一个扩展的卷积节点。 然后,将正常卷积的数据点传递到膨胀的卷积节点,然后将其独立地通过 Sigmoid 门和 tanh 激活。 然后,两个运算的输出通过逐点乘法运算符和`1x1`卷积进行。 WaveNet 使用剩余连接和跳连接来平滑数据流。 与主流程并行运行的剩余线程通过加法运算与`1x1`卷积的输出合并。
![WaveNet](img/B09475_06_13.jpg)
......@@ -270,7 +270,7 @@ WaveNet 的完整架构建立在膨胀卷积网络和卷积后门控激活的基
来源: 《WaveNet:原始音频的生成模型》,Aaron van den Oord 等
“图 6.12”中提供的 WaveNet 的结构图显示了所有这些小组件以及它们如何连接在一起。 跳连接之后的部分在程序中称为密集层,尽管它不是上一章介绍的密集层。 通常,密集层表示全连接层,以将非线性引入网络并获得所有数据的概览。 但是 WaveNet 的作者发现,正常的致密层可以由一串 ReLU 代替,并且`1x1`卷积可以通过最后的 softmax 层实现更高的精度,该层可以展开为 256 个单位(巨大扇出的 8 位`µ`律量化) 音频)。
“图 6.12”中提供的 WaveNet 的结构图显示了所有这些小组件以及它们如何连接在一起。 跳连接之后的部分在程序中称为密集层,尽管它不是上一章介绍的密集层。 通常,密集层表示全连接层,以将非线性引入网络并获得所有数据的概览。 但是 WaveNet 的作者发现,正常的致密层可以由一串 ReLU 代替,并且`1x1`卷积可以通过最后的 softmax 层实现更高的精度,该层可以展开为 256 个单位(巨大扇出的 8 位`µ`律量化) 音频)。
```py
class WaveNetModule(torch.nn.Module):
......@@ -296,7 +296,7 @@ class WaveNetModule(torch.nn.Module):
`ResidualStack`是需要更多说明的模块,它是 WaveNet 架构的核心。 `ResidualStack``ResidualBlock`的层的堆栈。 WaveNet 图片中的每个小圆圈都是一个残差块。 在正常卷积之后,数据到达`ResidualBlock`,如前所述。 `ResidualBlock`从膨胀的卷积开始,并且期望得到膨胀。 因此,`ResidualBlock`决定了架构中每个小圆节点的膨胀因子。 如前所述,膨胀卷积的输出然后通过类似于我们在 PixelCNN 中看到的门的门。
在那之后,它必须经历两个单独的卷积以进行跳连接和残差连接。 尽管作者并未将其解释为两个单独的卷积,但使用两个单独的卷积更容易理解。
在那之后,它必须经历两个单独的卷积以进行跳连接和残差连接。 尽管作者并未将其解释为两个单独的卷积,但使用两个单独的卷积更容易理解。
```py
class ResidualBlock(torch.nn.Module):
......@@ -358,7 +358,7 @@ return torch.stack(skip_connections)
GAN 从随机分布中获取样本,然后由网络将其转换为输出。 GAN 在学习输入分布的模式时不受监督,并且与其他生成网络不同,GAN 不会尝试明确地学习密度分布。 相反,他们使用博弈论方法来找到两个参与者之间的纳什均衡。 GAN 实现将始终拥有一个生成网络和一个对抗网络,这被视为两个试图击败的参与者。 GAN 的核心思想在于从统一或高斯等数据分布中采样,然后让网络将采样转换为真正的数据分布样。 我们将实现一个简单的 GAN,以了解 GAN 的工作原理,然后转向名为 CycleGAN 的高级 GAN 实现。
### Simple GAN
### 简单的 GAN
了解 GAN 的直观方法是从博弈论的角度了解它。 简而言之,GAN 由两个参与者组成,一个生成器和一个判别器,每一个都试图击败对方。 发生器从分布中获取一些随机噪声,并尝试从中生成一些输出分布。 生成器总是尝试创建与真实分布没有区别的分布; 也就是说,伪造的输出应该看起来像是真实的图像。
......
......@@ -112,7 +112,7 @@ MDP 定义有五件事:
既然我们已经学习了如何使用 MDP 来指定问题,那么代理需要制定解决方案。 此策略也可以称为策略。
### 策略和价值功能
### 策略和值函数
策略定义学习代理在给定时间的行为方式。 保单用希腊字母`Pi`表示。 该策略不能用公式定义; 它更多是基于直觉的概念。
......@@ -136,7 +136,7 @@ MDP 定义有五件事:
但是起初,我们可能不知道最佳作用值函数。 因此,由此产生的策略也将不是最佳策略。 我们将需要遍历动作值函数,并找到提供最佳回报的函数。 一旦找到它,我们将获得最优的`Q`。 最佳`Q`也称为`Q*`。 因此,我们将能够找到最优的`Pi`,也称为`Pi*`
`Q`功能是代理必须学习的功能。 我们将使用神经网络来学习此功能,因为神经网络也是通用函数逼近器。 一旦有了行动价值功能,座席就可以了解问题的最佳策略,我们就可以完成目标。
`Q`功能是代理必须学习的功能。 我们将使用神经网络来学习此功能,因为神经网络也是通用函数逼近器。 一旦有了行动值函数,座席就可以了解问题的最佳策略,我们就可以完成目标。
### 贝尔曼方程
......@@ -148,7 +148,7 @@ MDP 定义有五件事:
![Bellman equation](img/B09475_07_005.jpg)
简而言之,Bellman 等式指出,每个点的收益等于下一时间步长的估计报酬加上随后状态的折现报酬。 可以肯定地说,某些策略的任何值函数都遵循 Bellman 方程。
简而言之,Bellman 等式指出,每个点的收益等于下一时间步长的估计报酬加上随后状态的折现报酬。 可以肯定地说,某些策略的任何值函数都遵循 Bellman 方程。
#### 寻找最佳 Q 函数
......@@ -222,7 +222,7 @@ memory = ReplayMemory(10000)
在这里,我们为交易定义了一个存储库。 有一个称为`push`的功能可将事务推送到内存中。 还有另一个功能可以从内存中随机采样。
### 体育馆
### Gym
我们将使用 OpenAI 的 Gym 从环境`env`中获取参数。 环境变量很多,例如代理的速度和位置。 我们将训练一个平衡点来平衡自己。
......
# 第 8 章。PyTorch 生产
# 第 8 章。生产中的 PyTorch
2017 年,当 PyTorch 发布其可用版本时,它的承诺是成为研究人员的 Python 优先框架。 PyTorch 社区对此严格了一年,但随后看到了大量的生产要求,并决定将生产能力与 PyTorch 的第一个稳定版本 1.0 合并,但又不影响其创建的可用性和灵活性。
......@@ -14,11 +14,11 @@ ONNX 很棒,并且每个人都喜欢它,但是 ONNX 的主要缺点之一是
在本章中,我们将从使用 Flask(流行的 Python Web 框架)提供普通的 Python PyTorch 模型开始。 这样的设置通常就足够了,特别是如果您要设置示例 Web 应用或满足您个人需求或类似用例的东西。 然后,我们将探索 ONNX 并将 PyTorch 模型转换为 MXNet,然后可以使用 MXNet 模型服务器提供服务。 从那里,我们将转到 TorchScript,这是 PyTorch 街区的新孩子。 使用 TorchScript,我们将制作 C++ 可执行文件,然后可以在 LibTorch 的帮助下从 C++ 执行该可执行文件。 然后,可以从稳定,高性能的 C++ 服务器甚至使用 cgo 的 Go 服务器提供高效的 C++ 可执行文件。 对于所有份量,我们将使用在第 2 章,“简单神经网络”中构建的 fizzbuzz 网络。
## 与烧瓶一起食
## 与 Flask 一起使
在 Python 本身中提供 PyTorch 模型是在生产环境中提供模型的最简单方法。 但是在解释如何完成之前,让我们快速看一下 Flask 是什么。 完全解释 Flask 不在本章的讨论范围内,但我们仍将介绍 Flask 的最基本概念。
### 烧瓶简介
### Flask 简介
Flask 是的微框架,已被 Python 领域的多家大公司用于生产。 即使 Flask 提供了可用于将 UI 推送到客户端的模板引擎,我们也没有使用它。 相反,我们将制作一个提供 API 的 RESTful 后端。
......@@ -97,7 +97,7 @@ class FizBuzNet(nn.Module):
return out
```
#### 用于 Flask 的模型
#### 用于 Flask 的模型
下面的屏幕快照给出了我们应用的目录结构。 `assets`文件夹具有训练好的模型,在加载模型时,`controller.py`文件将使用该模型。 根目录中的`app.py`是 Flask 应用的入口。 Flask 首选`app.py`作为入口点文件的默认名称。
......@@ -135,7 +135,7 @@ def predict():
return out
```
Flask 为我们提供了`request`实用程序,它是一个全局变量,但对于存储有关当前请求信息的当前线程而言是局部的。 我们使用`request`对象的`get_json`函数从`request`对象获取主体`POST`参数。 然后,将通过 HTTP 传入的字符串数据转换为整数。 这个整数是我们从前端传递的数字。 我们应用的任务是预测下一个数字的状态。 那将是下一个数字本身还是嘶嘶声,嗡嗡声或嘶嘶声? 但是,如果您还记得,我们会训练我们的网络来预测我们通过的号码的状态。 但是,我们需要下一个号码的状态。 因此,我们将一个加到当前数上,然后将结果传递给我们的模型。
Flask 为我们提供了`request`工具,它是一个全局变量,但对于存储有关当前请求信息的当前线程而言是局部的。 我们使用`request`对象的`get_json`函数从`request`对象获取主体`POST`参数。 然后,将通过 HTTP 传入的字符串数据转换为整数。 这个整数是我们从前端传递的数字。 我们应用的任务是预测下一个数字的状态。 那将是下一个数字本身还是嘶嘶声,嗡嗡声或嘶嘶声? 但是,如果您还记得,我们会训练我们的网络来预测我们通过的号码的状态。 但是,我们需要下一个号码的状态。 因此,我们将一个加到当前数上,然后将结果传递给我们的模型。
我们的下一个导入是`controller`,我们在其中加载了模型文件。 我们正在调用`run`方法并将数字传递给模型。 然后,将`controller`的预测值作为字典传递回。 Flask 会将其转换为响应正文并将其发送回用户。
......@@ -158,7 +158,7 @@ Flask 为我们提供了`request`实用程序,它是一个全局变量,但
通过从加载了保存的`.pth`文件的模型文件中调用`FizBuz`类来创建我们的模型。 我们使用 Torch 的`load_state_dict`方法将参数加载到初始化的模型中。 之后,我们将模型转换为`eval()`模式,这将模型设置为评估模式(它在评估模式下关闭了`batchnorm`丢弃层)。 模型的输出是运行`max`并确定哪个索引具有最大值,然后将其转换为可读输出的概率分布。
#### 准备生产的服务器
#### 为生产准备的服务器
这是关于如何使用 Flask 将 PyTorch 模型部署到服务器的非常基本的演练。 但是 Flask 的内置服务器尚未投入生产,只能用于开发目的。 开发完成后,我们应该使用其他服务器软件包在生产中为 Flask 应用提供服务。
......@@ -297,9 +297,9 @@ netron -b fizbuz.onnx
MXNet 比其他服务模块更好。 在撰写本文时,TensorFlow 与 Python 3.7 不兼容,并且 MXNet 的服务模块已与内置的 ONNX 模型集成,这使开发人员可以轻松地以很少的命令行为模型提供服务,而无需了解其复杂性 分布式或高度可扩展的部署。
其他模型服务器,例如 TensorRT 和 Clipper,不像 MXNet 服务器那样易于设置和管理。 而且,MXNet 附带了另一个名为 MXNet 存档器的实用程序,该实用程序将所有必需的文件打包成一个捆绑包,这些文件可以独立部署,而不必担心其他依赖项。 除了 MXNet 模型服务器具备的所有这些很酷的功能之外,最大的好处是能够自定义预处理和后处理步骤。 我们将在接下来的部分中介绍如何完成所有这些操作。
其他模型服务器,例如 TensorRT 和 Clipper,不像 MXNet 服务器那样易于设置和管理。 而且,MXNet 附带了另一个名为 MXNet 存档器的工具,该工具将所有必需的文件打包成一个捆绑包,这些文件可以独立部署,而不必担心其他依赖项。 除了 MXNet 模型服务器具备的所有这些很酷的功能之外,最大的好处是能够自定义预处理和后处理步骤。 我们将在接下来的部分中介绍如何完成所有这些操作。
整个过程的流程从我们尝试使用模型存档器创建具有`.mar`格式的单个存档文件的位置开始。 单个捆绑包文件需要 ONNX 模型文件`signature.json`,该文件提供有关输入大小,名称等的信息。 认为它是可以随时更改的配置文件。 如果您决定将所有值硬编码到代码中,而不是从配置中读取,则它甚至不必成为存档的一部分。 然后,您需要服务文件,您可以在其中定义预处理,推理功能,后处理功能和其他实用程序功能。
整个过程的流程从我们尝试使用模型存档器创建具有`.mar`格式的单个存档文件的位置开始。 单个捆绑包文件需要 ONNX 模型文件`signature.json`,该文件提供有关输入大小,名称等的信息。 认为它是可以随时更改的配置文件。 如果您决定将所有值硬编码到代码中,而不是从配置中读取,则它甚至不必成为存档的一部分。 然后,您需要服务文件,您可以在其中定义预处理,推理功能,后处理功能和其他工具功能。
制作完模型档案后,我们可以调用模型服务器,并将位置作为输入传递给我们的模型档案。 而已; 您现在可以从超级性能模型服务器提供模型。
......
......@@ -6,7 +6,7 @@
此实现使用 PyTorch 张量手动计算正向传播,损耗和后向通过。
PyTorch张量基本上与 numpy 数组相同:它对深度学习或计算图或梯度一无所知,只是用于任意数值计算的通用 n 维数组。
PyTorch 张量基本上与 numpy 数组相同:它对深度学习或计算图或梯度一无所知,只是用于任意数值计算的通用 n 维数组。
numpy 数组和 PyTorch 张量之间的最大区别是 PyTorch 张量可以在 CPU 或 GPU 上运行。 要在 GPU 上运行操作,只需将张量转换为 cuda 数据类型。
......
......@@ -78,7 +78,7 @@ class PositionalEncoding(nn.Module):
## 加载和批量数据
本教程使用`torchtext`生成 Wikitext-2 数据集。 `vocab`对象是基于训练数据集构建的,用于将标记数字化为张量。 从顺序数据开始,`batchify()`函数将数据集排列为列,以修剪掉数据分成大小为`batch_size`的批量后剩余的所有令牌。 例如,以字母为序列(总长度为 26)并且批大小为 4,我们将字母分为 4 个长度为 6 的序列:
本教程使用`torchtext`生成 Wikitext-2 数据集。 `vocab`对象是基于训练数据集构建的,用于将标记数字化为张量。 从序列数据开始,`batchify()`函数将数据集排列为列,以修剪掉数据分成大小为`batch_size`的批量后剩余的所有令牌。 例如,以字母为序列(总长度为 26)并且批大小为 4,我们将字母分为 4 个长度为 6 的序列:
![](img/tex27-1.gif)
......
......@@ -10,7 +10,7 @@
## 数据处理
`torchtext`具有实用程序,可用于创建可以轻松迭代的数据集,以创建语言翻译模型。 在此示例中,我们展示了如何对原始文本句子进行标记,构建词汇表以及将标记数字化为张量。
`torchtext`具有工具,可用于创建可以轻松迭代的数据集,以创建语言翻译模型。 在此示例中,我们展示了如何对原始文本句子进行标记,构建词汇表以及将标记数字化为张量。
注意:本教程中的分词需要 [Spacy](https://spacy.io) 我们使用 Spacy 是因为它为英语以外的其他语言的分词提供了强大的支持。 `torchtext`提供了`basic_english`标记器,并支持其他英语标记器(例如 [Moses](https://bitbucket.org/luismsgomes/mosestokenizer/src/default/)),但对于语言翻译(需要多种语言),Spacy 是您的最佳选择。
......
......@@ -27,7 +27,7 @@
* 神经网络(`torch.nn`
* 优化(`torch.optim`
* 自动微分(`torch.autograd`
* 视觉任务的实用程序`torchvision`-[单独的软件包](https://github.com/pytorch/vision))。
* 视觉任务的工具`torchvision`-[单独的软件包](https://github.com/pytorch/vision))。
```py
import gym
......@@ -158,7 +158,7 @@ class DQN(nn.Module):
### 输入提取
以下代码是用于从环境中提取和处理渲染图像的实用程序。 它使用`torchvision`程序包,可轻松组成图像变换。 一旦运行单元,它将显示它提取的示例补丁。
以下代码是用于从环境中提取和处理渲染图像的工具。 它使用`torchvision`程序包,可轻松组成图像变换。 一旦运行单元,它将显示它提取的示例补丁。
```py
resize = T.Compose([T.ToPILImage(),
......@@ -206,9 +206,9 @@ plt.show()
## 训练
### 超参数和实用程序
### 超参数和工具
该单元实例化我们的模型及其优化器,并定义一些实用程序
该单元实例化我们的模型及其优化器,并定义一些工具
* `select_action`-将根据 ε 贪婪策略选择一个动作。 简而言之,有时我们会使用模型来选择操作,有时我们会统一采样。 选择随机动作的可能性将从`EPS_START`开始,并朝`EPS_END`呈指数衰减。 `EPS_DECAY`控制衰减率。
* `plot_durations`-绘制情节持续时间以及最近 100 个情节的平均值(官方评估中使用的度量)的助手。 该图将在包含主要训练循环的单元下面,并且将在每个情节之后更新。
......
......@@ -170,7 +170,7 @@ MyCell(
![How autograd works](img/beccc5ac5df1571304e11d6b12772a99.png)
自动毕业的工作原理
Autograd 的工作原理
## TorchScript 的基础
......
......@@ -124,7 +124,7 @@ Tensor myadd_autograd(const Tensor& self, const Tensor& other) {
使用`torch::autograd::Function`正常编写 Autograd 函数,除了代替直接在`forward()`中编写实现,我们:
1. 使用`at::AutoNonVariableTypeMode` RAII 保护器关闭自动毕业处理,然后
1. 使用`at::AutoNonVariableTypeMode` RAII 保护器关闭 Autograd 处理,然后
2. 调用调度函数`myadd`以回调调度程序。
如果没有(1),您的调用将无限循环(并且堆栈溢出),因为`myadd`将使您返回此函数(因为最高优先级分配键仍将是自动微分的。)对于(1),自动微分不包括在 一组正在考虑的调度键,我们将转到下一个处理程序,即 CPU 和 CUDA。
......
......@@ -444,7 +444,7 @@ Xavier 初始化是神经网络中权重的初始化,是遵循高斯分布的
# 循环神经网络
循环神经网络,缩写为 RNN,用于顺序数据的情况下,无论是作为输入,输出还是两者。 RNN 之所以如此有效,是因为它们的架构可以汇总来自过去数据集的学习,并将其与新数据一起使用以增强学习。 这样,它可以捕获事件的顺序,这在前馈神经网络或统计时间序列分析的早期方法中是不可能的。
循环神经网络,缩写为 RNN,用于序列数据的情况下,无论是作为输入,输出还是两者。 RNN 之所以如此有效,是因为它们的架构可以汇总来自过去数据集的学习,并将其与新数据一起使用以增强学习。 这样,它可以捕获事件的顺序,这在前馈神经网络或统计时间序列分析的早期方法中是不可能的。
考虑时间序列数据,例如股票市场,音频或视频数据集,其中事件的顺序非常重要。 因此,在这种情况下,除了从整个数据中进行集体学习之外,从时间上遇到的数据中学习的顺序也很重要。 这将有助于捕捉潜在趋势。
......@@ -494,7 +494,7 @@ Xavier 初始化是神经网络中权重的初始化,是遵循高斯分布的
![](img/bfc6e3b7-5070-40ed-8b99-c4e9eaa28e96.png)
由于 RNN 合并了顺序数据,因此反向传播会随时间扩展到反向传播。 在此,时间是一系列相互连接的有序时间步长,从而可以通过不同的时间步长进行反向传播。
由于 RNN 合并了序列数据,因此反向传播会随时间扩展到反向传播。 在此,时间是一系列相互连接的有序时间步长,从而可以通过不同的时间步长进行反向传播。
# 长期短期记忆网络
......@@ -532,7 +532,7 @@ LSTM 是一项突破,因为人们可以通过将 RNN 合并为单元单元来
卷积神经网络或卷积神经网络是在计算机视觉中提供成功结果的深度神经网络。 它们的灵感来自动物视皮层中神经元的组织和信号处理,也就是说,单个皮层神经元会对其相关小区域(视野)中的刺激做出反应,称为**感受域** ,并且不同神经元的这些感受域完全重叠,覆盖了整个视野。
当输入空间中的输入包含相同类型的信息时,我们将共享权重并针对这些输入共同训练这些权重。 对于空间数据(例如图像),这种权重共享会导致 CNN。 同样,对于顺序数据(例如文本),我们目睹了 RNN 中的这种权重共享。
当输入空间中的输入包含相同类型的信息时,我们将共享权重并针对这些输入共同训练这些权重。 对于空间数据(例如图像),这种权重共享会导致 CNN。 同样,对于序列数据(例如文本),我们目睹了 RNN 中的这种权重共享。
CNN 在计算机视觉和自然语言处理领域具有广泛的应用。 就行业而言,Facebook 在其自动图像标记算法中使用了它,在图像搜索中使用了 Google,在产品推荐系统中使用了亚马逊,对家用提要进行个性化的 Pinterest,以及用于图像搜索和推荐的 Instagram。
......@@ -687,7 +687,7 @@ Inception 由 Google 团队于 2014 年创建。其主要思想是创建更广
我们将在接下来的主题中详细讨论这两个方面。
# 最优值函数
# 最优值函数
代理商应该能够考虑立即和未来的回报。 因此,还会为每个遇到的状态分配一个值,该值也反映了此将来的信息。 这称为值函数。 延迟奖励的概念来了,目前,现在采取的行动将导致未来的潜在奖励。
......@@ -711,7 +711,7 @@ V(s) = E[all future rewards discounted | S(t)=s]
![](img/be42dad4-02e2-4f9e-8af8-bb8b677521d4.png)
因此,策略图将提供给定特定状态的不同操作的概率集。 该策略与值功能一起创建了一个解决方案,可根据策略和状态的计算值来帮助代理导航。
因此,策略图将提供给定特定状态的不同操作的概率集。 该策略与值函数一起创建了一个解决方案,可根据策略和状态的计算值来帮助代理导航。
# 强化学习的 Q 学习方法
......@@ -1016,6 +1016,6 @@ Libratus 是由卡内基梅隆大学的 Tuomas Sandholm 教授带领的团队设
在本章中,我们涵盖了构建模块,例如包括逻辑回归的浅层和深度神经网络,单隐藏层神经网络,RNN,LSTM,CNN 及其其他变体。 针对这些主题,我们还介绍了多个激活函数,正向和反向传播的工作方式以及与深度神经网络训练相关的问题,例如消失和梯度爆炸。
然后,我们涵盖了强化学习中非常基本的术语,我们将在接下来的章节中对其进行详细探讨。 这些是最优标准,即值函数和策略。 我们还了解了一些强化学习算法,例如 Q 学习和 A3C 算法。 然后,我们在 TensorFlow 框架中介绍了一些基本计算,这是 OpenAI Gym 的简介,还讨论了强化学习领域的一些有影响力的先驱者和研究突破。
然后,我们涵盖了强化学习中非常基本的术语,我们将在接下来的章节中对其进行详细探讨。 这些是最优标准,即值函数和策略。 我们还了解了一些强化学习算法,例如 Q 学习和 A3C 算法。 然后,我们在 TensorFlow 框架中介绍了一些基本计算,这是 OpenAI Gym 的简介,还讨论了强化学习领域的一些有影响力的先驱者和研究突破。
在下一章中,我们将对几个 OpenAI Gym 框架环境实现基本的强化学习算法,并更好地理解 OpenAI Gym。
\ No newline at end of file
......@@ -26,7 +26,7 @@ OpenAI Gym 提供不同类型的环境。 它们如下:
我们将在本章介绍以下主题:
* OpenAI Gym环境
* OpenAI Gym 环境
* 使用 OpenAI Gym 环境对代理进行编程
* 将 Q 网络用于实际应用
......
......@@ -124,7 +124,7 @@ MDP 试图通过将网格划分为状态,动作,模型/转换模型和奖励
序列的效用是指当代理人经历状态序列时所获得的总报酬。 它表示为![](img/c8a1136e-a890-4b64-b93b-0aa377237852.png),其中![](img/39d5f4c8-1fcb-4251-935c-fe3ea8d928ec.png)表示状态序列。
第二个假设是,如果有两个实用程序![](img/77076182-0b36-44a5-958f-314ce66cd114.png)和![](img/edc776c0-cee1-4b2a-a2a1-d55b7d0d19bc.png),则两个序列的开始状态都相同,并且
第二个假设是,如果有两个工具![](img/77076182-0b36-44a5-958f-314ce66cd114.png)和![](img/edc776c0-cee1-4b2a-a2a1-d55b7d0d19bc.png),则两个序列的开始状态都相同,并且
![](img/bb59d758-3f56-4513-bc9d-9d1d8292d013.png)
......@@ -213,7 +213,7 @@ MDP 试图通过将网格划分为状态,动作,模型/转换模型和奖励
因此,为了解决:
* 从任意实用程序开始
* 从任意工具开始
* 根据邻域更新效用,直到收敛为止,也就是说,根据给定状态的着陆状态的效用,使用 Bellman 方程更新状态的效用
......@@ -239,13 +239,13 @@ MDP 试图通过将网格划分为状态,动作,模型/转换模型和奖励
* 因此,绿色和红色状态是终端状态,进入其中一个状态,游戏结束。 如果座席遇到绿色状态(即进球状态),则座席获胜;如果他们进入红色状态,则座席将输掉比赛。
* ![](img/c5ef3106-3865-42ac-b31d-00932fc9bdef.png),![](img/42d4df8a-cfdd-4178-b0f2-bd11a5ae69d4.png)(即,对除`G``B`状态之外的所有状态的奖励是-0.04),![](img/b4354f1f-4615-42ee-b355-e822c11f4a12.png)(即,第一个实用程序`G``B`状态外,时间步长为 0。
* ![](img/c5ef3106-3865-42ac-b31d-00932fc9bdef.png),![](img/42d4df8a-cfdd-4178-b0f2-bd11a5ae69d4.png)(即,对除`G``B`状态之外的所有状态的奖励是-0.04),![](img/b4354f1f-4615-42ee-b355-e822c11f4a12.png)(即,第一个工具`G``B`状态外,时间步长为 0。
* 如果沿期望的方向前进,则过渡概率`T(s, a, s')`等于 0.8; 否则,如果垂直于所需方向,则各为 0.1。 例如,如果操作是`UP`,则概率为 0.8,代理会`UP`,但概率为 0.1 时,它会`RIGHT`,而 0.1 则为`LEFT`
问题:
1. 在时间步骤 1 找到![](img/a57bc045-8c4f-4a08-9b91-8834e66133b0.png) X 状态的实用程序![](img/a57bc045-8c4f-4a08-9b91-8834e66133b0.png),也就是说,代理将进行一次迭代
1. 在时间步骤 1 找到![](img/a57bc045-8c4f-4a08-9b91-8834e66133b0.png) X 状态的工具![](img/a57bc045-8c4f-4a08-9b91-8834e66133b0.png),也就是说,代理将进行一次迭代
2. 同样,找到![](img/9f997dda-7c3a-4217-b267-9b18ddab28f7.png)
解:
......@@ -430,7 +430,7 @@ POMDP 中的值迭代基本上是从信念 MDP 获得的无限状态空间上的
# 使用 MDP 训练 FrozenLake-v0 环境
这是关于 OpenAI Gym中名为 **FrozenLake-v0** 的网格世界环境,在第 2 章“使用 OpenAI Gym训练强化学习智能体”中讨论。 我们实现了 Q 学习和 Q 网络(我们将在以后的章节中进行讨论)以了解 OpenAI Gym的环境。
这是关于 OpenAI Gym 中名为 **FrozenLake-v0** 的网格世界环境,在第 2 章“使用 OpenAI Gym 训练强化学习智能体”中讨论。 我们实现了 Q 学习和 Q 网络(我们将在以后的章节中进行讨论)以了解 OpenAI Gym 的环境。
现在,让我们尝试使用以下代码实现值迭代,以获取 FrozenLake-v0 环境中每个状态的效用值:
......@@ -592,6 +592,6 @@ After learning completion printing the utilities for each states below from stat
在本章中,我们介绍了网格世界类型的环境的详细信息,并了解了马尔可夫决策过程的基础,即状态,动作,奖励,过渡模型和策略。 此外,我们利用这些信息通过价值迭代和策略迭代方法来计算效用和最优策略。
除此之外,我们对部分可观察的马尔可夫决策过程是什么样子以及解决它们的挑战有了基本的了解。 最后,我们从 OpenAI Gym获取了我们最喜欢的 gridworld 环境,即 FrozenLake-v0,并实现了一种值迭代方法,以使我们的代理学会在该环境中导航。
除此之外,我们对部分可观察的马尔可夫决策过程是什么样子以及解决它们的挑战有了基本的了解。 最后,我们从 OpenAI Gym 获取了我们最喜欢的 gridworld 环境,即 FrozenLake-v0,并实现了一种值迭代方法,以使我们的代理学会在该环境中导航。
在下一章中,我们将从策略梯度开始,然后从 **FrozenLake** 过渡到其他一些引人入胜的复杂环境。
\ No newline at end of file
# 策略梯度
到目前为止,我们已经看到了如何使用基于价值的方法从值函数中派生隐式策略。 在这里,代理将尝试直接学习策略。 做法是相似的,任何有经验的代理人都会在目睹之后更改策略。
到目前为止,我们已经看到了如何使用基于价值的方法从值函数中派生隐式策略。 在这里,代理将尝试直接学习策略。 做法是相似的,任何有经验的代理人都会在目睹之后更改策略。
价值迭代,策略迭代和 Q 学习属于通过动态编程解决的基于价值的方法,而策略优化方法则涉及策略梯度和该知识与策略迭代的结合,从而产生了行动者批判算法。
根据动态编程方法,存在一组自洽方程,可以满足`Q``V`值。 策略优化是不同的,策略学习直接进行,而不是从值函数中得出:
根据动态编程方法,存在一组自洽方程,可以满足`Q``V`值。 策略优化是不同的,策略学习直接进行,而不是从值函数中得出:
![](img/783c3d44-900b-4334-a5e6-b4a2a297a1a8.png)
因此,基于价值的方法学习了价值函数,我们得出了一个隐式策略,但是使用基于策略的方法,就不会学习任何价值函数,而直接学习了该策略。 由于我们同时学习了价值功能和策略,而行为者批评方法更为先进,而网络学习价值功能则充当了作为参与者的策略网络的批评者。 在本章中,我们将深入研究基于策略的方法。
因此,基于价值的方法学习了值函数,我们得出了一个隐式策略,但是使用基于策略的方法,就不会学习任何值函数,而直接学习了该策略。 由于我们同时学习了值函数和策略,而行为者批评方法更为先进,而网络学习值函数则充当了作为参与者的策略网络的批评者。 在本章中,我们将深入研究基于策略的方法。
我们将在本章介绍以下主题:
......@@ -190,7 +190,7 @@ Episode T
由于这些更新针对所有状态独立发生,因此可以针对所有状态并行执行这些操作。
在完成情节的最后一步之后扩展每个州的计算值估计值时,我们发现基于值的更新与基于结果的更新相同,例如在蒙特卡洛方法中,我们会进行全面的展望,直到 剧集的结尾。 因此,我们需要一种更好的方法来更新我们的值函数估算值,而无需多做一步。 通过合并`TD(0)`规则,我们可以解决此问题。
在完成情节的最后一步之后扩展每个州的计算值估计值时,我们发现基于值的更新与基于结果的更新相同,例如在蒙特卡洛方法中,我们会进行全面的展望,直到 剧集的结尾。 因此,我们需要一种更好的方法来更新我们的值函数估算值,而无需多做一步。 通过合并`TD(0)`规则,我们可以解决此问题。
# `TD(0)`规则
......@@ -348,7 +348,7 @@ end for
# 使用策略梯度的智能体学习 Pong
在本节中,我们将创建一个策略网络,该策略网络将使用来自 pong 环境的原始像素(来自 OpenAI Gym的 **pong-v0**)作为输入。 策略网络是一个单独的隐藏层神经网络,它全连接到输入层上 pong 的原始像素,还全连接到包含单个节点的输出层,该单个节点返回了桨上升的可能性。 我要感谢 Andrej Karpathy 提出了一种使代理使用策略梯度进行学习的解决方案。 我们将尝试实现类似的方法。
在本节中,我们将创建一个策略网络,该策略网络将使用来自 pong 环境的原始像素(来自 OpenAI Gym **pong-v0**)作为输入。 策略网络是一个单独的隐藏层神经网络,它全连接到输入层上 pong 的原始像素,还全连接到包含单个节点的输出层,该单个节点返回了桨上升的可能性。 我要感谢 Andrej Karpathy 提出了一种使代理使用策略梯度进行学习的解决方案。 我们将尝试实现类似的方法。
灰度大小为`80 * 80`的像素图像(我们将不使用 RGB,即`80 * 80 * 3`)。 因此,我们有一个`80 * 80`的二进制网格,它告诉我们桨和球的位置,并将其作为输入输入到神经网络。 因此,神经网络将包含以下内容:
......
# Q 学习和深度 Q 网络
在第 3 章,“马尔可夫决策过程”中,我们讨论了遵循马尔可夫性质的环境过渡模型以及延迟的奖励和价值的概念( 或实用程序)功能。 好,在本章中,我们将研究马尔可夫决策过程,了解 Q 学习,以及一种称为深度 Q 网络的改进方法,用于在不同环境中进行泛化。
在第 3 章,“马尔可夫决策过程”中,我们讨论了遵循马尔可夫性质的环境过渡模型以及延迟的奖励和价值的概念( 或工具)功能。 好,在本章中,我们将研究马尔可夫决策过程,了解 Q 学习,以及一种称为深度 Q 网络的改进方法,用于在不同环境中进行泛化。
我们将在本章介绍以下主题:
......@@ -48,7 +48,7 @@ DeepMind 在研究期刊 **Nature** 上发表了他们的论文[《通过深度
在第 3 章,“马尔可夫决策过程”中,我们使用状态,动作,奖励,过渡模型和折现因子来解决我们的马尔可夫决策过程,即 MDP 问题。 因此,如果 MDP 问题的所有这些要素均可用,我们可以轻松地使用规划算法为目标提出解决方案。 这种类型的学习称为**基于模型的学习**,其中 AI 代理将与环境交互,并基于其交互,将尝试近似环境的模型,即状态转换模型。 给定模型,现在代理可以尝试通过值迭代或策略迭代找到最佳策略。
但是,对于我们的 AI 代理来说,学习环境的显式模型不是必需的。 它可以直接从与环境的交互中得出最佳策略,而无需构建模型。 这种学习称为**无模型学习**。 无模型学习涉及在没有具体环境模型的情况下预测某个策略的价值功能
但是,对于我们的 AI 代理来说,学习环境的显式模型不是必需的。 它可以直接从与环境的交互中得出最佳策略,而无需构建模型。 这种学习称为**无模型学习**。 无模型学习涉及在没有具体环境模型的情况下预测某个策略的值函数
可以使用两种方法完成无模型学习:
......@@ -89,7 +89,7 @@ Repeat forever:
![](img/d82f0db8-7eb5-4425-b229-a08877c1ba7d.png)
时间差异学习是一种用于学习价值和策略迭代方法中的值函数以及 Q 学习中的 Q 函数的方法。
时间差异学习是一种用于学习价值和策略迭代方法中的值函数以及 Q 学习中的 Q 函数的方法。
如果我们希望我们的 AI 代理始终选择最大化折扣未来奖励的行动,那么我们需要某种时间差异学习。 为此,我们需要定义一个函数 Q,该函数表示当我们在状态`s`上执行动作`a`时最大的未来折扣。 因此,Q 函数表示给定状态下的动作质量。 使用它,我们可以通过仅了解当前状态和操作来估算最终得分,而在此之后无需进行任何操作。 因此,目标将是对具有最高 Q 值的状态采取该措施。 因此,我们必须通过称为 Q 学习的过程来学习此 Q 函数。
......@@ -159,7 +159,7 @@ end
因此,难题是 AI 是仅根据当前最佳策略基于动作信任已获悉的 Q 值,还是应该随机尝试其他动作以希望获得更好的回报,从而改善 Q 值,因此, 得出更好的最佳策略。
# OpenAI Gym山地车问题的 Q 学习
# OpenAI Gym 山地车问题的 Q 学习
**山地车**是强化学习领域的标准测试问题。 它由动力不足的汽车组成,必须将陡峭的山坡驱动到标志点,如下图所示:
......@@ -423,9 +423,9 @@ end
![](img/f31160d6-e246-41db-84d5-91fc9bd2495c.png)
决斗 DQN 具有独立的网络来计算值和优势函数,然后将它们组合回以获取 Q 函数的值。 将价值和优势的计算脱钩的原因在于,对于给定状态下的每个动作,代理不必照顾不必要的值函数。 因此,将这些计算去耦会导致鲁棒的状态动作 Q 值。
决斗 DQN 具有独立的网络来计算值和优势函数,然后将它们组合回以获取 Q 函数的值。 将价值和优势的计算脱钩的原因在于,对于给定状态下的每个动作,代理不必照顾不必要的值函数。 因此,将这些计算去耦会导致鲁棒的状态动作 Q 值。
# 适用于 OpenAI Gym山地车问题的深度 Q 网络
# 适用于 OpenAI Gym 山地车问题的深度 Q 网络
在针对山地车问题实现 Q 学习时,我们已经讨论了环境。 让我们直接深入实现一个深度 Q 网络来解决山地车问题。 首先,我们将使用以下代码导入所需的库:
......@@ -688,9 +688,9 @@ Episode 10 with Reward : 38.7923903502 at epsilon 0.9002 in steps 126
![](img/c662d7ff-84d0-4610-b63d-daec721d3143.png)
接下来,在以下主题中,我们尝试实现一个深度 Q 网络来解决 OpenAI Gym中的 Cartpole 问题。
接下来,在以下主题中,我们尝试实现一个深度 Q 网络来解决 OpenAI Gym 中的 Cartpole 问题。
# 适用于 OpenAI Gym的 Cartpole 问题的深度 Q 网络
# 适用于 OpenAI Gym 的 Cartpole 问题的深度 Q 网络
**Cartpole** 是 MDP 环境中最简单的问题之一,如以下屏幕快照所示。 它由一个在水平轴上移动的推车组成,该推车的中心处固定有一根可旋转的杆。 目的是采取行动,使电杆保持接近垂直且不会向下旋转。
......@@ -1361,7 +1361,7 @@ For each episode:
end
```
# 适用于 OpenAI Gym山地车问题的 SARSA 算法
# 适用于 OpenAI Gym 山地车问题的 SARSA 算法
让我们尝试实现先前在山地车问题中解释过的 SARSA 算法。 该程序的初始部分与先前的 Q 学习器具有相似之处。
......@@ -1506,6 +1506,6 @@ Episode 10 completed with total reward 213.212231118 in 786 steps
我们知道强化学习可以优化环境中智能体的回报,**马尔可夫决策过程****MDP**)是一种环境表示和数学框架,用于使用状态对决策进行建模 ,动作和奖励。 在本章中,我们了解到 Q 学习是一种无需任何过渡模型即可为任何 MDP 找到最佳动作选择策略的方法。 另一方面,如果给出了转换模型,则值迭代会为任何 MDP 找到最佳的动作选择策略。
我们还学习了另一个重要的话题,称为深度 Q 网络,这是一种经过改进的 Q 学习方法,它采用深度神经网络作为函数逼近器来在不同环境中进行泛化,这与特定于环境的 Q 表不同。 此外,我们还学会了在 OpenAI Gym环境中实现 Q 学习,深度 Q 网络和 SARSA 算法。 先前显示的大多数实现可能在具有更好的超参数值和更多训练集的情况下效果更好。
我们还学习了另一个重要的话题,称为深度 Q 网络,这是一种经过改进的 Q 学习方法,它采用深度神经网络作为函数逼近器来在不同环境中进行泛化,这与特定于环境的 Q 表不同。 此外,我们还学会了在 OpenAI Gym 环境中实现 Q 学习,深度 Q 网络和 SARSA 算法。 先前显示的大多数实现可能在具有更好的超参数值和更多训练集的情况下效果更好。
在下一章中,我们将详细介绍著名的异步优势参与者批评算法。
\ No newline at end of file
......@@ -22,7 +22,7 @@
* 异步一步 SARSA
* 异步 N 步 Q 学习
* 异步优势演员评论家
* OpenAI Gym中用于 CartPole v0 的 A3C
* OpenAI Gym 中用于 CartPole v0 的 A3C
# 为什么使用异步方法?
......@@ -265,9 +265,9 @@ repeat until :
Asynchronous update of using and using
```
# OpenAI Gym中 Pong-v0 的 A3C
# OpenAI Gym 中 Pong-v0 的 A3C
在第 4 章和“策略梯度”中,我们已经讨论过乒乓环境。 我们将使用以下代码在 OpenAI Gym中为 Pong-v0 创建 A3C:
在第 4 章和“策略梯度”中,我们已经讨论过乒乓环境。 我们将使用以下代码在 OpenAI Gym 中为 Pong-v0 创建 A3C:
```py
import multiprocessing
......
......@@ -35,7 +35,7 @@
在本书中,我们涵盖了从基础到高级的强化学习领域中的大多数算法。 因此,这些章节是理解机器人领域中不同算法所面临的应用和挑战的前提。 早期强化学习算法通过首先获取状态动作值,然后从中得出策略来处理获取最佳策略的问题。 然后,策略迭代方法出现了,直接用于输出优化的策略。 探索开发技术有助于完善现有策略,探索新措施并更新现有策略。 强化学习方法,例如 MDP(在第 3 章,“马尔可夫决策过程”中),其中需要采用过渡模型的值迭代方法称为**基于模型的学习器**。 另一方面,诸如 Q 学习(在第 5 章,“Q 学习和深度 Q 网络”中)的算法不需要这种过渡模型,因此也不需要任何预定义的策略。 他们被称为**无模型的脱离策略学习器**
在深度强化学习领域,行动值函数逼近器和策略函数逼近器在制定最先进的学习算法集方面发挥着关键作用。 策略搜索算法(例如策略梯度)旨在通过最大化期望的奖励总和来找到最佳策略,而使用行动值函数近似器(例如深度 Q 网络)的算法旨在通过最大化期望的总和来找到给定状态的行动值 奖励。 但是,在处理由高维和连续状态动作空间构成的环境时,性能上的差异在于,这最能描述机器人在其中运行的真实环境。 在这种情况下,策略搜索算法的性能会更好,因为它们在连续状态操作空间域中可以更好地工作:
在深度强化学习领域,行动值函数逼近器和策略函数逼近器在制定最先进的学习算法集方面发挥着关键作用。 策略搜索算法(例如策略梯度)旨在通过最大化期望的奖励总和来找到最佳策略,而使用行动值函数近似器(例如深度 Q 网络)的算法旨在通过最大化期望的总和来找到给定状态的行动值 奖励。 但是,在处理由高维和连续状态动作空间构成的环境时,性能上的差异在于,这最能描述机器人在其中运行的真实环境。 在这种情况下,策略搜索算法的性能会更好,因为它们在连续状态操作空间域中可以更好地工作:
![](img/dbe76734-7904-4c3f-b486-17840eae3d22.png)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册