提交 3416c9c4 编写于 作者: W wizardforcel

2021-01-20 21:31:43

上级 7bf8af2b
......@@ -2,7 +2,7 @@
**人工智能****AI**)继续流行并破坏了广泛的领域,但这是一个复杂而艰巨的话题。 在本书中,您将掌握构建深度学习应用程序的方法,以及如何使用 PyTorch 进行研究和解决实际问题。
本书从张量处理的基础开始,采用基于配方的方法,然后介绍了**卷积神经网络****CNN**)和 PyTorch 中的**循环神经网络****RNN**)。 熟悉这些基本网络后,您将使用深度学习来构建医学图像分类器。 接下来,您将使用 TensorBoard 进行可视化。 您还将深入研究**生成对抗网络****GAN**)和**深度强化学习****DRL**),然后最终将模型大规模部署到生产中。 您将发现针对机器学习,深度学习和强化学习中常见问题的解决方案。 您将学习如何在计算机视觉,**自然语言处理****NLP**)中实现 AI 任务并解决实际问题。 其他实际领域。
本书从张量处理的基础开始,采用基于秘籍的方法,然后介绍了**卷积神经网络****CNN**)和 PyTorch 中的**循环神经网络****RNN**)。 熟悉这些基本网络后,您将使用深度学习来构建医学图像分类器。 接下来,您将使用 TensorBoard 进行可视化。 您还将深入研究**生成对抗网络****GAN**)和**深度强化学习****DRL**),然后最终将模型大规模部署到生产中。 您将发现针对机器学习,深度学习和强化学习中常见问题的解决方案。 您将学习如何在计算机视觉,**自然语言处理****NLP**)中实现 AI 任务并解决实际问题。 其他实际领域。
到本书结尾,您将拥有使用 PyTorch 框架的 AI 中最重要且应用最广泛的技术的基础。
......@@ -24,7 +24,7 @@
第 6 章,“探索生成对抗网络”探索生成对抗网络,以及如何实现 PyTorch 的组件并训练端到端网络。 我们将探索 DCGAN,并通过渐进式 GAN 网络进一步改善 DCGAN 的局限性。
第 7 章,“深度强化学习”可帮助您通过各种食谱来了解深度 RL。 本章是一系列食谱和任务,您将在其中利用所需的能力和架构来转变为深度强化学习专家。
第 7 章,“深度强化学习”可帮助您通过各种秘籍来了解深度 RL。 本章是一系列秘籍和任务,您将在其中利用所需的能力和架构来转变为深度强化学习专家。
第 8 章,“PyTorch 中的生产 AI 模型”,着眼于以两种方式生产 PyTorch 应用程序。 首先,生成已经训练过的模型,其次,对大型数据集进行分布式训练。 最后,我们将研究各种框架之间的可移植性。
......@@ -94,15 +94,15 @@ pip3 install https://download.pytorch.org/whl/cu90/torch-1.1.0-cp36-cp36m-win_am
在本书中,您会发现几个经常出现的标题(“准备工作”,“操作步骤”,“工作原理”,“另见”。
要给出有关如何完成配方的明确说明,请按以下说明使用这些部分:
要给出有关如何完成秘籍的明确说明,请按以下说明使用这些部分:
# 做好准备
本节告诉您在配方中会有什么期望,并介绍如何设置配方所需的任何软件或任何初步设置。
本节告诉您在秘籍中会有什么期望,并介绍如何设置秘籍所需的任何软件或任何初步设置。
# 怎么做…
本节包含遵循食谱所需的步骤。
本节包含遵循秘籍所需的步骤。
# 这个怎么运作…
......@@ -110,9 +110,9 @@ pip3 install https://download.pytorch.org/whl/cu90/torch-1.1.0-cp36-cp36m-win_am
# 还有更多…
本节包含有关配方的其他信息,以使您对配方有更多的了解。
本节包含有关秘籍的其他信息,以使您对秘籍有更多的了解。
# 也可以看看
本节提供了指向该食谱其他有用信息的有用链接。
本节提供了指向该秘籍其他有用信息的有用链接。
......@@ -6,7 +6,7 @@ PyTorch 是 Python 中的一个开源深度学习框架,它使我们能够从
PyTorch 与 Python 深度集成,具有命令式风格,使用类似 Python 的语法,并且在 Eager 模式下易于使用且灵活。 它的学习曲线很浅,可以让您专注于功能而不是框架的样板和语法。 Python 命令的纯命令执行将失去很多优化机会,因此,随着**即时****JIT**)编译器的引入,PyTorch 允许过渡到图形 C++ 运行时环境中用于速度,功能和优化的模式。 它得到了来自不同领域的专业人员的大力社区支持,并且与图书馆打交道。 它具有与框架互操作性的本地**开放神经网络交换****ONNX**)支持。 它是分布式的,可扩展到生产环境,与 TensorBoard 集成,并具有出色的文档和 API,您可以轻松编写针对 CPU 和 GPU 的自定义扩展。 我们将在接下来的章节中探索这些以及更多内容。
在本章中,我们将介绍以下食谱
在本章中,我们将介绍以下秘籍
* 安装 PyTorch
* 在 PyTorch 中创建张量
......@@ -92,7 +92,7 @@ import numpy
![](img/ccc2bd36-f510-4adf-ac38-c7c185d40e53.png)
这样,我们将继续介绍如何使用张量的食谱
这样,我们将继续介绍如何使用张量的秘籍
# 怎么做...
......@@ -121,7 +121,7 @@ tensor([[1., 1., 1.],
* 现在,我们将创建一个仅由整数组成的张量:
1. 我们将执行与上一食谱完全相同的操作,但是将添加数据类型(`dtype`)作为参数:
1. 我们将执行与上一秘籍完全相同的操作,但是将添加数据类型(`dtype`)作为参数:
```py
torch.ones((2,3), dtype=torch.int8)
......@@ -314,7 +314,7 @@ tensor([[3, 3],
# 这个怎么运作...
在本食谱中,我们介绍了从各种数据源创建张量的各种方法。 在我们开始探索使用 PyTorch 进行深度学习的概念及其原理之前,必须了解一些最常用的功能来处理数据的基本单位张量。 我们可以使用`torch.tensor()`方法创建具有各种值和形状的张量。 我们甚至可以从均匀分布或标准正态分布中得出张量,这对于初始化神经网络以获得最佳性能和训练时间至关重要,所有这些张量都具有默认的`torch.FloatTensor` 数据类型,并使用`dtype`更新数据类型。 参数。
在本秘籍中,我们介绍了从各种数据源创建张量的各种方法。 在我们开始探索使用 PyTorch 进行深度学习的概念及其原理之前,必须了解一些最常用的功能来处理数据的基本单位张量。 我们可以使用`torch.tensor()`方法创建具有各种值和形状的张量。 我们甚至可以从均匀分布或标准正态分布中得出张量,这对于初始化神经网络以获得最佳性能和训练时间至关重要,所有这些张量都具有默认的`torch.FloatTensor` 数据类型,并使用`dtype`更新数据类型。 参数。
`.ones()`方法创建一个包含给定形状的张量的张量,`.zeros()`用所有零填充该张量,`full()`方法将给定形状的张量填充。 `.empty()`方法创建一个空张量,`.rand()``[0, 1]`的均匀分布中绘制一个具有随机值的张量,`.randn()`从正态分布中绘制均值为 0 和方差 1 的一个具有随机值的张量 ,也称为标准正态分布。
......@@ -387,7 +387,7 @@ array([[1., 1., 1.],
[1., 1., 1.]])
```
有了这个配方,我们现在可以在 NumPy 和 Torch 张量之间来回移动了。
有了这个秘籍,我们现在可以在 NumPy 和 Torch 张量之间来回移动了。
# 这个怎么运作...
......@@ -566,7 +566,7 @@ PyTorch 有一个名为`autograd`的软件包,可以对张量上的所有操
在使用张量和处理神经网络时,我们经常需要遍历和重新排列张量中的数据,以使张量的尺寸适合架构的需求。 在本节中,我们将探讨 PyTorch 中常见的重排和重塑技术。
在本食谱中,我们将学习如何使张量看起来像我们想要的样子。
在本秘籍中,我们将学习如何使张量看起来像我们想要的样子。
# 怎么做...
......@@ -638,7 +638,7 @@ tensor([[1., 2., 3.],
# 这个怎么运作...
在前面的食谱中,我们基于网络架构操纵了张量以改变其形状,研究了三种不同的方法,每种方法都适用于不同的用例:
在前面的秘籍中,我们基于网络架构操纵了张量以改变其形状,研究了三种不同的方法,每种方法都适用于不同的用例:
* `.reshape()`方法:`.reshape(a, b)`返回一个新张量,该张量具有与原始张量`(a, b)`相同的数据,因为它会将数据复制到内存的另一部分; `.reshape()`可以在连续和非连续张量上运行,并且可以返回原始张量的副本或视图。
* `.resize()`方法:`.resize_(a, b)`返回相同的张量,而不创建具有新给定形状的副本。 但是我们应该记住,如果新形状产生的元素少于原始张量,那么它将不会引发任何错误,并且某些元素将从张量中删除,但不会从内存中删除。 如果新形状产生的元素多于原始张量,则新元素将在内存中未初始化而不会引发任何错误。
......
......@@ -14,7 +14,7 @@
在前面的图中,圆圈代表神经元,或用深度学习的术语代表作为计算单元的节点。 边缘代表节点之间的连接,并保持两个节点之间的连接权重(突触强度)。
在本章中,以下食谱将使我们开始使用神经网络:
在本章中,以下秘籍将使我们开始使用神经网络:
* 定义神经网络类
* 创建一个全连接网络
......@@ -25,7 +25,7 @@
# 技术要求
在本章中,我们将开始处理图像数据并学习全连接神经网络如何工作。 PyTorch 有一个名为`torchvision`的补充库,我们将在开始食谱之前进行安装。
在本章中,我们将开始处理图像数据并学习全连接神经网络如何工作。 PyTorch 有一个名为`torchvision`的补充库,我们将在开始秘籍之前进行安装。
您可以对`torchvision`使用以下`pip`安装命令:
......@@ -37,7 +37,7 @@ pip install torchvision
# 定义神经网络类
在本食谱中,我们将从了解`torchvision`的一些重要功能开始,这些功能使它能够处理图像数据并进行处理。 然后,我们将通过定义一个类来定义神经网络的基本架构,并查看可用于此的模块和方法。 在本食谱中,我们将专注于全连接神经网络类。 它的属性是各个层,其目的是对各种类型的衣服进行分类。
在本秘籍中,我们将从了解`torchvision`的一些重要功能开始,这些功能使它能够处理图像数据并进行处理。 然后,我们将通过定义一个类来定义神经网络的基本架构,并查看可用于此的模块和方法。 在本秘籍中,我们将专注于全连接神经网络类。 它的属性是各个层,其目的是对各种类型的衣服进行分类。
我们将使用 Fashion–MNIST 数据集。 这是 Zalando 文章图片的数据集,包括 6 万个示例的训练集和 10,000 个示例的测试集。 我们将拍摄一张尺寸为`28 x 28`的灰度图像,并将其转换为 784 的向量。
......@@ -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()`结合在一起。
准备好转换后,我们定义了合适的批量大小。 较高的批量大小意味着该模型具有较少的训练步骤并且学习速度更快,而较高的批量大小会导致对内存的高要求。
......@@ -154,9 +154,9 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
# 创建一个全连接网络
在本食谱中,我们将扩展在先前食谱“定义神经网络类”中定义的类。 在“定义神经网络类”配方中,我们仅创建了所需架构的组件; 现在我们将把所有这些部分捆绑在一起,以建立一个明智的网络。 我们各层的进度将从 784 个单位增加到 256 个,然后是 128 个,最后是 10 个单位的输出层。
在本秘籍中,我们将扩展在先前秘籍“定义神经网络类”中定义的类。 在“定义神经网络类”秘籍中,我们仅创建了所需架构的组件; 现在我们将把所有这些部分捆绑在一起,以建立一个明智的网络。 我们各层的进度将从 784 个单位增加到 256 个,然后是 128 个,最后是 10 个单位的输出层。
在本食谱中,我们将使用类的构造函数中定义的组件来研究网络架构。 然后,我们将完成网络类定义并创建其对象。
在本秘籍中,我们将使用类的构造函数中定义的组件来研究网络架构。 然后,我们将完成网络类定义并创建其对象。
# 怎么做...
......@@ -228,7 +228,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
# 这个怎么运作...
配方中,通过建立前向网络来完成网络,其中我们将构造函数中定义的网络组件捆绑在一起。 用`nn.Module`定义的网络需要定义`forward()`方法。 它采用输入张量,并按照正向方法中定义的操作顺序,将其通过网络类中`__init__()`方法中定义的网络组件。
秘籍中,通过建立前向网络来完成网络,其中我们将构造函数中定义的网络组件捆绑在一起。 用`nn.Module`定义的网络需要定义`forward()`方法。 它采用输入张量,并按照正向方法中定义的操作顺序,将其通过网络类中`__init__()`方法中定义的网络组件。
当传递输入时,将引用模型对象的名称自动调用 forward 方法。 `nn.Module`自动创建将在正向方法中使用的权重和偏差张量。 线性单位本身定义了线性函数,例如`xW + B`; 要具有非线性功能,我们需要插入非线性激活函数,在这里我们使用最流行的激活函数之一 ReLU,尽管您可以在 PyTorch 中使用其他可用的激活函数。
......@@ -246,7 +246,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
机器学习模型在接受训练时,可能会在预测输出和实际输出之间存在一些偏差,这种差异称为模型的**误差**。 让我们计算该误差的函数称为**损失函数****误差函数**。 此功能提供了一种度量标准,用于评估所有可能的解决方案并选择最优化的模型。 损失函数必须能够将模型的所有属性减少到一个单一的数字,以便该损失函数值的改善代表更好的模型。
在本食谱中,我们将使用 PyTorch 中可用的损失函数为我们的时装数据集定义损失函数。
在本秘籍中,我们将使用 PyTorch 中可用的损失函数为我们的时装数据集定义损失函数。
# 怎么做...
......@@ -309,7 +309,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
# 这个怎么运作...
在此配方中,我们用对数 softmax 替换了 softmax,以便随后可以使用概率对数而不是概率的对数,这具有很好的理论解释。 这样做有多种原因,包括改进的数值性能和梯度优化。 在训练可能具有计算挑战性和昂贵成本的模型时,这些优势非常重要。 此外,当它没有预测正确的类别时,它具有很高的惩罚作用。
在此秘籍中,我们用对数 softmax 替换了 softmax,以便随后可以使用概率对数而不是概率的对数,这具有很好的理论解释。 这样做有多种原因,包括改进的数值性能和梯度优化。 在训练可能具有计算挑战性和昂贵成本的模型时,这些优势非常重要。 此外,当它没有预测正确的类别时,它具有很高的惩罚作用。
因此,在处理对数 softmax 时,我们会使用负对数似然率,因为 softmax 不兼容。 在`n`类数之间的分类中很有用。 该对数将确保我们不会处理 0 到 1 之间的非常小的值,而负值将确保小于 1 的概率的对数非零。 我们的目标是减少这种负的对数丢失误差函数。 在 PyTorch 中,损失函数称为**标准**,因此我们将损失函数命名为`criterion`
......@@ -323,7 +323,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
# 实施优化器
在本食谱中,我们将学习优化器。 在先前的食谱“定义损失函数”中,我们谈到了误差和误差函数,并了解到,为了获得一个好的模型,我们需要最小化计算出的误差。 **反向传播**是神经网络从错误中学习的一种方法。 错误用于修改权重,以使错误最小化。 优化功能负责修改权重以减少误差。 优化函数计算相对于权重的误差的偏导数。 导数显示正斜率的方向,因此我们需要反转梯度的方向。 **优化器**函数将模型参数和损失函数结合在一起,以迭代方式修改模型参数以减少模型误差。 可以考虑将优化器摆在模型权重的基础上,根据模型与实际输出的预测差异来获得最佳模型,而损失函数则通过指示优化器是对还是错来充当指导。
在本秘籍中,我们将学习优化器。 在先前的秘籍“定义损失函数”中,我们谈到了误差和误差函数,并了解到,为了获得一个好的模型,我们需要最小化计算出的误差。 **反向传播**是神经网络从错误中学习的一种方法。 错误用于修改权重,以使错误最小化。 优化功能负责修改权重以减少误差。 优化函数计算相对于权重的误差的偏导数。 导数显示正斜率的方向,因此我们需要反转梯度的方向。 **优化器**函数将模型参数和损失函数结合在一起,以迭代方式修改模型参数以减少模型误差。 可以考虑将优化器摆在模型权重的基础上,根据模型与实际输出的预测差异来获得最佳模型,而损失函数则通过指示优化器是对还是错来充当指导。
学习速率是优化器的超参数,它控制权重的更新量。 学习速度确保了权重不会大量更新,从而使算法根本无法收敛,并且误差越来越大。 然而,与此同时,权重的更新不应太低,以至于永远需要花费成本函数/误差函数的最小值。
......@@ -331,7 +331,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
![](img/ca32e442-d198-424e-bc49-52451f5a458b.png)
在本食谱中,我们将学习如何在 PyTorch 中使用优化器功能,以及一些常见的优化功能以及如何处理学习率。
在本秘籍中,我们将学习如何在 PyTorch 中使用优化器功能,以及一些常见的优化功能以及如何处理学习率。
# 怎么做...
......@@ -385,7 +385,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
>>running_loss = 0
```
8.我们将在训练图像加载器中遍历每个图像,这在本章前面的食谱“定义神经网络类”中定义:
8.我们将在训练图像加载器中遍历每个图像,这在本章前面的秘籍“定义神经网络类”中定义:
```py
>>for image, label in trainloader:
......@@ -459,7 +459,7 @@ Training loss: 0.2596
# 这个怎么运作...
在本食谱中,我们首先使用`Adam`优化器定义优化器,然后为优化器设置学习率,并查看默认参数。 我们设置一个时期`10`,并为每个时期开始迭代,在每次迭代中将`running_loss`设置为 0,并在该时期内对每个图像进行迭代(模型看到数据集的次数)。 我们首先使用`.zero_grad()`方法清除梯度。 PyTorch 在每次向后传递时都会累积梯度,这在某些情况下很有用,因此将其导入以将梯度归零,以正确更新模型参数。
在本秘籍中,我们首先使用`Adam`优化器定义优化器,然后为优化器设置学习率,并查看默认参数。 我们设置一个时期`10`,并为每个时期开始迭代,在每次迭代中将`running_loss`设置为 0,并在该时期内对每个图像进行迭代(模型看到数据集的次数)。 我们首先使用`.zero_grad()`方法清除梯度。 PyTorch 在每次向后传递时都会累积梯度,这在某些情况下很有用,因此将其导入以将梯度归零,以正确更新模型参数。
接下来,我们通过将每批 64 幅图像(每幅图像由`28 x 28`像素组成)展平到 784 来重塑图像,从而将张量形状从`64 x 28 x 28`更改为`64 x 784`,因为我们的模型期望这种形状 输入。 接下来,我们将此输入发送到模型,并从模型中获得该批量的输出预测,然后将其传递给损失函数,也称为`criterion`; 在那里,它评估了预测班级与实际班级之间的差异。
......@@ -475,13 +475,13 @@ Training loss: 0.2596
# 实施辍学
在本食谱中,我们将研究实现辍学。 在训练神经网络模型或一般任何机器学习模型时,我们可能会遇到的一种较常见的现象是过拟合。 当模型学习提供给训练的数据而不是在求解空间上进行泛化时,就会发生过拟合,也就是说,模型学习的是训练数据的细微细节和噪声,而不是掌握全局,因此在效果上表现不佳。 新数据。 正则化是防止模型过拟合的过程。
在本秘籍中,我们将研究实现辍学。 在训练神经网络模型或一般任何机器学习模型时,我们可能会遇到的一种较常见的现象是过拟合。 当模型学习提供给训练的数据而不是在求解空间上进行泛化时,就会发生过拟合,也就是说,模型学习的是训练数据的细微细节和噪声,而不是掌握全局,因此在效果上表现不佳。 新数据。 正则化是防止模型过拟合的过程。
使用辍学是神经网络中最流行的正则化技术之一,在这种技术中,训练时会关闭随机选择的神经元,也就是说,神经元的作用会暂时从正向传递中移除,而向后传递不会影响权重 ,因此没有一个神经元或神经元子集能获得模型的所有决定力; 相反,所有神经元都被迫为预测做出积极贡献。
辍学可以直观地理解为创建大量集成模型,学习在一个模型的大定义下捕获各种功能。
在本食谱中,我们将研究如何在模型定义中添加缺失,以通过防止过拟合来改善整体模型性能。 应当记住,辍学仅在训练时才适用; 但是,在测试和实际预测期间,我们希望所有神经元都做出贡献。
在本秘籍中,我们将研究如何在模型定义中添加缺失,以通过防止过拟合来改善整体模型性能。 应当记住,辍学仅在训练时才适用; 但是,在测试和实际预测期间,我们希望所有神经元都做出贡献。
# 怎么做...
......@@ -546,7 +546,7 @@ Training loss: 0.2596
# 这个怎么运作...
在此配方中,我们更改了`__init__()`方法,以 0.25 的丢失率添加了该丢失层,这意味着将应用该丢失的层中 25% 的神经元将被随机关闭。 然后,我们编辑`forward`函数,将其应用于其中具有 256 个单位的第一个隐藏层,然后对第二个层(具有 128 个单位)应用该滤除。 在完成激活函数之后,我们在两个层中都应用了激活。 我们必须牢记,必须仅在隐藏层上应用辍学,以防止我们丢失输入数据和丢失输出。
在此秘籍中,我们更改了`__init__()`方法,以 0.25 的丢失率添加了该丢失层,这意味着将应用该丢失的层中 25% 的神经元将被随机关闭。 然后,我们编辑`forward`函数,将其应用于其中具有 256 个单位的第一个隐藏层,然后对第二个层(具有 128 个单位)应用该滤除。 在完成激活函数之后,我们在两个层中都应用了激活。 我们必须牢记,必须仅在隐藏层上应用辍学,以防止我们丢失输入数据和丢失输出。
# 还有更多...
......@@ -558,7 +558,7 @@ Training loss: 0.2596
# 实施函数式 API
在本食谱中,我们将探索 PyTorch 中的函数式 API。 这样做将使我们能够编写更简洁的网络架构和组件。 我们将研究函数式 API,并使用函数式 API 定义模型或模型的一部分。
在本秘籍中,我们将探索 PyTorch 中的函数式 API。 这样做将使我们能够编写更简洁的网络架构和组件。 我们将研究函数式 API,并使用函数式 API 定义模型或模型的一部分。
# 怎么做...
......@@ -592,7 +592,7 @@ Training loss: 0.2596
# 这个怎么运作...
在此配方中,我们定义了与以前完全相同的网络,但是用`function.relu``function.log_softmax`代替了激活函数和对数 softmax,这使我们的代码看起来更加简洁明了。
在此秘籍中,我们定义了与以前完全相同的网络,但是用`function.relu``function.log_softmax`代替了激活函数和对数 softmax,这使我们的代码看起来更加简洁明了。
# 还有更多...
......
此差异已折叠。
......@@ -2,7 +2,7 @@
在本章中,我们将处理**循环神经网络****RNNs**),这是一种专门处理顺序数据或时变数据的神经网络。 利用卷积神经网络,我们处理在空间上彼此相关的数据点,其中一组像素值保存有关图像的信息。 但是请考虑一下节奏,节奏是由一段时间内一系列变化的声音信号形成的。 数据点彼此之间具有时间关系。 在循环神经网络中,神经元之间的连接在时间序列上形成有向图,表现出时间动态行为。 传统的前馈网络不存储先前的输入; 但是,RNN 使用存储单元来记住先前的输入,因此根据到目前为止的输入顺序来处理当前输入。
在本章中,我们将介绍以下食谱
在本章中,我们将介绍以下秘籍
* 代币化
* 创建字段
......@@ -69,11 +69,11 @@ pip install torchtext
# 代币化
在处理自然语言处理任务时,我们采用文本语料库并将其分解为较小的单元。 在本食谱中,我们将句子分解为单个单词,其中每个单词代表一个意思,其他单词与它附近的其他单词一起表达一个句子的意图。 计算机只能理解数字,因此为这些单词分配了唯一的整数值来表示单词。 将句子分解为标记的过程称为标记化。 在本食谱中,我们将执行单词标记化。
在处理自然语言处理任务时,我们采用文本语料库并将其分解为较小的单元。 在本秘籍中,我们将句子分解为单个单词,其中每个单词代表一个意思,其他单词与它附近的其他单词一起表达一个句子的意图。 计算机只能理解数字,因此为这些单词分配了唯一的整数值来表示单词。 将句子分解为标记的过程称为标记化。 在本秘籍中,我们将执行单词标记化。
# 怎么做...
在本食谱中,我们将编写一个标记器,将在本章的“创建字段”部分中使用:
在本秘籍中,我们将编写一个标记器,将在本章的“创建字段”部分中使用:
1. 我们将首先编写一个简单的 lambda 函数:
......@@ -88,11 +88,11 @@ pip install torchtext
['This', 'is', 'a', 'test', 'for', 'tokenizer']
```
在此食谱中,我们成功实现了单词标记化。
在此秘籍中,我们成功实现了单词标记化。
# 这个怎么运作...
在此食谱中,我们编写了一个简单的分词器 lambda 函数,该函数可用于英语和类似英语的语言。 我们使用单词之间的空格来标记句子。 然后,我们通过将句子传递给`tokenizer()`函数来测试标记器。 我们将在下一个配方中使用此标记生成器来创建字段。
在此秘籍中,我们编写了一个简单的分词器 lambda 函数,该函数可用于英语和类似英语的语言。 我们使用单词之间的空格来标记句子。 然后,我们通过将句子传递给`tokenizer()`函数来测试标记器。 我们将在下一个秘籍中使用此标记生成器来创建字段。
# 还有更多...
......@@ -112,13 +112,13 @@ pip install torchtext
# 创建字段
在本食谱中,我们将探索字段,这些字段与`torchvision`中可用的实用程序一样,使处理自然语言数据变得容易。 字段让我们定义数据类型,并通过指定要对数据执行的一组操作来帮助我们从文本数据中创建张量。 `Field`类使我们可以执行常见的文本处理任务,并掌握手边的数据词汇。
在本秘籍中,我们将探索字段,这些字段与`torchvision`中可用的实用程序一样,使处理自然语言数据变得容易。 字段让我们定义数据类型,并通过指定要对数据执行的一组操作来帮助我们从文本数据中创建张量。 `Field`类使我们可以执行常见的文本处理任务,并掌握手边的数据词汇。
在本食谱中,我们将研究如何使用`Field`类定义各种文本处理任务。
在本秘籍中,我们将研究如何使用`Field`类定义各种文本处理任务。
# 怎么做...
在本食谱中,我们将探讨使用字段的各种示例:
在本秘籍中,我们将探讨使用字段的各种示例:
1. 我们将从导入开始:
......@@ -162,11 +162,11 @@ pip install torchtext
>>SequenceField = Field(tokenize=tokenizer, init_token='<sos>', eos_token='<eos>', unk_token='<unk>', batch_first=True)
```
通过此食谱,我们探索了可用于在`torchtext`中创建字段的不同方法。
通过此秘籍,我们探索了可用于在`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`参数。
......@@ -182,11 +182,11 @@ pip install torchtext
# 开发数据集
在本食谱中,我们将研究读取文本数据并使用各种数据源。`torchtext`可以从文本文件,CSV/TSV 文件,JSON 文件和目录中读取数据,并将其转换为数据集。 数据集是已预处理的数据块,可读取到内存中,并可由其他数据结构使用。
在本秘籍中,我们将研究读取文本数据并使用各种数据源。`torchtext`可以从文本文件,CSV/TSV 文件,JSON 文件和目录中读取数据,并将其转换为数据集。 数据集是已预处理的数据块,可读取到内存中,并可由其他数据结构使用。
# 做好准备
我们将使用此食谱的新闻分类数据集,您可以从[这里](https://github.com/jibinmathew69/PyTorch1.0-Tutorial/tree/master/NewsClassification)下载该数据集。
我们将使用此秘籍的新闻分类数据集,您可以从[这里](https://github.com/jibinmathew69/PyTorch1.0-Tutorial/tree/master/NewsClassification)下载该数据集。
`.csv`文件中包含以下几列:
......@@ -199,7 +199,7 @@ pip install torchtext
# 怎么做...
在此配方中,我们将读取有毒评论数据集,该数据集存储为一组`.csv`文件:
在此秘籍中,我们将读取有毒评论数据集,该数据集存储为一组`.csv`文件:
1. 我们将从导入开始:
......@@ -249,13 +249,13 @@ pip install torchtext
>>Review.build_vocab(train, min_freq=2)
```
通过此配方,我们定义了数据集的格式。
通过此秘籍,我们定义了数据集的格式。
# 这个怎么运作...
我们使用`torchtext`中的`TabularDataset`模块读取 CSV 文件,该文件也可以用于读取 TSV,JSON 和 Python 字典中的输入,这些字典定义了列的数据集。 然后,我们定义了一个元组数组,其中每个元组都是一对列和`Field`对象(定义要应用的文本转换),但是在最终数据集中不需要特定的列。 然后,我们将在 ID 列中看到的该列的相应`Field`对象设置为`None`
在此配方中,我们使用了新闻分类数据集。 我们在其中一个文本列中应用了`Review`字段,并在其余列中应用了`Label`字段。 对于`test_datafield`,我们将具有新闻内容,因此对于`content`列,我们应用了`Review`字段,并完全删除了`id`列。 然后,我们在`TabularDataset`中使用`splits`方法,并将其传递到训练和验证文件所在的根文件夹路径中。 我们还使用`train``valid`参数传入了训练和验证文件的文件名。
在此秘籍中,我们使用了新闻分类数据集。 我们在其中一个文本列中应用了`Review`字段,并在其余列中应用了`Label`字段。 对于`test_datafield`,我们将具有新闻内容,因此对于`content`列,我们应用了`Review`字段,并完全删除了`id`列。 然后,我们在`TabularDataset`中使用`splits`方法,并将其传递到训练和验证文件所在的根文件夹路径中。 我们还使用`train``valid`参数传入了训练和验证文件的文件名。
我们将文件格式指定为`csv`,并通过将`skip_header`设置为`True`以及`fields`参数中的必需列来删除标题行,并且对数据集进行了相同的测试。 最后,我们在`Fields`对象中调用了`build_vocab()`方法,以建立可能的单词库,在数据集中的出现次数最少为两次。 不在词汇表中的单词将在验证和测试集中分配一个未知标签。
......@@ -269,11 +269,11 @@ pip install torchtext
# 开发迭代器
迭代器用于从数据集中加载一批数据。 它们提供了使加载数据和将数据移动到适当设备的方法更加容易。 我们可以使用这些迭代器对象遍历历元时对数据进行迭代。 在本食谱中,我们将从数据集中开发这些迭代器。 您将需要完成“开发数据集”配方中的步骤,因为我们将在此处使用该配方中的`Dataset`对象。
迭代器用于从数据集中加载一批数据。 它们提供了使加载数据和将数据移动到适当设备的方法更加容易。 我们可以使用这些迭代器对象遍历历元时对数据进行迭代。 在本秘籍中,我们将从数据集中开发这些迭代器。 您将需要完成“开发数据集”秘籍中的步骤,因为我们将在此处使用该秘籍中的`Dataset`对象。
# 怎么做...
在此配方中,我们将数据集转换为迭代器,以便在每个纪元准备好要迭代的适当批量:
在此秘籍中,我们将数据集转换为迭代器,以便在每个纪元准备好要迭代的适当批量:
1. 我们将从导入开始:
......@@ -305,7 +305,7 @@ pip install torchtext
sort_within_batch=False)
```
通过此配方,我们为训练,测试和验证数据集创建了迭代器。
通过此秘籍,我们为训练,测试和验证数据集创建了迭代器。
# 这个怎么运作...
......@@ -329,11 +329,11 @@ pip install torchtext
![](img/c4fc9f6e-bc00-4e90-a9e6-00637c82c64d.png)
在这里,我们能够从`king`向量中减去`man`向量,并将其与`woman`向量相加,所得向量将接近该向量`Queen`的表示形式。 我们将在本食谱中探讨此实现。
在这里,我们能够从`king`向量中减去`man`向量,并将其与`woman`向量相加,所得向量将接近该向量`Queen`的表示形式。 我们将在本秘籍中探讨此实现。
# 怎么做...
在此配方中,我们将对`torchtext`使用预训练的嵌入:
在此秘籍中,我们将对`torchtext`使用预训练的嵌入:
1. 我们将从导入开始:
......@@ -353,17 +353,17 @@ pip install torchtext
>>Review.build_vocab(train, min_freq=2, vectors=vec)
```
通过此配方,我们已加载了预训练的单词嵌入。
通过此秘籍,我们已加载了预训练的单词嵌入。
# 这个怎么运作...
`torchtext`具有用于处理嵌入的`vocab`模块。 我们可以通过在此食谱中提及需要的嵌入名称来下载预训练的嵌入。 我们使用了预先训练的 GloVe(GloVe 是词向量技术)模型,该模型使用 60 亿个​​令牌和 100 个嵌入维向量`glove.6B.50d`进行训练。
`torchtext`具有用于处理嵌入的`vocab`模块。 我们可以通过在此秘籍中提及需要的嵌入名称来下载预训练的嵌入。 我们使用了预先训练的 GloVe(GloVe 是词向量技术)模型,该模型使用 60 亿个​​令牌和 100 个嵌入维向量`glove.6B.50d`进行训练。
然后,我们从缓存位置加载向量。 如果所需的嵌入不在高速缓存中,那么它将自动从 URL 下载并作为嵌入向量传递。 然后,我们使用`Review`字段对象的`build_vocab`方法从这些预训练的嵌入中建立词汇表,然后将其添加到训练数据的词汇表中。
# 还有更多...
我们还可以使用训练数据中的预训练嵌入词汇表-例如,我们可以使用使用 gensim 创建的嵌入向量作为嵌入向量。 我们还可以使用`torch.nn`模块创建嵌入; 我们将在下一个食谱中了解如何执行此操作。
我们还可以使用训练数据中的预训练嵌入词汇表-例如,我们可以使用使用 gensim 创建的嵌入向量作为嵌入向量。 我们还可以使用`torch.nn`模块创建嵌入; 我们将在下一个秘籍中了解如何执行此操作。
# 也可以看看
......@@ -375,7 +375,7 @@ pip install torchtext
# 怎么做...
在此配方中,我们将定义 LSTM 分类器:
在此秘籍中,我们将定义 LSTM 分类器:
1. 我们将从导入开始:
......@@ -460,7 +460,7 @@ return self.fc(hidden)
>>model = LSTMClassifier(EMBEDDING_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT)
```
通过此配方,我们创建了一个 LSTM 模型。
通过此秘籍,我们创建了一个 LSTM 模型。
# 这个怎么运作...
......@@ -482,11 +482,11 @@ return self.fc(hidden)
# 多层 LSTM
我们在先前的食谱中介绍了简单的 LSTM。 在本食谱中,我们将为多层 LSTM 升级该简单的 LSTM 定义。 您需要完成“构建 LSTM 网络”配方才能了解此配方
我们在先前的秘籍中介绍了简单的 LSTM。 在本秘籍中,我们将为多层 LSTM 升级该简单的 LSTM 定义。 您需要完成“构建 LSTM 网络”秘籍才能了解此秘籍
# 怎么做...
配方是基于 LSTM 配方的修改。
秘籍是基于 LSTM 秘籍的修改。
1. 首先,我们将更新该类的`__init__()`
......@@ -529,17 +529,17 @@ class MultiLSTMClassifier(nn.Module):
>>model = MultiLSTMClassifier(EMBEDDING_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT, NUM_LAYERS)
```
通过此配方,我们修改了用于多层 LSTM 的网络。
通过此秘籍,我们修改了用于多层 LSTM 的网络。
# 这个怎么运作...
在此配方中,我们在构造函数中添加了`num_layers`和参数以控制模型中 LSTM 的层数,并将其作为关键字参数`num_layers`传递给 LSTM 定义。
在此秘籍中,我们在构造函数中添加了`num_layers`和参数以控制模型中 LSTM 的层数,并将其作为关键字参数`num_layers`传递给 LSTM 定义。
然后,在`forward()`方法中,由于隐藏状态的形状是`[num_layers * num_directions, batch, hidden_dim]`(默认情况下`num_direction``1`),因此我们仅使用`hidden[-1]`从最后一个 LSTM 层获取了隐藏状态。 这意味着`hidden[-1]`给出了最后一层的隐藏状态。 通过这样做,我们可以选择`num_layers`作为超参数。 来自较低层的隐藏状态输出作为较高状态的输入传递。
# 还有更多...
在本配方中,我们仅考虑了最后一个 LSTM 层的隐藏状态。 但是,可能存在使用所有隐藏层的复杂架构。 有一个`dropout`参数,可用于在多层 LSTM 的各层之间施加丢弃。
在本秘籍中,我们仅考虑了最后一个 LSTM 层的隐藏状态。 但是,可能存在使用所有隐藏层的复杂架构。 有一个`dropout`参数,可用于在多层 LSTM 的各层之间施加丢弃。
# 也可以看看
......@@ -547,15 +547,15 @@ class MultiLSTMClassifier(nn.Module):
# 双向 LSTM
配方以多层 LSTM 配方为基础。 在正常的 LSTM 中,LSTM 会从头到尾读取输入序列。 但是,在双向 LSTM 中,有第二个 LSTM 从最后到第一个读取序列,即反向 RNN。 当当前时间戳的预测取决于序列中进一步输入时,这种类型的 LSTM 可以提高模型性能。 考虑示例“我看过漫画”和“我昨天看过漫画”。 在这种情况下,基于将来出现的令牌,相同的令牌(即`read`)具有不同的含义。 我们将在本食谱中探讨其实现。
秘籍以多层 LSTM 秘籍为基础。 在正常的 LSTM 中,LSTM 会从头到尾读取输入序列。 但是,在双向 LSTM 中,有第二个 LSTM 从最后到第一个读取序列,即反向 RNN。 当当前时间戳的预测取决于序列中进一步输入时,这种类型的 LSTM 可以提高模型性能。 考虑示例“我看过漫画”和“我昨天看过漫画”。 在这种情况下,基于将来出现的令牌,相同的令牌(即`read`)具有不同的含义。 我们将在本秘籍中探讨其实现。
# 做好准备
配方建立在“多层 LSTM”配方的基础上,因此在尝试该配方之前,请务必先完成该配方
秘籍建立在“多层 LSTM”秘籍的基础上,因此在尝试该秘籍之前,请务必先完成该秘籍
# 怎么做...
在此配方中,我们将修改“多层 LSTM”配方中的类定义,使其成为双向 LSTM:
在此秘籍中,我们将修改“多层 LSTM”秘籍中的类定义,使其成为双向 LSTM:
1. 我们将`bidirectional`参数设置为`True`
......@@ -599,11 +599,11 @@ class BiLSTMClassifier(nn.Module):
>>model = BiLSTMClassifier(EMBEDDING_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT, NUM_LAYERS)
```
通过此配方,我们修改了网络,使其现在是双向 LSTM。
通过此秘籍,我们修改了网络,使其现在是双向 LSTM。
# 这个怎么运作...
在此配方中,我们在 LSTM 定义中将`bidirectional`标志设置为`True`。 我们将前向和后向 LSTM 的隐藏状态串联起来,并将它们传递到全连接层中。 因此,全连接层的输入尺寸增加了一倍,以适应前向和后向隐藏状态张量。
在此秘籍中,我们在 LSTM 定义中将`bidirectional`标志设置为`True`。 我们将前向和后向 LSTM 的隐藏状态串联起来,并将它们传递到全连接层中。 因此,全连接层的输入尺寸增加了一倍,以适应前向和后向隐藏状态张量。
`forward()`方法中,我们使用`torch.cat()`连接了向前和向后隐藏状态,并使用了向前和向后 LSTM 的最后一个隐藏状态。 在 PyTorch 中,隐藏状态堆叠为`[forward_layer_0, backward_layer_0, forward_layer_1, backward_layer_1, ..., forward_layer_n, backward_layer_n]`,因此所需的张量为`hidden[-2,:,:], hidden[-1,:,:]`。 串联后,在挤出额外的尺寸后,我们将隐藏的向量传递到全连接层中。
......
......@@ -12,7 +12,7 @@
4. 在可用于任务的训练数据上训练分类器层。
5. 微调超参数并根据需要解冻更多层。
在本章中,我们将介绍以下食谱
在本章中,我们将介绍以下秘籍
* 调整预训练模型
* 实施模型训练
......@@ -23,19 +23,19 @@
# 技术要求
要完成此食谱,我们需要 Torch 1.2 或更高版本,强烈建议我们使用支持 CUDA 的设备。
要完成此秘籍,我们需要 Torch 1.2 或更高版本,强烈建议我们使用支持 CUDA 的设备。
# 调整预训练模型
在本食谱中,我们将采用经过预训练的 ResNet 模型,并修改最后一层以适合我们所需的输出。 与 ImageNet 数据集中用于训练 ResNet-50 模型的类的数量相比,我们只需要两个类。 我们将修改 ResNet 模型的最后一个池化层和全连接分类器。 我们将进一步将模型的训练限制为仅添加新添加的分类器单元,并且将保留所有其余层以免更新权重。 这称为冻结模型。 让我们看一下如何实现配方
在本秘籍中,我们将采用经过预训练的 ResNet 模型,并修改最后一层以适合我们所需的输出。 与 ImageNet 数据集中用于训练 ResNet-50 模型的类的数量相比,我们只需要两个类。 我们将修改 ResNet 模型的最后一个池化层和全连接分类器。 我们将进一步将模型的训练限制为仅添加新添加的分类器单元,并且将保留所有其余层以免更新权重。 这称为冻结模型。 让我们看一下如何实现秘籍
# 做好准备
食谱要求我们下载特定的数据集。 我们将从[这里](https://www.kaggle.com/paultimothymooney/chest-xray-pneumonia/download)获取数据集。 为了完成此食谱,您的 PyTorch 安装应为 1.2 或更高版本,强烈建议您使用支持 CUDA 的设备。
秘籍要求我们下载特定的数据集。 我们将从[这里](https://www.kaggle.com/paultimothymooney/chest-xray-pneumonia/download)获取数据集。 为了完成此秘籍,您的 PyTorch 安装应为 1.2 或更高版本,强烈建议您使用支持 CUDA 的设备。
# 怎么做...
在本食谱中,我们将训练我们的神经网络,并从在 ImageNet 数据集上训练的预训练模型 ResNet-50 开始:
在本秘籍中,我们将训练我们的神经网络,并从在 ImageNet 数据集上训练的预训练模型 ResNet-50 开始:
1. 现在,我们将从导入开始编写 Python 代码:
......@@ -96,21 +96,21 @@ model.fc = nn.Sequential(
return model
```
有了这个配方,我们已经准备好要获取模型的功能。
有了这个秘籍,我们已经准备好要获取模型的功能。
# 这个怎么运作...
在此配方中,我们定义了一个子模块`AdaptiveConcatPool2d`,该子模块在平均 2D 池和最大 2D 池之间执行级联,以便从卷积层到具有最大特征信息的全连接层的平滑过渡。
在此秘籍中,我们定义了一个子模块`AdaptiveConcatPool2d`,该子模块在平均 2D 池和最大 2D 池之间执行级联,以便从卷积层到具有最大特征信息的全连接层的平滑过渡。
然后,我们定义了`get_model()`函数,该函数首先下载 ResNet-50 模型(本地不可用)并冻结该模型的权重。 通过冻结权重,较低的卷积层不会更新。 然后,我们用`AdaptiveConcatPool2d`层替换了平均池化层,并为两个可用的类添加了具有两个输出单元的全连接分类器。 我们最终返回了带有冻结的 ResNet 层的模型。
# 实施模型训练
在本食谱中,我们将实现一个在单个时期内训练模型的功能。 此功能进一步记录模型的训练指标并将其绘制到 TensorBoard 上。 我们将传入模型,训练数据,优化器和模型训练准则,并将返回训练损失。
在本秘籍中,我们将实现一个在单个时期内训练模型的功能。 此功能进一步记录模型的训练指标并将其绘制到 TensorBoard 上。 我们将传入模型,训练数据,优化器和模型训练准则,并将返回训练损失。
# 怎么做...
我们将在此食谱中实现训练功能:
我们将在此秘籍中实现训练功能:
1. 定义训练功能:
......@@ -147,11 +147,11 @@ return model
return total_loss/len(train_loader)
```
通过此配方,我们完成了训练功能。
通过此秘籍,我们完成了训练功能。
# 这个怎么运作...
在此配方中,我们定义了执行训练时期的功能。 在开始训练过程之前,我们使用`.train()`将模型设置为训练模式,并将训练损失设置为`0`。 然后,我们遍历训练数据并将输入数据点及其对应的标签移到可用设备(CPU 或 GPU)上。
在此秘籍中,我们定义了执行训练时期的功能。 在开始训练过程之前,我们使用`.train()`将模型设置为训练模式,并将训练损失设置为`0`。 然后,我们遍历训练数据并将输入数据点及其对应的标签移到可用设备(CPU 或 GPU)上。
然后,我们清除梯度,进行模型预测,然后将其传递给准则以确定训练损失。 然后,我们对损失进行了反向传播,并更新了模型的权重。 由于模型是冻结的,因此它仅更新模型中分类器的权重。
......@@ -159,11 +159,11 @@ return model
# 实施模型测试
在此配方中,我们将定义一个函数以在一个时期内根据验证数据测试模型。 此功能还将测试指标记录到 TensorBoard 上。 我们还将添加实用程序功能,通过绘制图像并以可读的方式标记这些图像来记录模型中的一些错误分类。
在此秘籍中,我们将定义一个函数以在一个时期内根据验证数据测试模型。 此功能还将测试指标记录到 TensorBoard 上。 我们还将添加实用程序功能,通过绘制图像并以可读的方式标记这些图像来记录模型中的一些错误分类。
# 怎么做...
在本食谱中,我们将实现模型测试以及实用程序功能:
在本秘籍中,我们将实现模型测试以及实用程序功能:
1. 首先,我们将定义一个将张量转换为图像的函数:
......@@ -222,21 +222,21 @@ return model
return total_loss, accuracy
```
通过此配方,我们完成了测试功能。
通过此秘籍,我们完成了测试功能。
# 这个怎么运作...
在此配方中,我们编写了逆归一化函数以撤消在将图像转换为具有 ImageNet 统计信息的张量时建立的归一化。 我们还定义了`misclassified_images()`方法,用于记录预测错误的图像。 然后使用`SummaryWriter`对象中的`add_image()`方法将分类错误的图像添加到 TensorBoard 中,该方法将输入图像名称,图像和计数器。
在此秘籍中,我们编写了逆归一化函数以撤消在将图像转换为具有 ImageNet 统计信息的张量时建立的归一化。 我们还定义了`misclassified_images()`方法,用于记录预测错误的图像。 然后使用`SummaryWriter`对象中的`add_image()`方法将分类错误的图像添加到 TensorBoard 中,该方法将输入图像名称,图像和计数器。
然后,我们定义了`test()`方法,该方法在模型的验证数据集上运行验证,并使用`add_scalar()`方法记录测试损失和准确率,就像在训练函数中一样。 最后,我们在验证数据集上返回了测试损失和模型准确率。
# 加载数据集
在此配方中,我们将加载肺炎数据集并将其转换为张量。 该模型需要张量形式的数据,因此我们将需要对图像进行预处理以为其提供所需的数据。 我们将执行数据扩充以增加数据集的大小。 在将其输入模型之前,我们还将根据 ImageNet 数据集执行图像归一化。
在此秘籍中,我们将加载肺炎数据集并将其转换为张量。 该模型需要张量形式的数据,因此我们将需要对图像进行预处理以为其提供所需的数据。 我们将执行数据扩充以增加数据集的大小。 在将其输入模型之前,我们还将根据 ImageNet 数据集执行图像归一化。
# 怎么做...
在此配方中,我们将加载数据集:
在此秘籍中,我们将加载数据集:
1. 首先,我们将定义转换:
......@@ -329,11 +329,11 @@ return model
>>LABEL = dict((v,k) for k,v in data['train'].class_to_idx.items())
```
有了这个配方,我们就可以准备好数据集。
有了这个秘籍,我们就可以准备好数据集。
# 这个怎么运作...
在此配方中,我们定义了训练,验证和测试数据集中图像所需的转换。 根据数据集选择变换,并且归一化变换中的值来自 ImageNet 统计信息。 然后,我们定义了数据集路径,模型名称,批量大小和日志目录。 然后,我们使用`datasets.ImageFolder()`方法根据文件夹名称加载数据,并为每个数据集创建一个迭代器。
在此秘籍中,我们定义了训练,验证和测试数据集中图像所需的转换。 根据数据集选择变换,并且归一化变换中的值来自 ImageNet 统计信息。 然后,我们定义了数据集路径,模型名称,批量大小和日志目录。 然后,我们使用`datasets.ImageFolder()`方法根据文件夹名称加载数据,并为每个数据集创建一个迭代器。
请注意,我们翻转了验证数据集和测试数据集目录。 这是因为给定数据集的验证数据集确实很小,因此我们将测试数据集用于验证数据集。
......@@ -341,11 +341,11 @@ return model
# 定义 TensorBoard 作者
在此配方中,我们将创建一个写入 TensorBoard 的对象。 我们使用`SummaryWriter`对象写入 TensorBoard。 我们可以使用 TensorBoard 编写标量值,绘图图和绘图图像以及其他功能。 我们将定义一个返回 TensorBoard `SummaryWriter`对象以记录我们的模型指标的函数。
在此秘籍中,我们将创建一个写入 TensorBoard 的对象。 我们使用`SummaryWriter`对象写入 TensorBoard。 我们可以使用 TensorBoard 编写标量值,绘图图和绘图图像以及其他功能。 我们将定义一个返回 TensorBoard `SummaryWriter`对象以记录我们的模型指标的函数。
# 做好准备
食谱要求我们安装 TensorBoard 库。
秘籍要求我们安装 TensorBoard 库。
我们需要安装 TensorBoard 夜间版本:
......@@ -353,11 +353,11 @@ return model
pip install tb-nightly
```
这样,我们准备实施该食谱
这样,我们准备实施该秘籍
# 怎么做...
在此食谱中,我们将创建编写器对象以将数据登录到 TensorBoard。
在此秘籍中,我们将创建编写器对象以将数据登录到 TensorBoard。
1. 我们将在命令行中输入以下内容来加载 TensorBoard:
......@@ -397,7 +397,7 @@ tensorboard --logdir=log_dir/ --port 6006
# 这个怎么运作...
在本食谱中,我们首先从命令行加载 TensorBoard 以从`logdir/`目录中读取。 即使目录不存在,TensorBoard 也不抛出错误,而是等待目录出现,因此传递正确的目录很重要。
在本秘籍中,我们首先从命令行加载 TensorBoard 以从`logdir/`目录中读取。 即使目录不存在,TensorBoard 也不抛出错误,而是等待目录出现,因此传递正确的目录很重要。
然后,我们将 TensorBoard 导入代码中,并定义了`tb_writer()`函数,该函数返回一个新的`SummaryWriter`对象。 我们向`writer`对象传递了 TensorBoard 日志要保存到的目录名称,并在时间戳`timestr`的帮助下,确保每个编写器都有一个唯一的目录来写入。
......@@ -405,11 +405,11 @@ tensorboard --logdir=log_dir/ --port 6006
# 训练模型和解冻层
在本食谱中,我们将为数据集的预定义迭代次数完成模型训练。 我们将在模型训练期间保存最佳模型。 一旦针对给定的时期数训练了模型,我们将使用最佳模型的权重加载模型。 然后,我们将解冻模型的先前冻结的 ResNet 层,并训练模型以较低的学习速率微调权重。
在本秘籍中,我们将为数据集的预定义迭代次数完成模型训练。 我们将在模型训练期间保存最佳模型。 一旦针对给定的时期数训练了模型,我们将使用最佳模型的权重加载模型。 然后,我们将解冻模型的先前冻结的 ResNet 层,并训练模型以较低的学习速率微调权重。
# 怎么做...
在本食谱中,我们将完成模型训练。
在本秘籍中,我们将完成模型训练。
1. 将模型移至可用设备:
......@@ -559,11 +559,11 @@ Epoch | Training Loss | Test Loss | Accuracy |
图 7:准确率得分
通过此配方,我们已经训练了模型并在 TensorBoard 中可视化了其结果。
通过此秘籍,我们已经训练了模型并在 TensorBoard 中可视化了其结果。
# 这个怎么运作...
在此配方中,我们创建了模型并将其移至可用设备,并分别使用负对数损耗和 Adam 作为我们的标准和优化器。 `train_epochs()`方法用于在定义的时期范围内训练模型。 在每个时期结束时,我们使用`writer.flush()`方法来确保所有未决事件已写入磁盘。 最后,我们使用`writer.close()`刷新关闭编写器。 我们还在此功能中保存了最佳模型,以供日后重新加载。
在此秘籍中,我们创建了模型并将其移至可用设备,并分别使用负对数损耗和 Adam 作为我们的标准和优化器。 `train_epochs()`方法用于在定义的时期范围内训练模型。 在每个时期结束时,我们使用`writer.flush()`方法来确保所有未决事件已写入磁盘。 最后,我们使用`writer.close()`刷新关闭编写器。 我们还在此功能中保存了最佳模型,以供日后重新加载。
然后,我们从到目前为止的训练中重新加载了最佳模型,并对其进行了冻结以进行微调。 解冻后,所有模型参数均可用于训练。 我们将优化器设置为较低的学习率,对该未冻结的模型进行了更多的训练,并记录了模型的性能。 我们看到,通过微调,我们的模型表现更好。
......@@ -573,7 +573,7 @@ Epoch | Training Loss | Test Loss | Accuracy |
# 还有更多...
在此配方中,我们可以进一步编写一个函数来确定测试数据集指标,使用`add_histogram()`方法将直方图添加到 TensorBoard 中,并使用其他预训练的网络训练模型。
在此秘籍中,我们可以进一步编写一个函数来确定测试数据集指标,使用`add_histogram()`方法将直方图添加到 TensorBoard 中,并使用其他预训练的网络训练模型。
# 也可以看看
......
......@@ -20,7 +20,7 @@ GAN 中的两个模型称为生成器和判别器,其中生成器负责创建
从理论上讲,生成器和判别器达到平衡,其中生成器已捕获了生成的伪图像中真实图像的所有特征,而从进一步的训练中没有任何收获。 类似地,鉴别者只能以 50% 的概率猜测图像是伪造的还是真实的,因为这两个图像就其性质而言完全无法区分。 在那个状态下,GAN 已经收敛。 然而,实际上,这种状态很难实现。 在本章中,我们将探讨 GAN 的概念以及 PyTorch 中各种 GAN 的实现。
在本章中,我们将介绍以下食谱
在本章中,我们将介绍以下秘籍
* 创建一个 DCGAN 生成器
* 创建 DCGAN 判别器
......@@ -30,23 +30,23 @@ GAN 中的两个模型称为生成器和判别器,其中生成器负责创建
# 技术要求
强烈建议,对于本章中实现的配方,代码应在具有 NVIDIA GPU 且启用了 CUDA 和 CUDNN 的计算机上运行,​​因为本章中的配方需要大量计算。
强烈建议,对于本章中实现的秘籍,代码应在具有 NVIDIA GPU 且启用了 CUDA 和 CUDNN 的计算机上运行,​​因为本章中的秘籍需要大量计算。
# 创建一个 DCGAN 生成器
在本食谱及其后续食谱中,我们将实现 DCGAN。 DCGAN 代表“深度卷积 GAN”; 与香草 GAN 相比,它们有很大的改进。 在 DCGAN 中,我们使用卷积神经网络,而不是香草 GAN 中的全连接网络。 在第 3 章,“用于计算机视觉的卷积神经网络”中,我们看到了第 2 章“处理神经网络”中全连接分类器是什么样,是该领域的一项改进; DCGAN 与香草 GAN 的情况相同。 在 DCGAN 中,我们将使用批量归一化,这是一种技术,它可以将作为输入输入到下一层的层的输出归一化。 批量归一化允许网络的每一层独立于其他层进行学习,从而减少了协变量偏移。
在本秘籍及其后续秘籍中,我们将实现 DCGAN。 DCGAN 代表“深度卷积 GAN”; 与香草 GAN 相比,它们有很大的改进。 在 DCGAN 中,我们使用卷积神经网络,而不是香草 GAN 中的全连接网络。 在第 3 章,“用于计算机视觉的卷积神经网络”中,我们看到了第 2 章“处理神经网络”中全连接分类器是什么样,是该领域的一项改进; DCGAN 与香草 GAN 的情况相同。 在 DCGAN 中,我们将使用批量归一化,这是一种技术,它可以将作为输入输入到下一层的层的输出归一化。 批量归一化允许网络的每一层独立于其他层进行学习,从而减少了协变量偏移。
批量归一化是通过缩放来实现的,以使平均值为 0,方差为 1。在此配方中,我们将生成类似于 MNIST 数据集的手写数字,其中包含来自噪声向量的数据。 我们将扩展此噪声向量,将其转换为 2D 矩阵,最后将其转换为`28 x 28`黑白图像。 为了增加高度和宽度,我们必须执行与卷积操作相反的操作,这称为反卷积。 我们将在使用卷积执行分类任务时执行此操作。 在执行反卷积时,我们将增加高度和宽度,同时减少通道数。
批量归一化是通过缩放来实现的,以使平均值为 0,方差为 1。在此秘籍中,我们将生成类似于 MNIST 数据集的手写数字,其中包含来自噪声向量的数据。 我们将扩展此噪声向量,将其转换为 2D 矩阵,最后将其转换为`28 x 28`黑白图像。 为了增加高度和宽度,我们必须执行与卷积操作相反的操作,这称为反卷积。 我们将在使用卷积执行分类任务时执行此操作。 在执行反卷积时,我们将增加高度和宽度,同时减少通道数。
以下是我们的 DCGAN 生成器的架构图:
![](img/89189246-b3a7-49dc-acc5-78bc00c5f9b7.png)
请注意,我们将使用第 3 章,“用于计算机视觉的卷积神经网络”中的概念,因此再次阅读这些食谱将非常有用。
请注意,我们将使用第 3 章,“用于计算机视觉的卷积神经网络”中的概念,因此再次阅读这些秘籍将非常有用。
# 怎么做...
在此配方中,我们将实现 GAN 网络的生成器端:
在此秘籍中,我们将实现 GAN 网络的生成器端:
1.我们将从进口开始:
......@@ -114,7 +114,7 @@ def forward(self, input):
# 这个怎么运作...
在此食谱中,我们进行了变换以将图像转换为张量并对其进行归一化,就像在第 3 章,“用于计算机视觉的卷积神经网络”中所做的一样。 然后,我们确定了机器上的设备:CPU 或 GPU。 然后,我们定义了从`nn.Module`类继承的`Generator_model`类,就像在所有以前的架构中所做的一样。
在此秘籍中,我们进行了变换以将图像转换为张量并对其进行归一化,就像在第 3 章,“用于计算机视觉的卷积神经网络”中所做的一样。 然后,我们确定了机器上的设备:CPU 或 GPU。 然后,我们定义了从`nn.Module`类继承的`Generator_model`类,就像在所有以前的架构中所做的一样。
在构造函数中,我们传递了`z_dim`参数,这是我们的噪声向量大小。 然后,我们定义了一个全连接单元`self.fc`,我们将噪声向量传递给该单元,并为其提供了`256 * 7 * 7`输出。 然后,我们定义了一个称为`self.gen``nn.Sequential`单元,其中包含用于定义生成器的关键组件。 我们使用 PyTorch 中提供的`nn.ConvTranspose2d``nn.BatchNorm2d``nn.LeakyReLU`使用一组反卷积,批量规范化和激活层。 `ConvTranspose2d`接受输入通道,输出通道,内核大小,步幅和填充等参数。 `BatchNorm2d`接受上一层的要素/通道数作为其参数,而 LeakyReLU 接受负斜率的角度。
......@@ -128,7 +128,7 @@ def forward(self, input):
# 创建 DCGAN 判别器
在本食谱中,我们将探讨 GAN 网络的鉴别方。 基本上,判别器是在两个类别之间进行分类的分类器,即根据给定图像是来自数据集的真实图像还是由生成器网络生成的伪图像。 正是基于来自判别器网络的反馈,生成器学会了创建更好的图像,以试图使判别器误以为来自生成器的图像是真实的。 现在,在 DCGAN 中,将使用卷积神经网络构建判别器。
在本秘籍中,我们将探讨 GAN 网络的鉴别方。 基本上,判别器是在两个类别之间进行分类的分类器,即根据给定图像是来自数据集的真实图像还是由生成器网络生成的伪图像。 正是基于来自判别器网络的反馈,生成器学会了创建更好的图像,以试图使判别器误以为来自生成器的图像是真实的。 现在,在 DCGAN 中,将使用卷积神经网络构建判别器。
以下是我们的判别器的架构图:
......@@ -136,11 +136,11 @@ def forward(self, input):
# 准备好
在本食谱中,我们将严重依赖第 3 章,“用于计算机视觉的卷积神经网络”的食谱,因此最好快速浏览 第 3 章,“用于计算机视觉的卷积神经网络”。
在本秘籍中,我们将严重依赖第 3 章,“用于计算机视觉的卷积神经网络”的秘籍,因此最好快速浏览 第 3 章,“用于计算机视觉的卷积神经网络”。
# 怎么做...
在此配方中,我们将构建 GAN 的判别器端:
在此秘籍中,我们将构建 GAN 的判别器端:
1.我们将从进口开始:
......@@ -195,7 +195,7 @@ def forward(self, input):
# 这个怎么运作...
在本食谱中,我们定义了一个分类器; 使用`nn.Sequential()`定义卷积,激活和批量规范化单元的数组; 并且还定义了最后一个全连接层,该层采用平坦的张量并给出通过 Sigmoid 层的单个输出。 由于只有两个类,因此我们最后使用了 Sigmoid 层。 输入是尺寸为`1 x 28 x 28`的图像张量,并经过第一卷积单元以给出尺寸为`32 x 14 x 14`的输出张量。 第二个卷积层使它成为`64 x 7 x 7`张量,然后从那里变成`128 x 4 x 4`。 之后,我们将拉平并使张量穿过全连接层。
在本秘籍中,我们定义了一个分类器; 使用`nn.Sequential()`定义卷积,激活和批量规范化单元的数组; 并且还定义了最后一个全连接层,该层采用平坦的张量并给出通过 Sigmoid 层的单个输出。 由于只有两个类,因此我们最后使用了 Sigmoid 层。 输入是尺寸为`1 x 28 x 28`的图像张量,并经过第一卷积单元以给出尺寸为`32 x 14 x 14`的输出张量。 第二个卷积层使它成为`64 x 7 x 7`张量,然后从那里变成`128 x 4 x 4`。 之后,我们将拉平并使张量穿过全连接层。
# 也可以看看
......@@ -203,7 +203,7 @@ def forward(self, input):
# 训练 DCGAN 模型
我们在前两个配方中定义了生成器,即“创建 DCGan 生成器”和“创建 DCGAN 判别器”。 在本食谱中,我们将继续训练 GAN 模型。 请记住,生成器的目标是创建与数据集尽可能相似的图像,而判别器的目标是区分真实图像和生成的图像。 从理论上讲,生成器将捕获数据集中图像的所有特征,并且无法学习更多信息,而判别器只能猜测图像是真实的还是生成的。 在本食谱中,我们将通过整合到目前为止已经创建的生成器和判别器来完成 DCGANs 模型的训练。
我们在前两个秘籍中定义了生成器,即“创建 DCGan 生成器”和“创建 DCGAN 判别器”。 在本秘籍中,我们将继续训练 GAN 模型。 请记住,生成器的目标是创建与数据集尽可能相似的图像,而判别器的目标是区分真实图像和生成的图像。 从理论上讲,生成器将捕获数据集中图像的所有特征,并且无法学习更多信息,而判别器只能猜测图像是真实的还是生成的。 在本秘籍中,我们将通过整合到目前为止已经创建的生成器和判别器来完成 DCGANs 模型的训练。
# 准备好
......@@ -217,7 +217,7 @@ pip install torchsummary
# 怎么做...
在此食谱中,我们将完成 GAN 训练:
在此秘籍中,我们将完成 GAN 训练:
1. 一,进口:
......@@ -565,11 +565,11 @@ Epoch : | 005 / 050 |
以前我们已经看到,使用 GAN,生成器和判别器相互竞争,并且这样做可以产生越来越好的图像。 但是,从理论上讲,它们达到了生成器已捕获真实图像的所有特征的程度,并且生成器无法学习。 同样,鉴别者只能猜测给定图像是真实的还是伪造的,成功机会为 50/50。 在这一点上,据说 GAN 已经收敛。
现在,任何方面的改善都会导致另一面的结果降低,这是**零和**状态或**纳什平衡**; 但是在实践中很难实现,因为生成器和判别器都在不断变化,因此检查 GAN 性能的最佳方法是通过图形和图表。 在本食谱中,我们将快速了解可视化。
现在,任何方面的改善都会导致另一面的结果降低,这是**零和**状态或**纳什平衡**; 但是在实践中很难实现,因为生成器和判别器都在不断变化,因此检查 GAN 性能的最佳方法是通过图形和图表。 在本秘籍中,我们将快速了解可视化。
# 准备好
对于此食谱,您必须具有`matplotlib`和`numpy`库,可以使用`pip`如下安装它们:
对于此秘籍,您必须具有`matplotlib`和`numpy`库,可以使用`pip`如下安装它们:
```py
pip install matplotlib
......@@ -580,7 +580,7 @@ pip install numpy
# 怎么做...
在此配方中,我们将快速绘制 GAN 中的图形和图像:
在此秘籍中,我们将快速绘制 GAN 中的图形和图像:
1. 我们将从进口开始:
......@@ -642,7 +642,7 @@ pip install numpy
# 这个怎么运作...
在本食谱中,我们使用 matplotlib 绘制图形和图像。 我们使用`figure()`和`title()`方法设置图形尺寸和标题,然后使用`plot()`方法绘制发生器和判别器损耗。 我们还使用`xlabel`和`ylabel`方法添加了`x`和`y`标签。 我们还使用`legend()`方法为图添加了图例,最后使用`show()`方法显示了图。
在本秘籍中,我们使用 matplotlib 绘制图形和图像。 我们使用`figure()`和`title()`方法设置图形尺寸和标题,然后使用`plot()`方法绘制发生器和判别器损耗。 我们还使用`xlabel`和`ylabel`方法添加了`x`和`y`标签。 我们还使用`legend()`方法为图添加了图例,最后使用`show()`方法显示了图。
我们遍历训练期间保存在`image_list`中的图像,并使用 NumPy 的`transpose()`方法以所需顺序固定图像的尺寸。 `image_list`中的图像是使用`torchvision.util.make_grid()`方法生成的,我们根据噪声向量创建了生成图像的网格。
......@@ -656,7 +656,7 @@ pip install numpy
# 使用 PyTorch 集线器运行 PGGAN
在本食谱中,我们将研究**渐进 GAN**(**PGGAN**),与 DCGAN 相比它们是高级 GAN,并且能够生成逼真的图像。 PGGAN 分多个阶段训练 GAN 网络。 它具有`z`的潜在特征,并使用两个反卷积层生成`4×4`图像。 在判别器方面,网络使用两个卷积层训练生成的`4 x 4`图像。 网络稳定后,它会在判别器中再增加两个卷积层以将图像上采样到`8 x 8`,再增加两个卷积层以对图像下采样。
在本秘籍中,我们将研究**渐进 GAN**(**PGGAN**),与 DCGAN 相比它们是高级 GAN,并且能够生成逼真的图像。 PGGAN 分多个阶段训练 GAN 网络。 它具有`z`的潜在特征,并使用两个反卷积层生成`4×4`图像。 在判别器方面,网络使用两个卷积层训练生成的`4 x 4`图像。 网络稳定后,它会在判别器中再增加两个卷积层以将图像上采样到`8 x 8`,再增加两个卷积层以对图像下采样。
经过 9 个这样的级数后,生成器将生成`1024 x 1024`个图像。 PGGAN 的渐进式训练策略相对于常规 GAN 具有优势,因为它可以加快并稳定训练。 之所以如此,是因为大多数训练都是在较低的分辨率下进行的,而在网络达到各个阶段的稳定性之后,会逐渐发展为较高的分辨率。
......@@ -679,7 +679,7 @@ Nvidia 最初执行 PGGAN 的过程要花一到两个月的时间。 但是,
# 怎么做...
在此配方中,我们将从火炬中心运行 PGGAN:
在此秘籍中,我们将从火炬中心运行 PGGAN:
1. 首先,我们将设置进口:
......@@ -733,7 +733,7 @@ Nvidia 最初执行 PGGAN 的过程要花一到两个月的时间。 但是,
# 这个怎么运作...
在此配方中,我们加载了在`celebAHQ`数据集上训练的 PGGAN 预训练模型; 为此,我们使用了`torch.hub`中的`load()`方法。 然后,我们定义了创建和生成尺寸为`num_images x 512`的噪声向量所需的图像数量,因为此模型使用大小为 512 的噪声向量进行训练,所有噪声向量都由`buildNoiseData()`方法内部处理 在模型对象中可用。
在此秘籍中,我们加载了在`celebAHQ`数据集上训练的 PGGAN 预训练模型; 为此,我们使用了`torch.hub`中的`load()`方法。 然后,我们定义了创建和生成尺寸为`num_images x 512`的噪声向量所需的图像数量,因为此模型使用大小为 512 的噪声向量进行训练,所有噪声向量都由`buildNoiseData()`方法内部处理 在模型对象中可用。
`model.test()`方法生成了我们用来制作网格的图像。 钳位方法将所有值限制在`min`和`max`定义的范围内。 `.cpu()`方法将生成的图像移至 CPU,我们使用`permute`固定尺寸。 最后,`plt.imshow()`显示了我们创建的网格。
......
此差异已折叠。
......@@ -2,7 +2,7 @@
在本章中,我们将学习如何将 PyTorch 模型预测用于实际问题。 PyTorch 已从研究工具发展为可用于生产的框架,在本章中,我们将探讨一些使 PyTorch 可用于生产的功能。 部署模型意味着将模型提供给最终用户或系统。 为此,您可能需要满足多个要求,例如能够通过 Web 访问预测,快速进行预测以降低延迟或确保与其他深度学习框架的互操作性,以便开发人员可以使用正确的工具作为目标。 项目在发展。 所有这些确保了从研究到生产的更快过渡。
在本章中,我们将介绍以下食谱
在本章中,我们将介绍以下秘籍
* 使用 Flask 部署模型
* 创建一个 TorchScript
......@@ -10,15 +10,15 @@
# 技术要求
使用 Python 3.6 中的 PyTorch 1.3 已完成了本章的所有食谱
使用 Python 3.6 中的 PyTorch 1.3 已完成了本章的所有秘籍
# 使用 Flask 部署模型
在本食谱中,我们将使用 Flask 微框架部署图像分类器。 我们使用 Flask 的原因是因为它是一个易于使用的微框架,可用于构建 RESTful 微服务,它是一个非常流行的框架,并且有据可查。 我们将部署一个使用 Densenet-161 预训练模型构建的图像分类器模型,以完成此食谱
在本秘籍中,我们将使用 Flask 微框架部署图像分类器。 我们使用 Flask 的原因是因为它是一个易于使用的微框架,可用于构建 RESTful 微服务,它是一个非常流行的框架,并且有据可查。 我们将部署一个使用 Densenet-161 预训练模型构建的图像分类器模型,以完成此秘籍
# 做好准备
我们将需要为此食谱安装 Flask。 使用`pip`管理器安装`flask`
我们将需要为此秘籍安装 Flask。 使用`pip`管理器安装`flask`
```py
pip install flask
......@@ -28,7 +28,7 @@ pip install flask
# 怎么做...
我们将把这个食谱分成多个文件。 请按照以下步骤操作:
我们将把这个秘籍分成多个文件。 请按照以下步骤操作:
1. 创建一个名为`image_classifier.py`的文件。
2. 现在,我们需要进行进口:
......@@ -156,11 +156,11 @@ python imageapp.py
![](img/1f477c82-4311-4f6f-9b05-04ad7f50f4eb.png)
在此食谱中,我们使用 Flask 进行了简单的应用程序部署。
在此秘籍中,我们使用 Flask 进行了简单的应用程序部署。
# 这个怎么运作...
在本食谱中,我们使用 Flask Python 框架部署了使用 RESTful API 进行推理的模型。 我们首先创建`image_classifier.py`并从`idx_class.json`加载类名。
在本秘籍中,我们使用 Flask Python 框架部署了使用 RESTful API 进行推理的模型。 我们首先创建`image_classifier.py`并从`idx_class.json`加载类名。
在此文件中,第一个函数加载预先训练的`densenet161`模型,该模型在 ImageNet 数据集中具有 1,000 个类别的模型上进行训练; 我们将模型设置为评估模式,然后返回模型。 第二个函数将给定的输入图像转换为张量并对其进行变换。 我们使用了`PIL`中的`Image`模块来读取图像数据。 第三个功能通过将给定图像转换为张量并将其传递到模型中来进行预测。 这将返回图像中对象的名称。
......@@ -170,7 +170,7 @@ python imageapp.py
# 还有更多...
在本食谱中,我们使用`debug=True`将调试模式设置为开启,这在生产中不建议使用。 Flask 服务器的功能不足以支持生产负载。 相反,应使用`gunicorn``nginx`进行正确的部署。
在本秘籍中,我们使用`debug=True`将调试模式设置为开启,这在生产中不建议使用。 Flask 服务器的功能不足以支持生产负载。 相反,应使用`gunicorn``nginx`进行正确的部署。
# 也可以看看
......@@ -182,11 +182,11 @@ python imageapp.py
# 创建一个 TorchScript
TorchScript 为最初用 PyTorch 编写的模型提供中间表示。 这样,您就可以在高性能环境(例如 C++)中运行模型。 TorchScript 通过 PyTorch 代码创建模型的可序列化和优化版本。 使用 TorchScript 编写的代码可以加载到进程中,而无需任何 Python 依赖项。 TorchScript 提供了可用于捕获模型定义的工具,而 PyTorch 具有动态和灵活的特性,因此足以支持此定义。 可以通过两种方式创建 TorchScript:跟踪或使用脚本编译器。 在本食谱中,我们将使用跟踪和脚本编译器将 PyTorch 模型转换为 TorchScript。
TorchScript 为最初用 PyTorch 编写的模型提供中间表示。 这样,您就可以在高性能环境(例如 C++)中运行模型。 TorchScript 通过 PyTorch 代码创建模型的可序列化和优化版本。 使用 TorchScript 编写的代码可以加载到进程中,而无需任何 Python 依赖项。 TorchScript 提供了可用于捕获模型定义的工具,而 PyTorch 具有动态和灵活的特性,因此足以支持此定义。 可以通过两种方式创建 TorchScript:跟踪或使用脚本编译器。 在本秘籍中,我们将使用跟踪和脚本编译器将 PyTorch 模型转换为 TorchScript。
# 怎么做...
在此配方中,我们将创建一个 TorchScript。 请按照以下步骤操作:
在此秘籍中,我们将创建一个 TorchScript。 请按照以下步骤操作:
1. 首先,我们将编写一个简单的网络:
......@@ -373,7 +373,7 @@ def forward(self,
# 这个怎么运作...
在本食谱中,我们使用了跟踪方法来创建 TorchScript。 我们定义了一个简单的模块`MyCell`转换为`Torchscript`,并创建了两个采样张量`x``h`传递给网络模块的正向方法。 然后,我们使用`jit.trace`跟踪 Python 代码并创建 TorchScript。
在本秘籍中,我们使用了跟踪方法来创建 TorchScript。 我们定义了一个简单的模块`MyCell`转换为`Torchscript`,并创建了两个采样张量`x``h`传递给网络模块的正向方法。 然后,我们使用`jit.trace`跟踪 Python 代码并创建 TorchScript。
我们使用跟踪将`PyTorch`模型转换为 TorchScript,并传递了我们的模型实例。 `jit.trace`通过在模块的前向方法内跟踪模型评估中的操作来创建`torch.jit.ScriptModule`对象。 `jit.trace`运行网络模块,记录运行该模块时发生的操作,并创建`torch.jit.ScriptModule`对象的实例。 TorchScript 以中间表示形式(在深度学习中称为图形)记录其定义。 然后,我们检查了具有`.graph`属性的图形,并使用`.code`生成了更具可读性的版本,这是代码的 Python 语法解释。
......@@ -426,25 +426,25 @@ my_cell = MyCell(MyDecisionGate())
# 汇出至 ONNX
在本食谱中,我们将介绍如何将 PyTorch 模型导出到**开放神经网络交换****ONNX**),该模型为深度学习和传统机器学习模型提供了一种开源格式。 它定义了一个可扩展的计算图模型,以及内置的运算符和标准数据类型。
在本秘籍中,我们将介绍如何将 PyTorch 模型导出到**开放神经网络交换****ONNX**),该模型为深度学习和传统机器学习模型提供了一种开源格式。 它定义了一个可扩展的计算图模型,以及内置的运算符和标准数据类型。
ONNX 得到了广泛的支持,可以在许多框架,工具和硬件中找到,因为它可以实现不同框架之间的互操作性,并可以实现从研究到生产的过渡。
# 做好准备
对于此食谱,我们需要安装 ONNX,可以使用以下命令进行安装:
对于此秘籍,我们需要安装 ONNX,可以使用以下命令进行安装:
```py
pip install onnx
```
这样,我们就可以进行配方了。
这样,我们就可以进行秘籍了。
对于此配方,我们还将需要在第 3 章,“用于计算机视觉的卷积神经网络”中在`CIFAR-10`上训练的模型的训练权重。
对于此秘籍,我们还将需要在第 3 章,“用于计算机视觉的卷积神经网络”中在`CIFAR-10`上训练的模型的训练权重。
# 怎么做...
在本食谱中,我们将 CIFAR-1o 模型导出为 ONNX 格式,并使用`onnxruntime`运行它。 请按照以下步骤操作:
在本秘籍中,我们将 CIFAR-1o 模型导出为 ONNX 格式,并使用`onnxruntime`运行它。 请按照以下步骤操作:
1. 我们将从进口开始:
......@@ -567,15 +567,15 @@ CNN(
>>np.testing.assert_allclose(to_numpy(model_out), ort_outs[0], rtol=1e-03, atol=1e-05)
```
通过此配方,我们已导出为`onnx`格式,并使用 ONNX 运行时以`onnx`格式运行了模型。
通过此秘籍,我们已导出为`onnx`格式,并使用 ONNX 运行时以`onnx`格式运行了模型。
# 这个怎么运作...
在此食谱中,我们将正常的 PyTorch 模型导出为 ONNX 格式,并使用 ONNX 运行时运行`onnx`模型。 为此,我们采用了权重模型。 在这里,我们使用了第 3 章“卷积神经网络”的 CIFAR-10 模型,用于计算机视觉*。 我们从训练中使用了模型的权重,并将模型设置为评估模式,以进行快速,轻便的计算。
在此秘籍中,我们将正常的 PyTorch 模型导出为 ONNX 格式,并使用 ONNX 运行时运行`onnx`模型。 为此,我们采用了权重模型。 在这里,我们使用了第 3 章“卷积神经网络”的 CIFAR-10 模型,用于计算机视觉*。 我们从训练中使用了模型的权重,并将模型设置为评估模式,以进行快速,轻便的计算。
然后,我们使用了一个随机变量,其形状与输入张量的形状相同,在本例中为三通道`32 x 32`像素图像。 我们将此随机输入传递到模型中并获得输出。 然后,我们使用输出将其与模型的 ONNX 版本中的模型进行比较。
在 PyTorch 中使用跟踪或脚本导出模型。 在本食谱中,我们在`torch.onnx.export()`的帮助下使用了跟踪。 跟踪跟踪用于获取输出的操作。 这就是为什么我们提供`x`的原因-因此可以进行跟踪。 `x`必须具有正确的类型和大小。 输入尺寸在导出的 ONNX 图形中固定为所有输入尺寸,我们必须指定所有动态轴。 在此配方中,我们使用第一维的输入导出模型,将批量大小设置为 1,并在`torch.onnx.export()``dynamic_axes`参数中将第一维指定为动态。
在 PyTorch 中使用跟踪或脚本导出模型。 在本秘籍中,我们在`torch.onnx.export()`的帮助下使用了跟踪。 跟踪跟踪用于获取输出的操作。 这就是为什么我们提供`x`的原因-因此可以进行跟踪。 `x`必须具有正确的类型和大小。 输入尺寸在导出的 ONNX 图形中固定为所有输入尺寸,我们必须指定所有动态轴。 在此秘籍中,我们使用第一维的输入导出模型,将批量大小设置为 1,并在`torch.onnx.export()``dynamic_axes`参数中将第一维指定为动态。
第一个参数是 PyTorch 模型,第二个参数是随机变量。 然后,我们有了`onnx`格式的路径; `export_params`用于将训练后的参数权重存储在模型文件中; `opset_version``onnx`导出版本; `do_constant_folding`用于执行常量折叠以进行优化; `input_names`是模型的输入名称,`output_names`是模型的输出名称。 然后,我们加载了导出的`onnx`模型,并检查了模型结构并使用`onnx.checker.check_model(onnx_model)`验证了架构。 通过检查模型版本,图形的结构,节点及其输入和输出来验证 ONNX 图形。
......
......@@ -467,7 +467,7 @@ RNN 实现通常是单向的,这就是到目前为止我们已经实现的。
高级`RNNClassifier`与简单`RNNClassifier`完全相同,唯一的例外是 RNN 编码器已被 LSTM 或 GRU 编码器替代。 但是,高级分类器由于使用了高度优化的 cuDNN 后端,因此可以显着提高网络性能,尤其是在 GPU 上。
我们为高级 RNN 开发的模型是多层双向 LSTM/GRU 网络。 增加对配方的关注可大大提高性能。 但这不会改变分类器,因为所有这些组件都将使用`Encoder`方法包装,并且分类器仅担心`Encoder`的功能 API 不会改变。
我们为高级 RNN 开发的模型是多层双向 LSTM/GRU 网络。 增加对秘籍的关注可大大提高性能。 但这不会改变分类器,因为所有这些组件都将使用`Encoder`方法包装,并且分类器仅担心`Encoder`的功能 API 不会改变。
##### 注意
......
......@@ -10,7 +10,7 @@ PyTorch 包含一个探查器 API,可用于识别代码中各种 PyTorch 操
Profiler 支持多线程模型。 Profiler 与该操作在同一线程中运行,但它还将对可能在另一个线程中运行的子运算符进行概要分析。 同时运行的探查器的作用域将限制在其自己的线程中,以防止结果混淆。
转到[食谱](https://pytorch.org/tutorials/recipes/recipes/profiler.html),可以更快地了解 Profiler API 的用法。
转到[秘籍](https://pytorch.org/tutorials/recipes/recipes/profiler.html),可以更快地了解 Profiler API 的用法。
* * *
......@@ -272,7 +272,7 @@ Self CPU time total: 225.801ms
我们已经看到了 Profiler 如何用于调查 PyTorch 模型中的时间和内存瓶颈。 在此处阅读有关 Profiler 的更多信息:
* [事件探查器使用配方](https://pytorch.org/tutorials/recipes/recipes/profiler.html)
* [事件探查器使用秘籍](https://pytorch.org/tutorials/recipes/recipes/profiler.html)
* [分析基于 RPC 的工作负载](https://pytorch.org/tutorials/recipes/distributed_rpc_profiling.html)
* [Profiler API 文档](https://pytorch.org/docs/stable/autograd.html?highlight=profiler#profiler)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册