提交 8a766406 编写于 作者: W wizardforcel

2021-01-16 18:28:27

上级 7b5860e3
......@@ -56,7 +56,7 @@
**总损失**:这结合了内容损失和样式损失。 两种损失都具有与之相关的权重,该权重用于确定它们参与总损失的计算。
5. **参数更新**:此步骤使用渐变来更新模型的不同参数。
5. **参数更新**:此步骤使用梯度来更新模型的不同参数。
# 使用 VGG-19 网络架构实现样式转移
......@@ -424,7 +424,7 @@ style_features = features_extractor(style_img, model, \
target_img = content_img.clone().requires_grad_(True)
```
优良作法是将初始目标图像创建为内容图像的副本。 此外,考虑到我们希望能够在迭代过程中对其进行修改,直到内容与内容图像的内容和样式与样式图像的相似为止,将其设置为需要渐变计算至关重要。
优良作法是将初始目标图像创建为内容图像的副本。 此外,考虑到我们希望能够在迭代过程中对其进行修改,直到内容与内容图像的内容和样式与样式图像的相似为止,将其设置为需要梯度计算至关重要。
同样,如果您的计算机具有可用的 GPU,请确保同时使用以下代码段将目标图像分配给 GPU:
......
......@@ -30,7 +30,7 @@
# 了解模型不可知的元学习
**与模型无关的元学习****MAML**)尝试通过为每个新任务提供更好的权重初始化来解决梯度下降方法的缺点。 这种方法的关键思想是使用不同的数据集训练模型的参数。 当将其用于新任务时,该模型通过使用已初始化的参数通过一个或多个渐变步骤来微调架构,从而提供更好的性能。 从特征学习的角度来看,这种训练模型参数以使一些梯度步骤可以优化损失函数的方法也可以从构建内部表示的角度来看。 在这种方法中,我们选择通用模型的架构,以便可以将其用于各种任务。 MAML 的主要贡献是一种与模型和任务无关的简单快速学习算法。
**与模型无关的元学习****MAML**)尝试通过为每个新任务提供更好的权重初始化来解决梯度下降方法的缺点。 这种方法的关键思想是使用不同的数据集训练模型的参数。 当将其用于新任务时,该模型通过使用已初始化的参数通过一个或多个梯度步骤来微调架构,从而提供更好的性能。 从特征学习的角度来看,这种训练模型参数以使一些梯度步骤可以优化损失函数的方法也可以从构建内部表示的角度来看。 在这种方法中,我们选择通用模型的架构,以便可以将其用于各种任务。 MAML 的主要贡献是一种与模型和任务无关的简单快速学习算法。
# 了解 MAML 背后的逻辑
......@@ -38,7 +38,7 @@ MAML 的目的是为模型的参数提供良好的初始化,从而以较少的
![](img/b3cabe38-594a-4604-a177-7da4089882bb.png)
如上图所示,`θ`是模型的参数,粗黑线是元学习阶段。 假设我们有三个不同的新任务,并且为每个任务(带有箭头的灰色线)执行了一个渐变步骤。 我们可以看到参数`θ`接近三个任务的所有三个最佳参数,这使`θ`成为可以快速适应不同新任务的最佳参数初始化。 结果,参数θ的很小变化将导致任何任务的损失函数的最佳最小化。 根据这一观察结果,MML 建议我们首先应通过主要数据集学习θ; 在对实际数据集进行微调的同时,我们仅需移动一小步。
如上图所示,`θ`是模型的参数,粗黑线是元学习阶段。 假设我们有三个不同的新任务,并且为每个任务(带有箭头的灰色线)执行了一个梯度步骤。 我们可以看到参数`θ`接近三个任务的所有三个最佳参数,这使`θ`成为可以快速适应不同新任务的最佳参数初始化。 结果,参数θ的很小变化将导致任何任务的损失函数的最佳最小化。 根据这一观察结果,MML 建议我们首先应通过主要数据集学习θ; 在对实际数据集进行微调的同时,我们仅需移动一小步。
顾名思义,与模型无关的元学习可以用于任何形式的模型,无论是分类,回归还是强化学习。 但是对于这本书,我们将只关注 MAML 算法的一键式学习分类方面。 所以,让我们开始吧!
......@@ -99,7 +99,7 @@ LSTM 元学习器的关键思想是训练 LSTM 单元以*学习我们原始任
![](img/7f93507c-8eba-4a42-a6f5-8eb229b65be1.png)
LSTM 在各种门的帮助下存储信息历史记录,如上图所示。 我们还知道,**随机梯度下降****SGD**)有多种变化形式,例如动量,RMSprop,Adam 等,它们实质上存储了有关过去学习的信息(在 渐变形式)以实现更好的优化。 因此,从逻辑上讲,可以将 LSTM 单元视为一种更好的优化策略,该策略使模型能够捕获特定任务的短期知识和公共长期知识。
LSTM 在各种门的帮助下存储信息历史记录,如上图所示。 我们还知道,**随机梯度下降****SGD**)有多种变化形式,例如动量,RMSprop,Adam 等,它们实质上存储了有关过去学习的信息(在 梯度形式)以实现更好的优化。 因此,从逻辑上讲,可以将 LSTM 单元视为一种更好的优化策略,该策略使模型能够捕获特定任务的短期知识和公共长期知识。
在下一部分中,我们将了解架构,LSTM 单元背后的逻辑以及权重更新算法。
......
......@@ -194,7 +194,7 @@ PyTorch 与其他深度学习框架之间的另一个主要区别是语法。 Py
y = Torch.Tensor(train_labels).long()
注意这两个张量的数据类型。 浮点张量由 32 位浮点数组成,而长张量由 64 位整数组成。 为了使 PyTorch 能够计算渐变,我们的`X`功能必须为浮点数,而我们的标签必须为该分类模型中的整数(因为我们正在尝试预测 1、2、3 和 等等),因此 1.5 的预测就没有意义。
注意这两个张量的数据类型。 浮点张量由 32 位浮点数组成,而长张量由 64 位整数组成。 为了使 PyTorch 能够计算梯度,我们的`X`功能必须为浮点数,而我们的标签必须为该分类模型中的整数(因为我们正在尝试预测 1、2、3 和 等等),因此 1.5 的预测就没有意义。
## 建立分类器
......
......@@ -55,7 +55,7 @@ RNN 由循环层组成。 尽管它们在许多方面类似于标准前馈神经
RNN 中我们经常面临的一个问题是**梯度爆炸或收缩**。 我们可以将递归层视为一个非常深的网络。 在计算梯度时,我们在隐藏状态的每次迭代中都这样做。 如果在给定位置的损耗相对于权重的梯度变得很大,则在递归层的所有迭代中前馈时,这将产生乘法效果。 这会导致梯度爆炸,因为它们会很快变得非常大。 如果我们的梯度较大,则可能导致网络不稳定。 另一方面,如果隐藏状态下的梯度非常小,这将再次产生乘法效果,并且梯度将接近 0。这意味着梯度可能变得太小而无法通过梯度下降准确地更新参数, 表示我们的模型无法学习。
我们可以用来防止的梯度爆炸的一种技术是使用**梯度剪切**。 此技术限制了我们的渐变,以防止它们变得太大。 我们只需选择一个超参数`C`,就可以计算出裁剪的梯度,如下所示:
我们可以用来防止的梯度爆炸的一种技术是使用**梯度剪切**。 此技术限制了我们的梯度,以防止它们变得太大。 我们只需选择一个超参数`C`,就可以计算出裁剪的梯度,如下所示:
![](img/Formula_05_002.png)
......@@ -465,7 +465,7 @@ nn.utils.clip_grad_norm(net.parameters(),剪辑)
Optimizer.step()
在这里,我们只训练了多个时期的模型,对于每个时期,我们首先使用批量大小参数初始化隐藏层。 在这种情况下,我们设置`batch_size = 1`,因为我们一次只训练我们的模型一个句子。 对于火车装载机中的每批输入语句和标签,我们首先将梯度归零(以防止它们累积),并使用模型的当前状态使用数据的正向传递来计算模型输出。 然后使用此输出,使用模型的预测输出和正确的标签来计算损失。 然后,我们通过网络对该损失进行反向传递,以计算每个阶段的梯度。 接下来,我们使用`grad_clip_norm()`函数裁剪渐变,因为这将阻止渐变爆炸,如本章前面所述。 我们定义了`clip = 5`,这意味着任何给定节点的最大梯度为`5`。 最后,我们通过调用`optimizer.step()`,使用在向后传递中计算出的梯度来更新权重。
在这里,我们只训练了多个时期的模型,对于每个时期,我们首先使用批量大小参数初始化隐藏层。 在这种情况下,我们设置`batch_size = 1`,因为我们一次只训练我们的模型一个句子。 对于火车装载机中的每批输入语句和标签,我们首先将梯度归零(以防止它们累积),并使用模型的当前状态使用数据的正向传递来计算模型输出。 然后使用此输出,使用模型的预测输出和正确的标签来计算损失。 然后,我们通过网络对该损失进行反向传递,以计算每个阶段的梯度。 接下来,我们使用`grad_clip_norm()`函数裁剪梯度,因为这将阻止梯度爆炸,如本章前面所述。 我们定义了`clip = 5`,这意味着任何给定节点的最大梯度为`5`。 最后,我们通过调用`optimizer.step()`,使用在向后传递中计算出的梯度来更新权重。
如果我们自己运行此循环,我们将训练我们的模型。 但是,我们想在每个时期之后评估模型的性能,以便根据验证数据集确定模型的性能。 我们这样做如下:
......
......@@ -1155,7 +1155,7 @@ corpus_name = "movie_corpus"
现在我们已经创建了编码器和解码器的实例,我们准备开始训练它们。
我们首先初始化一些训练超参数。 以与模型超参数相同的方式,可以调整这些参数以影响训练时间以及模型的学习方式。 裁剪控制渐变裁剪,教师强迫控制我们在模型中使用教师强迫的频率。 请注意,我们如何使用教师强制比 1,以便始终使用教师强制。 降低教学强迫率将意味着我们的模型需要更长的时间才能收敛。 但是,从长远来看,这可能有助于我们的模型更好地自行生成正确的句子。
我们首先初始化一些训练超参数。 以与模型超参数相同的方式,可以调整这些参数以影响训练时间以及模型的学习方式。 裁剪控制梯度裁剪,教师强迫控制我们在模型中使用教师强迫的频率。 请注意,我们如何使用教师强制比 1,以便始终使用教师强制。 降低教学强迫率将意味着我们的模型需要更长的时间才能收敛。 但是,从长远来看,这可能有助于我们的模型更好地自行生成正确的句子。
6. We also need to define the learning rates of our models and our decoder learning ratio. You will find that your model performs better when the decoder carries out larger parameter updates during gradient descent. Therefore, we introduce a decoder learning ratio to apply a multiplier to the learning rate so that the learning rate is greater for the decoder than it is for the encoder. We also define how often our model prints and saves the results, as well as how many epochs we want our model to run for:
......
......@@ -11,7 +11,7 @@ PyTorch 与 Python 深度集成,具有命令式风格,使用类似 Python
* 安装 PyTorch
* 在 PyTorch 中创建张量
* 互操作的 NumPy 桥
* 渐变且无渐变
* 梯度且无梯度
* 在 PyTorch 中查看张量
# 技术要求
......@@ -424,13 +424,13 @@ tensor([[2., 2., 2.],
要了解更多信息,[请单击 NyPy 桥的 PyTorch 官方文档链接](https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#numpy-bridge)
# 探索渐变
# 探索梯度
让我们简要介绍一下什么是渐变。 为此,我们需要首先了解什么是梯度下降。 在机器学习问题中,我们提供一个输入和期望的输出对,并要求我们的模型概括给定输入和输出对之间的关​​系。 但是有时模型会得知其预测会与期望的输出相去甚远(这种差异称为**损失**)。 那么什么是梯度下降?
让我们简要介绍一下什么是梯度。 为此,我们需要首先了解什么是梯度下降。 在机器学习问题中,我们提供一个输入和期望的输出对,并要求我们的模型概括给定输入和输出对之间的关​​系。 但是有时模型会得知其预测会与期望的输出相去甚远(这种差异称为**损失**)。 那么什么是梯度下降?
**梯度下降**是一种优化算法,用于通过在梯度的负值所定义的最陡下降方向上反复移动来使函数最小化。 我们在训练模型时会使用它,以使损失最小化。 它用于查找使成本或损失函数最小化的函数参数值(机器学习中的系数或权重)。
那么什么是渐变呢? 梯度度量的是当输入改变很小的时候给定函数的输出有多少变化,这与微积分中的导数概念相同。 梯度会计算所有权重相对于误差变化的变化。 渐变是函数的斜率。 较高的坡度意味着坡度更陡,并且模型可以更快地学习。 梯度指向最陡的倾斜方向。 PyTorch 中的`Autograd`模块在 PyTorch 中执行所有梯度计算。 它是自动差异化的核心 Torch 软件包。 它使用基于磁带的系统进行自动区分。 在前进阶段,`Autograd`磁带将记住它执行的所有操作,而在倒退阶段,它将重放它们。
那么什么是梯度呢? 梯度度量的是当输入改变很小的时候给定函数的输出有多少变化,这与微积分中的导数概念相同。 梯度会计算所有权重相对于误差变化的变化。 梯度是函数的斜率。 较高的坡度意味着坡度更陡,并且模型可以更快地学习。 梯度指向最陡的倾斜方向。 PyTorch 中的`Autograd`模块在 PyTorch 中执行所有梯度计算。 它是自动差异化的核心 Torch 软件包。 它使用基于磁带的系统进行自动区分。 在前进阶段,`Autograd`磁带将记住它执行的所有操作,而在倒退阶段,它将重放它们。
# 怎么做...
......@@ -464,7 +464,7 @@ tensor([[11., 11., 11.],
[11., 11., 11.]], grad_fn=<AddBackward0>)
```
3.让我们从原始的`x`开始进一步探索 PyTorch 中的渐变
3.让我们从原始的`x`开始进一步探索 PyTorch 中的梯度
```py
x
......@@ -556,7 +556,7 @@ PyTorch 有一个名为`autograd`的软件包,可以对张量上的所有操
# 还有更多...
您可以使用`torch.set_grad_enabled()`方法启用和禁用梯度计算,以及使用`detach()`方法来将来跟踪计算。 使用`grad_fn`属性查看附加到张量的渐变函数。
您可以使用`torch.set_grad_enabled()`方法启用和禁用梯度计算,以及使用`detach()`方法来将来跟踪计算。 使用`grad_fn`属性查看附加到张量的梯度函数。
# 也可以看看
......
# 迁移学习和 TensorBoard
迁移学习是深度学习中的一个重要概念,它使我们可以将深度学习用于各种日常任务。 这是一种机器学习技术,其中针对任务训练的模型被重用以创建用于类似任务的新模型。 我们采用在大型数据集上训练的模型,并将其知识转移到较小的数据集。 对于具有**卷积神经网络****CNN**)的计算机视觉任务,我们冻结了网络的早期卷积层,仅训练了最后几层。 早期的卷积层提取适用于整个图像的通用低级特征,以检测边缘,图案和渐变,而稍后的层识别图像中的特定特征,并且特定于数据集。
迁移学习是深度学习中的一个重要概念,它使我们可以将深度学习用于各种日常任务。 这是一种机器学习技术,其中针对任务训练的模型被重用以创建用于类似任务的新模型。 我们采用在大型数据集上训练的模型,并将其知识转移到较小的数据集。 对于具有**卷积神经网络****CNN**)的计算机视觉任务,我们冻结了网络的早期卷积层,仅训练了最后几层。 早期的卷积层提取适用于整个图像的通用低级特征,以检测边缘,图案和梯度,而稍后的层识别图像中的特定特征,并且特定于数据集。
在本章中,我们将训练图像分类器以区分正常患者和肺炎患者的胸部 X 光,并使用经过训练的 ResNet-50 模型进行迁移学习。 我们将替换分类器,并有两个输出单元代表正常和肺炎分类。
......
......@@ -570,7 +570,7 @@ for _ in range(num_agents):
agent.apply(init_weight)
```
4. 我们将关闭每个代理层的渐变
4. 我们将关闭每个代理层的梯度
```py
for param in agent.parameters():
......
......@@ -32,7 +32,7 @@ Python 在深度学习社区中的广泛接受使一些研究人员和开发人
作为 **Python 优先框架**,PyTorch 大大超越了在整体 C ++或 C 引擎上实现 Python 包装器的其他框架。 在 PyTorch 中,您可以继承 PyTorch 类并根据需要进行自定义。 内置于 PyTorch 核心的命令式编码风格仅由于 Python 优先方法才有可能。 尽管诸如 TensorFlow,MXNet 和 CNTK 的某些符号图框架提出了一种强制性方法,但由于社区的支持及其灵活性,PyTorch 仍能保持领先地位。
基于磁带的**自动分级**系统使 PyTorch 具有**动态图**功能。 这是 PyTorch 与其他流行的符号图框架之间的主要区别之一。 基于磁带的 autograd 也支持 Chainer,autograd 和 Torch-autograd 的反向传播算法。 具有动态图功能,您的图将在 Python 解释器到达相应行时创建。 与 TensorFlow 的*定义并运行*方法不同,这称为*通过运行定义*
基于磁带的**自动微分**系统使 PyTorch 具有**动态图**功能。 这是 PyTorch 与其他流行的符号图框架之间的主要区别之一。 基于磁带的 autograd 也支持 Chainer,autograd 和 Torch-autograd 的反向传播算法。 具有动态图功能,您的图将在 Python 解释器到达相应行时创建。 与 TensorFlow 的*定义并运行*方法不同,这称为*通过运行定义*
基于磁带的 autograd 使用反向模式自动微分,在前进过程中,图形将每个操作保存到磁带中,然后在磁带中向后移动以进行反向传播。 动态图和 Python 优先方法使**易于调试**,您可以在其中使用常用的 Python 调试器,例如 Pdb 或基于编辑器的调试器。
......
......@@ -168,13 +168,13 @@ tensor([1.])
当成为图形的一部分时,张量需要存储 autograd 自动区分所需的信息。 张量充当计算图中的一个节点,并通过功能模块实例连接到其他节点。 Tensor 实例主要具有支持 autograd 的三个属性:`.grad``.data``grad_fn()`(注意字母大小写:`Function`代表 PyTorch `Function`模块,而`function`代表 Python 函数)。
`.grad`属性在任何时间点存储渐变,所有向后调用将当前渐变累积到`.grad`属性。 `.data`属性可访问其中包含数据的裸张量对象。
`.grad`属性在任何时间点存储梯度,所有向后调用将当前梯度累积到`.grad`属性。 `.data`属性可访问其中包含数据的裸张量对象。
![Autograd attributes of a tensor](img/B09475_02_05.jpg)
图 2.5:data,grad 和 grad_fn
如果您想知道,前面的代码片段中的`required_grad`参数会通知张量或 autograd-engine 在进行反向传播时需要渐变。 创建张量时,可以指定是否需要该张量来承载渐变。 在我们的示例中,我们没有使用梯度更新输入张量(输入永远不会改变):我们只需要更改权重即可。 由于我们没有在迭代中更改输入,因此不需要输入张量即可计算梯度。 因此,在包装输入张量时,我们将`False`作为`required_grad`参数传递,对于权重,我们传递`True`。 检查我们之前创建的张量实例的`grad``data`属性。
如果您想知道,前面的代码片段中的`required_grad`参数会通知张量或 autograd-engine 在进行反向传播时需要梯度。 创建张量时,可以指定是否需要该张量来承载梯度。 在我们的示例中,我们没有使用梯度更新输入张量(输入永远不会改变):我们只需要更改权重即可。 由于我们没有在迭代中更改输入,因此不需要输入张量即可计算梯度。 因此,在包装输入张量时,我们将`False`作为`required_grad`参数传递,对于权重,我们传递`True`。 检查我们之前创建的张量实例的`grad``data`属性。
Tensor 和`Function`实例在图中时是相互连接的,并且一起构成了非循环计算图。 除了用户明确创建的张量以外,每个张量都连接到一个函数。 (如果用户未明确创建张量,则必须通过函数创建张量。例如,表达式`c = a + b`中的`c`由加法函数创建。 )您可以通过在张量上调用`grade_fn`来访问创建器功能。 打印`grad``.data``.grade_fn()`的值可得到以下结果:
......@@ -263,11 +263,11 @@ print(a2.grad, a2.grad_fn, a2)
反向传播通过找到每个参数应移动的方向来实现这一点,从而使损耗值的整体运动爬下山。 我们为此寻求微积分的帮助。 任何函数相对于最终误差的导数都可以告诉我们上图中该函数的斜率是多少。 因此,反向传播通过获取关于最终损失的每个神经元(通常每个神经元通常是非线性函数)的导数并告诉我们必须移动的方向来帮助我们。
在拥有框架之前,这不是一个容易的过程。 实际上,找到每个参数的导数并进行更新是一项繁琐且容易出错的任务。 在 PyTorch 中,您要做的就是在最后一个节点上调用`backward`,它将反向传播并更新它。 具有渐变`grad`属性。
在拥有框架之前,这不是一个容易的过程。 实际上,找到每个参数的导数并进行更新是一项繁琐且容易出错的任务。 在 PyTorch 中,您要做的就是在最后一个节点上调用`backward`,它将反向传播并更新它。 具有梯度`grad`属性。
PyTorch 的`backward`函数进行反向传播,并找到每个神经元的错误。 但是,我们需要基于此误差因子来更新神经元的权重。 更新发现的错误的过程通常称为优化,并且有不同的优化策略。 PyTorch 为我们提供了另一个名为`optim`的模块,用于实现不同的优化算法。 在先前的实现中,我们使用了基本且最受欢迎的优化算法,称为**随机梯度下降****SGD**)。 当我们使用复杂的神经网络时,我们将在后面的章节中看到不同的优化算法。
PyTorch 还通过将反向传播和优化分为不同的步骤,为我们提供了更大的灵活性。 请记住,反向传播会在`.grad`属性中累积渐变。 这是有帮助的,特别是在我们的项目更注重研究,或者想要深入研究权重-梯度关系,或者想要了解梯度的变化方式时。 有时,我们希望更新除特定神经元之外的所有参数,或者有时我们可能认为不需要更新特定层。 在需要对参数更新进行更多控制的情况下,具有显式的参数更新步骤会带来很大的好处。
PyTorch 还通过将反向传播和优化分为不同的步骤,为我们提供了更大的灵活性。 请记住,反向传播会在`.grad`属性中累积梯度。 这是有帮助的,特别是在我们的项目更注重研究,或者想要深入研究权重-梯度关系,或者想要了解梯度的变化方式时。 有时,我们希望更新除特定神经元之外的所有参数,或者有时我们可能认为不需要更新特定层。 在需要对参数更新进行更多控制的情况下,具有显式的参数更新步骤会带来很大的好处。
在前进之前,我们检查之前检查过的所有张量,以了解在向后传递之后发生了什么变化。
......@@ -280,15 +280,15 @@ print(a2.grad, a2.grad_fn, a2)
# None <AddBackward0 object at 0x7f5f3d42c780> tensor([[...]])
```
事情变了! 由于我们使用`required_grad`作为`False`创建了输入张量,因此我们首先进行打印以检查输入的属性没有显示任何差异。 `w1`已更改。 在向后传递之前,`.grad`属性为`None`,现在它具有一些渐变。 令人耳目一新!
事情变了! 由于我们使用`required_grad`作为`False`创建了输入张量,因此我们首先进行打印以检查输入的属性没有显示任何差异。 `w1`已更改。 在向后传递之前,`.grad`属性为`None`,现在它具有一些梯度。 令人耳目一新!
权重是我们需要根据渐变更改的参数,因此我们获得了它们的渐变。 我们没有渐变函数,因为它是由用户创建的,因此`grad_fn`仍然是`None`,而`.data`仍然相同。 如果我们尝试打印数据的值,它将仍然是相同的,因为向后传递不会隐式更新张量。 总之,在`x``w1``a2`中,只有`w1`得到了梯度。 这是因为由内部函数(例如`a2`)创建的中间节点将不保存梯度,因为它们是无参数节点。 影响神经网络输出的唯一参数是我们为层定义的权重。
权重是我们需要根据梯度更改的参数,因此我们获得了它们的梯度。 我们没有梯度函数,因为它是由用户创建的,因此`grad_fn`仍然是`None`,而`.data`仍然相同。 如果我们尝试打印数据的值,它将仍然是相同的,因为向后传递不会隐式更新张量。 总之,在`x``w1``a2`中,只有`w1`得到了梯度。 这是因为由内部函数(例如`a2`)创建的中间节点将不保存梯度,因为它们是无参数节点。 影响神经网络输出的唯一参数是我们为层定义的权重。
##### 参数更新
参数更新或优化步骤采用反向传播生成的梯度,并使用一些策略来更新权重,以通过一小步来减小参数的贡献因子。 然后重复此步骤,直到找到一组良好的参数。
所有用户创建的张量都要求渐变`gradient`属性中具有值,并且我们需要更新参数。 所有参数张量都具有`.data`属性和`.grad`属性,它们分别具有张量值和梯度。 显然,我们需要做的是获取梯度并将其从数据中减去。 但是,事实证明,从参数减小整个梯度并不是一个好主意。 其背后的想法是,参数更新的数量决定了网络从每个示例(每次迭代)中学到的知识,并且如果我们给出的特定示例是一个异常值,我们不希望我们的网络学习虚假信息。
所有用户创建的张量都要求梯度`gradient`属性中具有值,并且我们需要更新参数。 所有参数张量都具有`.data`属性和`.grad`属性,它们分别具有张量值和梯度。 显然,我们需要做的是获取梯度并将其从数据中减去。 但是,事实证明,从参数减小整个梯度并不是一个好主意。 其背后的想法是,参数更新的数量决定了网络从每个示例(每次迭代)中学到的知识,并且如果我们给出的特定示例是一个异常值,我们不希望我们的网络学习虚假信息。
我们希望我们的网络得到推广,从所有示例中学习一些,并最终变得擅长于推广任何新示例。 因此,我们不是从数据中减少整个梯度,而是使用学习率来决定在特定更新中应使用多少梯度。 找到最佳学习率始终是一个重要的决定,因为这会影响模型的整体性能。 基本的经验法则是找到一个学习率,该学习率应足够小以使模型最终能够学习,而又要足够高以至于不会永远收敛。
......@@ -302,7 +302,7 @@ SGD 的主要缺点是效率低下。 例如,考虑我们的 *FizzBu​​zz*
除了我们刚才介绍的新超参数,学习率和批量大小以外,其他所有内容均保持不变。 我们用学习率乘以`.grad`属性来更新`.data`属性,并针对每次迭代进行此操作。 选择批量大小几乎总是取决于内存的可用性。 我们尝试使小批量尽可能大,以便可以将其放置在 GPU 内存中。 将整个批量划分为小批量,以确保每次梯度更新都会产生足够的抽动,从而在使用 GPU 提供的全部功能的同时,将模型从局部最小值中剔除。
我们已经到达了模型构建旅程的最后一部分。 到目前为止,所有操作都很直观,简单,但是最后一部分有点令人困惑。 `zero_grad`做什么? 还记得关于重量`w1.grad`的第一份印刷声明吗? 它是空的,现在具有当前反向传递的渐变。 因此,我们需要在下一次向后传递之前清空渐变,因为渐变会累积而不是被重写。 参数更新后,我们在每个迭代的每个张量上调用`zero_grad()`,然后继续进行下一个迭代。
我们已经到达了模型构建旅程的最后一部分。 到目前为止,所有操作都很直观,简单,但是最后一部分有点令人困惑。 `zero_grad`做什么? 还记得关于重量`w1.grad`的第一份印刷声明吗? 它是空的,现在具有当前反向传递的梯度。 因此,我们需要在下一次向后传递之前清空梯度,因为梯度会累积而不是被重写。 参数更新后,我们在每个迭代的每个张量上调用`zero_grad()`,然后继续进行下一个迭代。
`.grad_fn`通过连接函数和张量将图形保持在一起。 在`Function`模块中定义了对张量的每种可能的操作。 所有张量的`.grad_fn`始终指向功能对象,除非用户创建了它。 PyTorch 允许您使用`grad_fn`向后浏览图形。 从图形中的任何节点,可以通过在`grad_fn`的返回值上调用`next_functions`来到达任何父节点。
......@@ -444,7 +444,7 @@ y = torch.from_numpy(trY).type(ytype)
##### parameters()
调用`parameters()`会返回所有模型参数,这对于优化程序或要使用参数进行实验非常有用。 在我们开发的新手模型中,它具有四个参数`w1``w2``b1``b2`,并且逐行使用渐变更新了参数。 但是,在`FizBuzNet`中,由于我们有一个模型类,并且尚未创建模型的权重和偏差,因此`.parameter()`调用是可行的方法。
调用`parameters()`会返回所有模型参数,这对于优化程序或要使用参数进行实验非常有用。 在我们开发的新手模型中,它具有四个参数`w1``w2``b1``b2`,并且逐行使用梯度更新了参数。 但是,在`FizBuzNet`中,由于我们有一个模型类,并且尚未创建模型的权重和偏差,因此`.parameter()`调用是可行的方法。
```py
net = FizBuzNet(input_size, hidden_size, output_size)
......@@ -540,7 +540,7 @@ error = hyp - y_
output = error.pow(2).sum() / 2.0
```
然后,由`loss(hyp, y_)`返回的节点将成为叶节点,我们可以在该叶节点上向后调用以找到渐变
然后,由`loss(hyp, y_)`返回的节点将成为叶节点,我们可以在该叶节点上向后调用以找到梯度
### 优化器
......
......@@ -519,7 +519,7 @@ evaluator.run(val_loader)
函数`create_supervised_trainer``create_supervised_evaluator`返回一个`Engine`对象,该对象具有类似于`training_loop`的功能来执行代码的公共模式,如先前给出的那样。 除了给定的参数,这两个函数还接受一个设备(CPU 或 GPU),该设备返回在我们指定的设备上运行的 Trainer 或 Evaluator `Engine`实例。 现在情况越来越好了吧? 我们传递了定义的模型,所需的优化器以及正在使用的损失函数,但是在有了训练器和`evaluator`对象之后我们该怎么办?
`Engine`对象定义了`run`方法,该方法使循环根据传递给`run`函数的时期和加载器开始执行。 与往常一样,`run`方法使`trainer`循环从零到历元数。 对于每次迭代,我们的训练师都会通过加载程序进行渐变更新。
`Engine`对象定义了`run`方法,该方法使循环根据传递给`run`函数的时期和加载器开始执行。 与往常一样,`run`方法使`trainer`循环从零到历元数。 对于每次迭代,我们的训练师都会通过加载程序进行梯度更新。
训练完成后,`evaluator``val_loader`开始,并通过使用评估数据集运行相同的模型来确保情况得到改善。
......
......@@ -277,7 +277,7 @@ trainloader, testloader = get_data()
4. 运行网络的正向传递。
5. 通过通过网络输出调用损失函数来获取损失。
6. 运行向后传递。
7. 使用优化程序进行渐变更新。
7. 使用优化程序进行梯度更新。
8. 如果需要,可以节省运行损失。
在保存运行损失时要小心,因为 PyTorch 会在变量进行反向传播之前保存整个图形。 增量保存图形只是图形中的另一种操作,其中每次迭代中的图形都使用求和运算将先前的图形附加到图形上,最终导致内存不足。 始终从图形中取出值并将其保存为没有图形历史记录的普通张量。
......
......@@ -354,7 +354,7 @@ opt = optim.Adam(model.parameters(), lr=lr)
尽管 PyTorch 会为用户进行反向传播,并且反向传播在概念上始终是相同的,但顺序网络的反向传播与我们在普通网络中看到的反向传播并不完全相似。 在这里,我们进行**时间上的反向传播****BPTT**)。 为了了解 BPTT 的工作原理,我们必须假设 RNN 是相似 RNN 单元的长重复单元,而不是将相同的输入视为通过同一 RNN 单元传递。
如果我们在句子中有五个单词,则我们有五个 RNN 单元,但是所有单元的权重都相同,并且当我们更新一个 RNN 单元的权重时,我们将更新所有 RNN 单元的权重。 现在,如果将输入分为五个时间步,每个单词位于每个时间步,则我们应该能够轻松描绘每个单词如何通过每个 RNN 单元。 在进行反向传播时,我们将遍历每个 RNN 单元,并在每个时间步长累积梯度。 更新一个 RNN 单元的权重也会更新其他 RNN 单元的权重。 由于所有五个单元都具有渐变,并且每次更新都会更新所有五个单元的权重,因此我们最终将每个单元的权重更新了五次。 无需进行五次更新,而是将梯度累加在一起并更新一次。 这是 BPTT。
如果我们在句子中有五个单词,则我们有五个 RNN 单元,但是所有单元的权重都相同,并且当我们更新一个 RNN 单元的权重时,我们将更新所有 RNN 单元的权重。 现在,如果将输入分为五个时间步,每个单词位于每个时间步,则我们应该能够轻松描绘每个单词如何通过每个 RNN 单元。 在进行反向传播时,我们将遍历每个 RNN 单元,并在每个时间步长累积梯度。 更新一个 RNN 单元的权重也会更新其他 RNN 单元的权重。 由于所有五个单元都具有梯度,并且每次更新都会更新所有五个单元的权重,因此我们最终将每个单元的权重更新了五次。 无需进行五次更新,而是将梯度累加在一起并更新一次。 这是 BPTT。
### 高级 RNN
......
# 使用 PyTorch 进行深度学习:60 分钟的闪电战
# 使用 PyTorch 进行深度学习:60 分钟的闪电战
> 原文:<https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html>
......
# Tensors
# Tensors
> 原文:<https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#sphx-glr-beginner-blitz-tensor-tutorial-py>
......@@ -97,7 +97,7 @@ Zeros Tensor:
* * *
## 张量属性] [docs / modern-java-zh /
## 张量属性
张量属性描述了它们的形状,数据类型以及存储它们的设备。
......
# Torch.autograd 的简要介绍
# Torch.autograd 的简要介绍
> 原文:<https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py>
`torch.autograd`是 PyTorch 的自动差分引擎,可为神经网络训练提供支持。 在本节中,您将获得有关 autograd 如何帮助神经网络训练的概念性理解。
## 背景] [docs / modern-java-zh /
## 背景
神经网络(NN)是在某些输入数据上执行的嵌套函数的集合。 这些功能由*参数*(由权重和偏差组成)定义,这些参数在 PyTorch 中存储在张量中。
......@@ -61,7 +61,7 @@ optim.step() #gradient descent
## Autograd 的差异
让我们来看看`autograd`如何收集渐变。 我们用`requires_grad=True`创建两个张量`a``b`。 这向`autograd`发出信号,应跟踪对它们的所有操作。
让我们来看看`autograd`如何收集梯度。 我们用`requires_grad=True`创建两个张量`a``b`。 这向`autograd`发出信号,应跟踪对它们的所有操作。
```py
import torch
......@@ -98,7 +98,7 @@ Q.backward(gradient=external_grad)
```
渐变现在沉积在`a.grad``b.grad`
梯度现在沉积在`a.grad``b.grad`
```py
# check if collected gradients are correct
......@@ -156,11 +156,11 @@ tensor([True, True])
**DAG 在 PyTorch 中是动态的**。要注意的重要一点是,图形是从头开始重新创建的; 在每个`.backward()`调用之后,autograd 开始填充新图。 这正是允许您在模型中使用控制流语句的原因。 您可以根据需要在每次迭代中更改形状,大小和操作。
### 从 DAG 中排除] [docs / modern-java-zh /
### 从 DAG 中排除
`torch.autograd`跟踪所有将其`requires_grad`标志设置为`True`的张量的操作。 对于不需要梯度的张量,将此属性设置为`False`会将其从梯度计算 DAG 中排除。
即使只有一个输入张量具有`requires_grad=True`,操作的输出张量也将需要渐变
即使只有一个输入张量具有`requires_grad=True`,操作的输出张量也将需要梯度
```py
x = torch.rand(5, 5)
......
# 神经网络
# 神经网络
> 原文:<https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-neural-networks-tutorial-py>
......@@ -20,10 +20,10 @@
* 遍历输入数据集
* 通过网络处理输入
* 计算损失(输出正确的距离有多远)
*渐变传播回网络参数
*梯度传播回网络参数
* 通常使用简单的更新规则来更新网络的权重:`weight = weight - learning_rate * gradient`
## 定义网络] [docs / modern-java-zh /
## 定义网络
让我们定义这个网络:
......@@ -137,10 +137,10 @@ out.backward(torch.randn(1, 10))
**回顾**
* `torch.Tensor`-一个*多维数组*,支持诸如`backward()`的自动分级操作。 同样,保持相对于张量的梯度。
* `torch.Tensor`-一个*多维数组*,支持诸如`backward()`的自动微分操作。 同样,保持相对于张量的梯度。
* `nn.Module`-神经网络模块。 *封装参数*的便捷方法,并带有将其移动到 GPU,导出,加载等的帮助器。
* `nn.Parameter`-一种张量,即将其分配时,`Module`的属性时自动注册为参数。
* `autograd.Function`-实现自动微分操作的正向和反向定义。 每个`Tensor`操作都会创建至少一个`Function`节点,该节点连接到创建`Tensor`的函数,并且对其历史记录进行编码
* `nn.Parameter`-一种张量,即将其分配`Module`的属性时,自动注册为参数。
* `autograd.Function`-实现自动微分操作的正向和反向定义。 每个`Tensor`操作都会创建至少一个`Function`节点,该节点连接到创建`Tensor`的函数,并且编码其历史记录
**目前为止,我们涵盖了**
......@@ -208,9 +208,9 @@ print(loss.grad_fn.next_functions[0][0].next_functions[0][0]) # ReLU
```
## 反向传播] [docs / modern-java-zh /
## 反向传播
要反向传播错误,我们要做的只是对`loss.backward()`。 不过,您需要清除现有的渐变,否则渐变将累积到现有的渐变中。
要反向传播错误,我们要做的只是对`loss.backward()`。 不过,您需要清除现有的梯度,否则梯度将累积到现有的梯度中。
现在,我们将其称为`loss.backward()`,然后看一下向后前后 conv1 的偏差梯度。
......
......@@ -24,7 +24,7 @@
cifar10
## 训练图像分类器] [docs / modern-java-zh /
## 训练图像分类器
我们将按顺序执行以下步骤:
......@@ -220,7 +220,7 @@ torch.save(net.state_dict(), PATH)
有关保存 PyTorch 模型的更多详细信息,请参见此处的[](https://pytorch.org/docs/stable/notes/serialization.html)
### 5.根据测试数据测试网络] [docs / modern-java-zh /
### 5.根据测试数据测试网络
我们已经在训练数据集中对网络进行了 2 次训练。 但是我们需要检查网络是否学到了什么。
......@@ -390,14 +390,14 @@ inputs, labels = data[0].to(device), data[1].to(device)
与 CPU 相比,为什么我没有注意到 MASSIVE 加速? 因为您的网络真的很小。
**练习:**尝试增加网络的宽度(第一个`nn.Conv2d`的参数 2 和第二个`nn.Conv2d`的参数 1 –它们必须是相同的数字),看看您可以提高哪种速度 得到。
**练习**尝试增加网络的宽度(第一个`nn.Conv2d`的参数 2 和第二个`nn.Conv2d`的参数 1 –它们必须是相同的数字),看看您可以提高哪种速度 得到。
**已实现的目标**
* 全面了解 PyTorch 的 Tensor 库和神经网络。
* 训练一个小型神经网络对图像进行分类
## 在多个 GPU 上进行训练] [docs / modern-java-zh /
## 在多个 GPU 上进行训练
如果您想使用所有 GPU 来获得更大的大规模加速,请查看[可选:数据并行](data_parallel_tutorial.html)
......
# 通过示例学习 PyTorch
# 通过示例学习 PyTorch
> 原文:<https://pytorch.org/tutorials/beginner/pytorch_with_examples.html>
......@@ -22,7 +22,7 @@ PyTorch 的核心是提供两个主要功能:
* [张量](#tensors)
* [热身:numpy](#warm-up-numpy)
* [PyTorch:张量](#pytorch-tensors)
* [自动分级](#autograd)
* [自动微分](#autograd)
* [PyTorch:张量和自定等级](#pytorch-tensors-and-autograd)
* [PyTorch:定义新的 autograd 功能](#pytorch-defining-new-autograd-functions)
* [<cite>nn</cite> 模块](#nn-module)
......@@ -32,7 +32,7 @@ PyTorch 的核心是提供两个主要功能:
* [PyTorch:控制流+权重共享](#pytorch-control-flow-weight-sharing)
* [范例](#examples)
* [张量](#id1)
* [自动分级](#id2)
* [自动微分](#id2)
* [<cite>nn</cite> 模块](#id3)
## [张量](#id12)
......@@ -90,7 +90,7 @@ print(f'Result: y = {a} + {b} x + {c} x^2 + {d} x^3')
Numpy 是一个很棒的框架,但是它不能利用 GPU 来加速其数值计算。 对于现代深度神经网络,GPU 通常会提供 [50 倍或更高](https://github.com/jcjohnson/cnn-benchmarks)的加速,因此遗憾的是,numpy 不足以实现现代深度学习。
在这里,我们介绍最基本的 PyTorch 概念:**张量**。 PyTorch 张量在概念上与 numpy 数组相同:张量是 n 维数组,PyTorch 提供了许多在这些张量上进行操作的功能。 在幕后,张量可以跟踪计算图和渐变,但它们也可用作科学计算的通用工具。
在这里,我们介绍最基本的 PyTorch 概念:**张量**。 PyTorch 张量在概念上与 numpy 数组相同:张量是 n 维数组,PyTorch 提供了许多在这些张量上进行操作的功能。 在幕后,张量可以跟踪计算图和梯度,但它们也可用作科学计算的通用工具。
与 numpy 不同,PyTorch 张量可以利用 GPU 加速其数字计算。 要在 GPU 上运行 PyTorch Tensor,您只需要指定正确的设备即可。
......@@ -218,7 +218,7 @@ print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3'
### [PyTorch:定义新的 autograd 函数](#id17)
在幕后,每个原始的 autograd 运算符实际上都是在 Tensor 上运行的两个函数。 **正向**函数从输入张量计算输出张量。 **向后**函数接收相对于某个标量值的输出张量的梯度,并计算相对于相同标量值的输入张量的梯度。
在幕后,每个原始的 autograd 运算符实际上都是在 Tensor 上运行的两个函数。 **正向**函数从输入张量计算输出张量。 **反向**函数接收相对于某个标量值的输出张量的梯度,并计算相对于相同标量值的输入张量的梯度。
在 PyTorch 中,我们可以通过定义`torch.autograd.Function`的子类并实现`forward``backward`函数来轻松定义自己的 autograd 运算符。 然后,我们可以通过构造实例并像调用函数一样调用新的 autograd 运算符,并传递包含输入数据的张量。
......
# 热身:numpy
# 热身:numpy
> 原文:<https://pytorch.org/tutorials/beginner/examples_tensor/polynomial_numpy.html#sphx-glr-beginner-examples-tensor-polynomial-numpy-py>
......
# PyTorch:张量
# PyTorch:张量
> 原文:<https://pytorch.org/tutorials/beginner/examples_tensor/polynomial_tensor.html#sphx-glr-beginner-examples-tensor-polynomial-tensor-py>
......
# PyTorch:张量和 autograd
# PyTorch:张量和 autograd
> 原文:<https://pytorch.org/tutorials/beginner/examples_autograd/polynomial_autograd.html#sphx-glr-beginner-examples-autograd-polynomial-autograd-py>
......
# PyTorch:定义新的 autograd 函数
# PyTorch:定义新的 autograd 函数
> 原文:<https://pytorch.org/tutorials/beginner/examples_autograd/polynomial_custom_function.html#sphx-glr-beginner-examples-autograd-polynomial-custom-function-py>
......
# PyTorch:nn
# PyTorch:nn
> 原文:<https://pytorch.org/tutorials/beginner/examples_nn/polynomial_nn.html#sphx-glr-beginner-examples-nn-polynomial-nn-py>
......
# PyTorch:优化
# PyTorch:优化
> 原文:<https://pytorch.org/tutorials/beginner/examples_nn/polynomial_optim.html#sphx-glr-beginner-examples-nn-polynomial-optim-py>
......
# PyTorch:自定义 nn 模块
# PyTorch:自定义 nn 模块
> 原文:<https://pytorch.org/tutorials/beginner/examples_nn/polynomial_module.html#sphx-glr-beginner-examples-nn-polynomial-module-py>
......
# PyTorch:控制流+权重共享
# PyTorch:控制流+权重共享
> 原文:<https://pytorch.org/tutorials/beginner/examples_nn/dynamic_net.html#sphx-glr-beginner-examples-nn-dynamic-net-py>
......
# torch.nn 到底是什么?
# torch.nn 到底是什么?
> 原文:<https://pytorch.org/tutorials/beginner/nn_tutorial.html>
......@@ -10,7 +10,7 @@ PyTorch 提供设计精美的模块和类 [torch.nn](https://pytorch.org/docs/st
**本教程假定您已经安装了 PyTorch,并且熟悉张量操作的基础知识。** (如果您熟悉 Numpy 数组操作,将会发现此处使用的 PyTorch 张量操作几乎相同)。
## MNIST 数据设置] [docs / modern-java-zh /
## MNIST 数据设置
我们将使用经典的 [MNIST](http://deeplearning.net/data/mnist/) 数据集,该数据集由手绘数字的黑白图像组成(0 到 9 之间)。
......@@ -100,9 +100,9 @@ tensor(0) tensor(9)
首先,我们仅使用 PyTorch 张量操作创建模型。 我们假设您已经熟悉神经网络的基础知识。 (如果不是,则可以在 [course.fast.ai](https://course.fast.ai) 中学习它们)。
PyTorch 提供了创建随机或零填充张量的方法,我们将使用它们来为简单的线性模型创建权重和偏差。 这些只是常规张量,还有一个非常特殊的附加值:我们告诉 PyTorch 它们需要渐变。 这使 PyTorch 记录了在张量上完成的所有操作,因此它可以在反向传播*时自动计算*的梯度!
PyTorch 提供了创建随机或零填充张量的方法,我们将使用它们来为简单的线性模型创建权重和偏差。 这些只是常规张量,还有一个非常特殊的附加值:我们告诉 PyTorch 它们需要梯度。 这使 PyTorch 记录了在张量上完成的所有操作,因此它可以在反向传播*时自动计算*的梯度!
对于权重,我们在初始化之后设置`requires_grad` **,因为我们不希望该步骤包含在渐变中。 (请注意,PyTorch 中的尾随`_`表示该操作是原地执行的。)**
**对于权重,我们在初始化之后设置`requires_grad`,因为我们不希望该步骤包含在梯度中。 (请注意,PyTorch 中的尾随`_`表示该操作是原地执行的。)**
注意
......@@ -207,7 +207,7 @@ tensor(0.0938)
现在,我们使用这些梯度来更新权重和偏差。 我们在`torch.no_grad()`上下文管理器中执行此操作,因为我们不希望在下一步的梯度计算中记录这些操作。 您可以在上阅读有关 PyTorch 的 Autograd 如何记录操作[的更多信息。](https://pytorch.org/docs/stable/notes/autograd.html)
然后,将梯度设置为零,以便为下一个循环做好准备。 否则,我们的渐变会记录所有已发生操作的运行记录(即`loss.backward()` *将*渐变添加到已存储的内容中,而不是替换它们)。
然后,将梯度设置为零,以便为下一个循环做好准备。 否则,我们的梯度会记录所有已发生操作的运行记录(即`loss.backward()` *将*梯度添加到已存储的内容中,而不是替换它们)。
小费
......@@ -432,7 +432,7 @@ tensor(0.0824, grad_fn=<NllLossBackward>)
```
## 使用优化重构] [docs / modern-java-zh /
## 使用优化重构
Pytorch 还提供了一个包含各种优化算法的软件包`torch.optim`。 我们可以使用优化器中的`step`方法采取向前的步骤,而不是手动更新每个参数。
......@@ -606,13 +606,13 @@ tensor(0.0821, grad_fn=<NllLossBackward>)
得益于 Pytorch 的`nn.Module``nn.Parameter``Dataset``DataLoader`,我们的训练循环现在变得更小,更容易理解。 现在,让我们尝试添加在实践中创建有效模型所需的基本功能。
## 添加验证] [docs / modern-java-zh /
## 添加验证
在第 1 节中,我们只是试图建立一个合理的训练循环以用于我们的训练数据。 实际上,您**始终**也应该具有[验证集](https://www.fast.ai/2017/11/13/validation-sets/),以便识别您是否过拟合。
对训练数据进行改组对于[很重要,](https://www.quora.com/Does-the-order-of-training-data-matter-when-training-neural-networks)对于防止批量与过拟合之间的相关性很重要。 另一方面,无论我们是否改组验证集,验证损失都是相同的。 由于改组需要花费更多时间,因此改组验证数据没有任何意义。
我们将验证集的批量大小设为训练集的两倍。 这是因为验证集不需要反向传播,因此占用的内存更少(不需要存储渐变)。 我们利用这一优势来使用更大的批量,并更快地计算损失。
我们将验证集的批量大小设为训练集的两倍。 这是因为验证集不需要反向传播,因此占用的内存更少(不需要存储梯度)。 我们利用这一优势来使用更大的批量,并更快地计算损失。
```py
train_ds = TensorDataset(x_train, y_train)
......
# TorchVision 对象检测微调教程
# TorchVision 对象检测微调教程
> 原文:<https://pytorch.org/tutorials/intermediate/torchvision_tutorial.html>
......@@ -139,7 +139,7 @@ class PennFudanDataset(object):
这就是数据集的全部内容。 现在,我们定义一个可以对该数据集执行预测的模型。
## 定义模型] [docs / modern-java-zh /
## 定义模型
在本教程中,我们将基于 [Faster R-CNN](https://arxiv.org/abs/1506.01497) 使用 [Mask R-CNN](https://arxiv.org/abs/1703.06870) 。 更快的 R-CNN 是可预测图像中潜在对象的边界框和类分数的模型。
......@@ -153,7 +153,7 @@ Mask R-CNN 在 Faster R-CNN 中增加了一个分支,该分支还可以预测
在以下各节中,让我们看看如何做一个或另一个。
### 1-通过预训练模型进行微调] [docs / modern-java-zh /
### 1-通过预训练模型进行微调
假设您要从在 COCO 上经过预训练的模型开始,并希望针对您的特定班级对其进行微调。 这是一种可行的方法:
......@@ -174,7 +174,7 @@ model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
```
### 2-修改模型以添加其他主干] [docs / modern-java-zh /
### 2-修改模型以添加其他主干
```py
import torchvision
......
......@@ -81,7 +81,7 @@ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
```
### 可视化一些图像] [docs / modern-java-zh /
### 可视化一些图像
让我们可视化一些训练图像,以了解数据扩充。
......@@ -577,7 +577,7 @@ plt.show()
![../_img/sphx_glr_transfer_learning_tutorial_003.png](img/54625e60404f9c98f34cf32ca56bb118.png)
## 进一步学习] [docs / modern-java-zh /
## 进一步学习
如果您想了解有关迁移学习的更多信息,请查看我们的[计算机视觉教程的量化迁移学习](https://pytorch.org/tutorials/intermediate/quantized_transfer_learning_tutorial.html)
......
......@@ -42,7 +42,7 @@ import matplotlib.pyplot as plt
在本节中,我们将讨论本教程的输入参数,定义受到攻击的模型,然后编写攻击代码并运行一些测试。
### 输入] [docs / modern-java-zh /
### 输入
本教程只有三个输入,定义如下:
......
# DCGAN 教程
# DCGAN 教程
> 原文:<https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html>
......@@ -64,7 +64,7 @@ Random Seed: 999
```
## 输入] [docs / modern-java-zh /
## 输入
让我们为跑步定义一些输入:
......@@ -379,7 +379,7 @@ optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))
```
### 训练] [docs / modern-java-zh /
### 训练
最后,既然我们已经定义了 GAN 框架的所有部分,我们就可以对其进行训练。 请注意,训练 GAN 某种程度上是一种艺术形式,因为不正确的超参数设置会导致模式崩溃,而对失败的原因几乎没有解释。 在这里,我们将严格遵循 Goodfellow 论文中的算法 1,同时遵守 [ganhacks](https://github.com/soumith/ganhacks) 中显示的一些最佳做法。 即,我们将“为真实和伪造构建不同的小批量”图像,并调整 G 的目标函数以最大化\(logD(G(z))\)。 训练分为两个主要部分。 第 1 部分更新了鉴别器,第 2 部分更新了生成器。
......@@ -717,7 +717,7 @@ plt.show()
![../_img/sphx_glr_dcgan_faces_tutorial_004.png](img/c0f8a413c1f6dd23bb137d8adff1adda.png)
## 下一步去哪里] [docs / modern-java-zh /
## 下一步去哪里
我们已经走到了旅程的尽头,但是您可以从这里到达几个地方。 你可以:
......
# 音频 I / O 和 torchaudio 的预处理
# 音频 I / O 和 torchaudio 的预处理
> 原文:<https://pytorch.org/tutorials/beginner/audio_preprocessing_tutorial.html>
......@@ -233,7 +233,7 @@ Median relative difference between original and MuLaw reconstucted signals: 1.28
```
## 功能] [docs / modern-java-zh /
## 功能
上面看到的转换依赖于较低级别的无状态函数进行计算。 这些功能在`torchaudio.functional`下可用。 完整列表在此处[可用,包括:](https://pytorch.org/audio/functional.html)
......
......@@ -8,7 +8,7 @@ PyTorch 1.2 版本包括一个基于纸张[的标准转换器模块。 事实证
![../_img/transformer_architecture.jpg](img/4b79dddf1ff54b9384754144d8246d9b.png)
## 定义模型] [docs / modern-java-zh /
## 定义模型
在本教程中,我们将在语言建模任务上训练`nn.TransformerEncoder`模型。 语言建模任务是为给定单词(或单词序列)遵循单词序列的可能性分配概率。 令牌序列首先传递到嵌入层,然后传递到位置编码层以说明单词的顺序(有关更多详细信息,请参见下一段)。 `nn.TransformerEncoder`由多层 [nn.TransformerEncoderLayer](https://pytorch.org/docs/master/nn.html?highlight=transformerencoderlayer#torch.nn.TransformerEncoderLayer) 组成。 与输入序列一起,还需要一个正方形的注意掩码,因为`nn.TransformerEncoder`中的自注意层仅允许出现在该序列中的较早位置。 对于语言建模任务,应屏蔽将来头寸上的所有标记。 为了获得实际的单词,将`nn.TransformerEncoder`模型的输出发送到最终的 Linear 层,然后是 log-Softmax 函数。
......@@ -298,7 +298,7 @@ for epoch in range(1, epochs + 1):
```
## 使用测试数据集评估模型] [docs / modern-java-zh /
## 使用测试数据集评估模型
应用最佳模型以检查测试数据集的结果。
......
# 从零开始的 NLP:使用字符级 RNN 对名称进行分类
# 从零开始的 NLP:使用字符级 RNN 对名称进行分类
> 原文:<https://pytorch.org/tutorials/intermediate/char_rnn_classification_tutorial.html>
......@@ -164,7 +164,7 @@ torch.Size([5, 1, 57])
## 创建网络
在进行自动分级之前,在 Torch 中创建一个循环神经网络涉及在多个时间步长上克隆层的参数。 层保留了隐藏状态和渐变,这些层现在完全由图形本身处理。 这意味着您可以非常“纯”的方式将 RNN 用作常规前馈层。
在进行自动微分之前,在 Torch 中创建一个循环神经网络涉及在多个时间步长上克隆层的参数。 层保留了隐藏状态和梯度,这些层现在完全由图形本身处理。 这意味着您可以非常“纯”的方式将 RNN 用作常规前馈层。
该 RNN 模块(主要从 PyTorch for Torch 用户教程的[复制)只有两个线性层,它们在输入和隐藏状态下运行,在输出之后是 LogSoftmax 层。](https://pytorch.org/tutorials/beginner/former_torchies/nn_tutorial.html#example-2-recurrent-net)
......@@ -230,7 +230,7 @@ tensor([[-2.8934, -2.7991, -2.8549, -2.8915, -2.9122, -2.9010, -2.8979, -2.8875,
如您所见,输出为`<1 x n_categories>`张量,其中每个项目都是该类别的可能性(可能性更大)。
## 训练] [docs / modern-java-zh /
## 训练
### 准备训练
......@@ -400,7 +400,7 @@ for iter in range(1, n_iters + 1):
```
### 绘制结果] [docs / modern-java-zh /
### 绘制结果
`all_losses`绘制历史损失可显示网络学习情况:
......@@ -468,7 +468,7 @@ plt.show()
您可以从主轴上挑出一些亮点,以显示它猜错了哪些语言,例如 中文(朝鲜语)和西班牙语(意大利语)。 它似乎与希腊语搭配得很好,而与英语搭配得很差(可能是因为与其他语言重叠)。
### 在用户输入上运行] [docs / modern-java-zh /
### 在用户输入上运行
```py
def predict(input_line, n_predictions=3):
......
......@@ -150,7 +150,7 @@ class RNN(nn.Module):
```
## 训练] [docs / modern-java-zh /
## 训练
### 准备训练
......
# 从零开始的 NLP:从序列到序列网络的翻译和注意
# 从零开始的 NLP:从序列到序列网络的翻译和注意
> 原文:<https://pytorch.org/tutorials/intermediate/seq2seq_translation_tutorial.html>
......@@ -374,7 +374,7 @@ class AttnDecoderRNN(nn.Module):
还有其他形式的注意,可以通过使用相对位置方法来解决长度限制问题。 在[基于注意力的神经机器翻译的有效方法](https://arxiv.org/abs/1508.04025)中阅读“本地注意力”。
## 训练] [docs / modern-java-zh /
## 训练
### 准备训练数据
......@@ -699,7 +699,7 @@ evaluateRandomly(encoder1, attn_decoder1)
```
### 可视化注意] [docs / modern-java-zh /
### 可视化注意
注意机制的一个有用特性是其高度可解释的输出。 因为它用于加权输入序列的特定编码器输出,所以我们可以想象一下在每个时间步长上网络最关注的位置。
......
......@@ -46,7 +46,7 @@ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
```
## 定义模型] [docs / modern-java-zh /
## 定义模型
该模型由 [EmbeddingBag](https://pytorch.org/docs/stable/nn.html?highlight=embeddingbag#torch.nn.EmbeddingBag) 层和线性层组成(请参见下图)。 `nn.EmbeddingBag`计算嵌入“袋”的平均值。 此处的文本条目具有不同的长度。 `nn.EmbeddingBag`此处不需要填充,因为文本长度以偏移量保存。
......@@ -164,7 +164,7 @@ def test(data_):
```
## 分割数据集并运行模型] [docs / modern-java-zh /
## 分割数据集并运行模型
由于原始的 AG_NEWS 没有有效的数据集,因此我们将训练数据集分为训练/有效集,其分割比率为 0.95(训练)和 0.05(有效)。 在这里,我们在 PyTorch 核心库中使用 [torch.utils.data.dataset.random_split](https://pytorch.org/docs/stable/data.html?highlight=random_split#torch.utils.data.random_split) 函数。
......@@ -263,7 +263,7 @@ Loss: 0.0000(valid) | Acc: 91.0%(valid)
```
## 使用测试数据集评估模型] [docs / modern-java-zh /
## 使用测试数据集评估模型
```py
print('Checking the results of test dataset...')
......@@ -287,7 +287,7 @@ Loss: 0.0237(test) | Acc: 90.5%(test)
```
## 测试随机新闻] [docs / modern-java-zh /
## 测试随机新闻
使用到目前为止最好的模型并测试高尔夫新闻。 标签信息在中可用[](https://pytorch.org/text/datasets.html?highlight=ag_news#torchtext.datasets.AG_NEWS)
......
# TorchText 语言翻译
# TorchText 语言翻译
> 原文:<https://pytorch.org/tutorials/beginner/torchtext_translation_tutorial.html>
......
# 强化学习(DQN)教程
# 强化学习(DQN)教程
> 原文:<https://pytorch.org/tutorials/intermediate/reinforcement_q_learning.html>
......@@ -97,7 +97,7 @@ class ReplayMemory(object):
现在,让我们定义我们的模型。 但是首先,让我们快速回顾一下 DQN 是什么。
## DQN 算法] [docs / modern-java-zh /
## DQN 算法
我们的环境是确定性的,因此为简单起见,此处介绍的所有方程式也都确定性地制定。 在强化学习文献中,它们还将包含对环境中随机转变的期望。
......@@ -204,7 +204,7 @@ plt.show()
```
## 训练] [docs / modern-java-zh /
## 训练
### 超参数和实用程序
......
# 训练 Mario 播放 RL 代理
# 训练 Mario 播放 RL 代理
> 原文:<https://pytorch.org/tutorials/intermediate/mario_rl_tutorial.html>
......@@ -161,7 +161,7 @@ env = FrameStack(env, num_stack=4)
![picture](img/ad48ffbd1cfc0475d744b8b89a0d962a.png)
## 代理] [docs / modern-java-zh /
## 代理
我们创建一个类`Mario`来表示我们的代理在游戏中。 马里奥应该能够:
......@@ -373,7 +373,7 @@ class MarioNet(nn.Module):
由于我们不知道下一个动作\(a'\)是什么,因此我们在下一个状态\(s'\)中使用动作\(a'\)最大化\(Q_ {online} \)
请注意,我们在`td_target()`上使用了 [@ torch.no_grad()](https://pytorch.org/docs/stable/generated/torch.no_grad.html#no-grad)装饰器来禁用渐变计算(因为我们无需在\(\ theta_ {target} \)上进行反向传播。)
请注意,我们在`td_target()`上使用了 [@ torch.no_grad()](https://pytorch.org/docs/stable/generated/torch.no_grad.html#no-grad)装饰器来禁用梯度计算(因为我们无需在\(\ theta_ {target} \)上进行反向传播。)
```py
class Mario(Mario):
......@@ -443,7 +443,7 @@ class Mario(Mario):
```
#### 全部放在一起] [docs / modern-java-zh /
#### 全部放在一起
```py
class Mario(Mario):
......
# 通过带有 Flask 的 REST API 在 Python 中部署 PyTorch
# 通过带有 Flask 的 REST API 在 Python 中部署 PyTorch
> 原文:<https://pytorch.org/tutorials/intermediate/flask_rest_api_tutorial.html>
......@@ -24,7 +24,7 @@
```
## 依赖项] [docs / modern-java-zh /
## 依赖项
通过运行以下命令来安装所需的依赖项:
......@@ -77,7 +77,7 @@ def predict():
```
## 推论] [docs / modern-java-zh /
## 推论
在下一部分中,我们将重点介绍编写推理代码。 这将涉及两部分,第一部分是准备图像,以便可以将其馈送到 DenseNet;第二部分,我们将编写代码以从模型中获取实际的预测。
......
# TorchScript 简介
# TorchScript 简介
> 原文:<https://pytorch.org/tutorials/beginner/Intro_to_TorchScript_tutorial.html>
......@@ -166,13 +166,13 @@ MyCell(
我们再次重新定义了 MyCell 类,但是在这里我们定义了`MyDecisionGate`。 该模块利用**控制流**。 控制流包括循环和`if`语句之类的内容。
给定完整的程序表示形式,许多框架都采用计算符号派生的方法。 但是,在 PyTorch 中,我们使用渐变色带。 我们记录发生的操作,并在计算派生时向后回放。 这样,框架不必为语言中的所有构造显式定义派生类。
给定完整的程序表示形式,许多框架都采用计算符号派生的方法。 但是,在 PyTorch 中,我们使用梯度色带。 我们记录发生的操作,并在计算派生时向后回放。 这样,框架不必为语言中的所有构造显式定义派生类。
![How autograd works](img/beccc5ac5df1571304e11d6b12772a99.png)
自动毕业的工作原理
## TorchScript 的基础] [docs / modern-java-zh /
## TorchScript 的基础
现在,让我们以正在运行的示例为例,看看如何应用 TorchScript。
......@@ -285,7 +285,7 @@ print(traced_cell(x, h))
```
## 使用脚本转换模块] [docs / modern-java-zh /
## 使用脚本转换模块
有一个原因是我们使用了模块的第二版,而不是使用带有大量控制流的子模块。 现在让我们检查一下:
......@@ -361,7 +361,7 @@ traced_cell(x, h)
```
### 混合脚本和跟踪] [docs / modern-java-zh /
### 混合脚本和跟踪
在某些情况下,需要使用跟踪而不是脚本(例如,一个模块具有许多基于不变的 Python 值做出的架构决策,而我们不希望它们出现在 TorchScript 中)。 在这种情况下,可以通过跟踪来编写脚本:`torch.jit.script`将内联被跟踪模块的代码,而跟踪将内联脚本模块的代码。
......
# (原型)PyTorch 中的命名张量简介
# (原型)PyTorch 中的命名张量简介
> 原文:<https://pytorch.org/tutorials/intermediate/named_tensor_tutorial.html>
......@@ -194,7 +194,7 @@ print(img0.names)
```
### 名称推断] [docs / modern-java-zh /
### 名称推断
名称在称为**名称推断**的两步过程中在操作上传播:
......@@ -240,7 +240,7 @@ print((x + y).names)
大多数名称推断规则都很简单明了,但是其中一些可能具有意想不到的语义。 让我们来看看您可能会遇到的一对:广播和矩阵乘法。
#### 广播] [docs / modern-java-zh /
#### 广播
命名张量不会改变广播行为; 他们仍然按位置广播。 但是,在检查两个尺寸是否可以广播时,PyTorch 还会检查这些尺寸的名称是否匹配。
......@@ -287,7 +287,7 @@ print(new_state.names)
接下来,我们将介绍命名张量启用的两个新行为:按名称的显式广播以及按名称的展平和展平尺寸
### 新行为:按名称明确广播] [docs / modern-java-zh /
### 新行为:按名称明确广播
有关使用多个维度的主要抱怨之一是需要`unsqueeze`“虚拟”维度,以便可以进行操作。 例如,在之前的每批比例示例中,使用未命名的张量,我们将执行以下操作:
......@@ -340,7 +340,7 @@ print(imgs.names)
### Autograd 支持
Autograd 当前会忽略所有张量上的名称,只是将它们视为常规张量。 梯度计算是正确的,但是我们失去了名称赋予我们的安全性。 在路线图上引入名称以自动分级的处理。
Autograd 当前会忽略所有张量上的名称,只是将它们视为常规张量。 梯度计算是正确的,但是我们失去了名称赋予我们的安全性。 在路线图上引入名称以自动微分的处理。
```py
x = torch.randn(3, names=('D',))
......@@ -372,7 +372,7 @@ tensor([0.5398, 0.7907, 0.7784])
```
### 其他受支持的(和不受支持的)功能] [docs / modern-java-zh /
### 其他受支持的(和不受支持的)功能
[有关 1.3 发行版支持的功能的详细分类,请参见此处](https://pytorch.org/docs/stable/named_tensor.html)
......@@ -402,7 +402,7 @@ NYI: Named tensors are currently unsupported in TorchScript. As a workaround pl
解决方法是,在使用尚不支持命名张量的任何东西之前,请通过`tensor = tensor.rename(None)`删除名称。
### 更长的例子:多头关注] [docs / modern-java-zh /
### 更长的例子:多头关注
现在,我们将通过一个完整的示例来实现一个常见的 PyTorch `nn.Module`:多头注意。 我们假设读者已经熟悉多头注意; 要进行复习,请查看[此说明](https://nlp.seas.harvard.edu/2018/04/03/attention.html)[此说明](http://jalammar.github.io/illustrated-transformer/)
......
# (beta)在 PyTorch 中引导最后的内存格式
# (beta)在 PyTorch 中引导最后的内存格式
> 原文:<https://pytorch.org/tutorials/intermediate/memory_format_tutorial.html>
......@@ -204,7 +204,7 @@ True
```
## 性能提升] [docs / modern-java-zh /
## 性能提升
在具有 Tensor Cores 支持的 Nvidia 硬件上观察到了最大的性能提升。 在运行 [Nvidia](https://github.com/NVIDIA/apex) 提供的 AMP(自动混合精度)训练脚本时,我们可以将性能提高 22% 以上。
......
# 使用 PyTorch C ++前端
# 使用 PyTorch C ++前端
> 原文:<https://pytorch.org/tutorials/advanced/cpp_frontend.html>
......@@ -151,11 +151,11 @@ root@fa350df05ecf:/home/build# ./dcgan
现在我们已经配置了基本环境,我们可以深入研究本教程中更有趣的部分。 首先,我们将讨论如何在 C ++前端中定义模块并与之交互。 我们将从基本的小规模示例模块开始,然后使用 C ++前端提供的广泛的内置模块库来实现全面的 GAN。
### 模块 API 基础] [docs / modern-java-zh /
### 模块 API 基础
与 Python 界面一致,基于 C ++前端的神经网络由称为*模块*的可重用构建块组成。 有一个基础模块类,所有其他模块都从该基础类派生。 在 Python 中,此类为`torch.nn.Module`,在 C ++中为`torch::nn::Module`。 除了实现模块封装的算法的`forward()`方法之外,模块通常还包含以下三种子对象中的任何一种:参数,缓冲区和子模块。
参数和缓冲区以张量的形式存储状态。 参数记录渐变,而缓冲区不记录。 参数通常是神经网络的可训练权重。 缓冲区的示例包括批量标准化的均值和方差。 为了重用特定的逻辑和状态块,PyTorch API 允许嵌套模块。 嵌套模块称为*子模块*
参数和缓冲区以张量的形式存储状态。 参数记录梯度,而缓冲区不记录。 参数通常是神经网络的可训练权重。 缓冲区的示例包括批量标准化的均值和方差。 为了重用特定的逻辑和状态块,PyTorch API 允许嵌套模块。 嵌套模块称为*子模块*
参数,缓冲区和子模块必须显式注册。 注册后,可以使用`parameters()``buffers()`之类的方法来检索整个(嵌套)模块层次结构中所有参数的容器。 类似地,使用`to(...)`之类的方法,例如 `to(torch::kCUDA)`将所有参数和缓冲区从 CPU 移到 CUDA 内存,在整个模块层次结构上工作。
......@@ -332,7 +332,7 @@ linear.bias: -0.0250
[`torch::nn::Module`的文档](https://pytorch.org/cppdocs/api/classtorch_1_1nn_1_1_module.html#exhale-class-classtorch-1-1nn-1-1-module)包含在模块层次结构上运行的方法的完整列表。
#### 在转发模式下运行网络] [docs / modern-java-zh /
#### 在转发模式下运行网络
要使用 C ++执行网络,我们只需调用我们自己定义的`forward()`方法:
......@@ -758,7 +758,7 @@ Scanning dependencies of target dcgan
```
## 移至 GPU] [docs / modern-java-zh /
## 移至 GPU
虽然我们当前的脚本可以在 CPU 上正常运行,但是我们都知道卷积在 GPU 上要快得多。 让我们快速讨论如何将训练转移到 GPU 上。 为此,我们需要做两件事:将 GPU 设备规范传递给我们分配给自己的张量,并通过`to()`方法将所有其他张量明确复制到 C ++前端中的所有张量和模块上。 实现这两者的最简单方法是在我们的训练脚本的顶层创建`torch::Device`的实例,然后将该设备传递给张量工厂功能,例如`torch::zeros``to()`方法。 我们可以从使用 CPU 设备开始:
......
# 自定义 C ++和 CUDA 扩展
# 自定义 C ++和 CUDA 扩展
> 原文:<https://pytorch.org/tutorials/advanced/cpp_extension.html>
......@@ -80,7 +80,7 @@ new_h, new_C = rnn(X, (h, C))
让我们看看如何使用 C ++扩展来实现 LLTM 的*融合*版本。 首先,我们使用 [ATen](https://github.com/zdevito/ATen) 库以普通的 C ++语言编写代码,该库为 PyTorch 的许多后端提供了强大的支持,并了解它如何使我们轻松转换 Python 代码。 然后,我们将模型的某些部分移至 CUDA 内核,以从 GPU 提供的大量并行处理中受益,从而进一步加快处理速度。
## 编写 C ++扩展] [docs / modern-java-zh /
## 编写 C ++扩展
C ++扩展有两种形式:它们可以使用`setuptools`提前构建,也可以通过`torch.utils.cpp_extension.load()`适时构建。 我们将从第一种方法开始,稍后再讨论后者。
......@@ -111,7 +111,7 @@ Extension(
`BuildExtension`执行许多必需的配置步骤,并检查和管理混合 C ++ / CUDA 扩展的混合编译。 这就是我们现在真正需要了解的有关构建 C ++扩展的全部信息! 现在让我们看一下`lltm.cpp`中 C ++扩展的实现。
### 编写 C ++ Op] [docs / modern-java-zh /
### 编写 C ++ Op
让我们开始以 C ++实现 LLTM! 我们需要向后传递的一项功能是 S 型导数。 这是一小段代码,用于讨论编写 C ++扩展时可供我们使用的总体环境:
......@@ -424,7 +424,7 @@ Forward: 349.335 us | Backward 443.523 us
我们已经可以看到前进功能的明显提速(超过 30% )。 对于后退功能,可以看到加速,尽管不是很大。 我在上面编写的后向通行证没有特别优化,并且肯定可以改进。 而且,PyTorch 的自动微分引擎可以自动并行化计算图,可以整体上使用更高效的操作流程,并且也可以用 C ++来实现,因此有望实现更快的速度。 不过,这是一个良好的开始。
#### GPU 设备上的性能] [docs / modern-java-zh /
#### GPU 设备上的性能
关于 PyTorch 的 *ATen* 后端的一个奇妙事实是,它抽象了您正在运行的计算设备。 这意味着我们为 CPU 编写的同一代码可以*也可以*在 GPU 上运行,并且各个操作将相应地分派到 GPU 优化的实现。 对于某些运算,例如矩阵乘法(例如`mm``addmm`),这是一个很大的胜利。 让我们看一下使用 CUDA 张量运行 C ++代码所获得的性能。 无需更改实现,我们只需要将张量从 Python 放入 GPU 内存,即可在创建时添加`device=cuda_device`参数,或者在创建后使用`.to(cuda_device)`
......@@ -478,7 +478,7 @@ Forward: 149.802 us | Backward 393.458 us
与非 CUDA 代码相比,这可以大大提高整体速度。 但是,通过编写自定义 CUDA 内核,我们可以从 C ++代码中获得更多性能,我们将很快深入其中。 在此之前,让我们讨论构建 C ++扩展的另一种方法。
### JIT 编译扩展] [docs / modern-java-zh /
### JIT 编译扩展
之前,我提到过有两种构建 C ++扩展的方法:使用`setuptools`或即时(JIT)。 在介绍了前者之后,让我们详细介绍后者。 JIT 编译机制通过调用 PyTorch API 中称为`torch.utils.cpp_extension.load()`的简单函数,为您提供了一种动态编译和加载扩展的方式。 对于 LLTM,这看起来像这样简单:
......@@ -942,7 +942,7 @@ std::vector<torch::Tensor> lltm_cuda_backward(
```
### 将 C ++ / CUDA 操作与 PyTorch 集成] [docs / modern-java-zh /
### 将 C ++ / CUDA 操作与 PyTorch 集成
同样,将支持 CUDA 的 op 与 PyTorch 集成非常简单。 如果要编写`setup.py`脚本,它可能看起来像这样:
......
# 使用自定义 C ++运算符扩展 TorchScript
# 使用自定义 C ++运算符扩展 TorchScript
> 原文:<https://pytorch.org/tutorials/advanced/torch_script_custom_ops.html>
......@@ -110,7 +110,7 @@ TORCH_LIBRARY(my_ops, m) {
现在,我们已经用 C ++实现了自定义运算符并编写了其注册代码,是时候将该运算符构建到一个(共享的)库中了,可以将其加载到 Python 中进行研究和实验,或者加载到 C ++中以在非 Python 中进行推理。 环境。 有多种方法可以使用纯 CMake 或`setuptools`之类的 Python 替代方法来构建我们的运算符。 为简洁起见,以下段落仅讨论 CMake 方法。 本教程的附录将深入探讨其他替代方法。
### 环境设置] [docs / modern-java-zh /
### 环境设置
我们需要安装 PyTorch 和 OpenCV。 实现这两者的最简单,最独立于平台的方法是通过 Conda:
......@@ -246,7 +246,7 @@ tensor([[0.0000, 0.3218, 0.4611, ..., 0.4636, 0.4636, 0.4636],
从这里开始,您可以在脚本或跟踪代码中使用自定义运算符,就像`torch`包中的其他函数一样。 实际上,诸如`torch.matmul`之类的“标准库”功能在很大程度上与自定义运算符使用相同的注册路径,这使得自定义运算符在 TorchScript 中的使用方式和位置方面真正成为一流公民。 (但是,区别之一是标准库函数具有自定义的 Python 自变量解析逻辑,与`torch.ops`自变量解析不同。)
### 在跟踪中使用自定义运算符] [docs / modern-java-zh /
### 在跟踪中使用自定义运算符
首先,将我们的运算符嵌入到跟踪函数中。 回想一下,为了进行跟踪,我们从一些原始的 Pytorch 代码开始:
......@@ -320,7 +320,7 @@ graph(%x.1 : Float(4:8, 8:1),
如此简单地将 TorchScript 自定义操作集成到跟踪的 PyTorch 代码中!
### 将自定义运算符与脚本一起使用] [docs / modern-java-zh /
### 将自定义运算符与脚本一起使用
除了跟踪之外,获得 PyTorch 程序的 TorchScript 表示形式的另一种方法是直接在 TorchScript 中编写代码*。 TorchScript 在很大程度上是 Python 语言的子集,它具有一些限制,使 TorchScript 编译器更容易推理程序。 您可以使用`@torch.jit.script`标记免费功能,使用`@torch.jit.script_method`标记类中的方法(也必须从`torch.jit.ScriptModule`派生),将常规 PyTorch 代码转换为 TorchScript。 有关 TorchScript 批注的更多详细信息,请参见此处的[。](https://pytorch.org/docs/master/jit.html)*
......@@ -714,7 +714,7 @@ print(torch.ops.my_ops.warp_perspective)
请注意,如果您在 Jupyter 笔记本中使用此功能,则不应多次执行单元格的注册,因为每次执行都会注册一个新库并重新注册自定义运算符。 如果需要重新执行它,请事先重新启动笔记本的 Python 内核。
### 使用 Setuptools 构建] [docs / modern-java-zh /
### 使用 Setuptools 构建
从 Python 专门构建自定义运算符的第二种方法是使用`setuptools`。 这样做的好处是`setuptools`具有相当强大而广泛的接口,可以用来构建用 C ++编写的 Python 模块。 但是,由于`setuptools`实际上是用于构建 Python 模块而不是普通的共享库(它们没有 Python 期望从模块中获得的必要入口点),因此这种方法可能有点古怪。 也就是说,您需要的是一个`setup.py`文件来代替`CMakeLists.txt`,该文件看起来像这样:
......
# 使用自定义 C ++类扩展 TorchScript
# 使用自定义 C ++类扩展 TorchScript
> 原文:<https://pytorch.org/tutorials/advanced/torch_script_custom_classes.html>
......
# TorchScript 中的动态并行性
# TorchScript 中的动态并行性
> 原文:<https://pytorch.org/tutorials/advanced/torch-script-parallelism.html>
......@@ -176,7 +176,7 @@ def forward(self, x : torch.Tensor) -> torch.Tensor:
通过简单的修改再次运行脚本会产生`1.71`秒的运行时间,从而改进了`17%`
## 旁:可视化并行性] [docs / modern-java-zh /
## 旁:可视化并行性
我们还没有完成模型的优化,但是值得介绍一下用于可视化性能的工具。 一种重要的工具是 [PyTorch 分析器](https://pytorch.org/docs/stable/autograd.html#profiler)
......
# C ++前端中的 Autograd
# C ++前端中的 Autograd
> 原文:<https://pytorch.org/tutorials/advanced/cpp_autograd.html>
......@@ -6,7 +6,7 @@
在本教程中,我们将看几个在 PyTorch C ++前端中进行 autograd 的示例。 请注意,本教程假定您已经对 Python 前端中的 autograd 有基本的了解。 如果不是这种情况,请先阅读 [Autograd:自动分化](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html)
## 基本的 autograd 操作] [docs / modern-java-zh /
## 基本的 autograd 操作
(改编自[本教程](https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#autograd-automatic-differentiation)
......@@ -115,7 +115,7 @@ out.backward();
```
打印渐变 d(out)/ dx
打印梯度 d(out)/ dx
```py
std::cout << x.grad() << std::endl;
......@@ -201,7 +201,7 @@ false
```
或者使用`.detach()`获得具有相同内容但不需要渐变的新张量:
或者使用`.detach()`获得具有相同内容但不需要梯度的新张量:
```py
std::cout << x.requires_grad() << std::endl;
......@@ -263,7 +263,7 @@ std::cout << input.grad() << std::endl;
有关如何使用它们的更多信息,请参见`torch::autograd::backward`[链接](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1autograd_1afa9b5d4329085df4b6b3d4b4be48914b.html))和`torch::autograd::grad`[链接](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1autograd_1a1e03c42b14b40c306f9eb947ef842d9c.html))的文档。
## 在 C ++中使用自定义 autograd 函数] [docs / modern-java-zh /
## 在 C ++中使用自定义 autograd 函数
(改编自[本教程](https://pytorch.org/docs/stable/notes/extending.html#extending-torch-autograd)
......
......@@ -5,16 +5,16 @@
调度程序是 PyTorch 的内部组件,负责确定调用`torch::add`之类的函数时应实际运行哪些代码。 这是不平凡的,因为 PyTorch 操作需要处理很多交叉关注点,这些关注点“层叠”在另一个之上。 以下是其处理的一些示例:
* 根据输入张量的设备,在运算符的 CPU 和 CUDA 实现之间切换。
* 在操作员的自动分级和后端实现之间切换,这取决于是否需要自动分级处理。
* 在操作员的自动微分和后端实现之间切换,这取决于是否需要自动微分处理。
* 必要时应用自动广播以实现自动混合精度。
* 当操作员在`vmap`调用下运行时,应用批量规则。
* 如果要跟踪导出的模型,则跟踪操作的执行。
如果在[自定义运算符代码](torch_script_custom_ops)中发现自己手动编写了 if 语句来处理这些情况,则调度程序 API 可以帮助组织代码。 (相反,如果您的自定义运算符非常简单并且仅用于 CPU 推断,则可能不需要使用调度程序,只需使用基本 API。)
在本教程中,我们将描述如何构造自定义操作员注册以使用调度程序来组织各种组件。 我们假设您熟悉如何[注册操作员](torch_script_custom_ops)以及如何编写[自定义自动分级功能](cpp_autograd)
在本教程中,我们将描述如何构造自定义操作员注册以使用调度程序来组织各种组件。 我们假设您熟悉如何[注册操作员](torch_script_custom_ops)以及如何编写[自定义自动微分功能](cpp_autograd)
## 定义模式和后端实现] [docs / modern-java-zh /
## 定义模式和后端实现
调度程序背后的一般原理是将一个运算符的实现分为多个内核,每个内核都为特定的*调度键*实现功能; 例如,CPU,CUDA 或 Autograd。 调度程序在您调用运算符时确定最高优先级的调度键是什么(这通过查看张量参数和某些线程本地状态来完成),并将控制权传递给内核以使用该调度键。 最终结果是,当您调用运算符时,我们首先执行 Autograd 内核,然后根据传入的张量的设备类型将其重新分配到 CPU 或 CUDA 内核。
......@@ -75,7 +75,7 @@ TORCH_LIBRARY_IMPL(myops, CUDA, m) {
您知道吗,您还可以为 PyTorch 中的现有核心操作员编写`TORCH_LIBRARY_IMPL`块? 这就是实现 XLA 对 PyTorch 的支持的方式:`torch_xla`库包含一个`TORCH_LIBRARY_IMPL`,该库为 XLA 调度键上的所有基本运算符提供实现。
## 添加 autograd 支持] [docs / modern-java-zh /
## 添加 autograd 支持
至此,我们有了一个同时具有 CPU 和 CUDA 实现的操作员。 我们如何为它添加 autograd 支持? 您可能会猜到,我们将注册一个 autograd 内核(类似于[自定义 autograd 函数](cpp_autograd)教程中描述的内容)! 但是,有一个变数:与 CPU 和 CUDA 内核不同,autograd 内核需要*重新分发*:它需要回调分派器才能到达最终的 CPU 和 CUDA 实现。
......@@ -127,7 +127,7 @@ Tensor myadd_autograd(const Tensor& self, const Tensor& other) {
1. 使用`at::AutoNonVariableTypeMode` RAII 保护器关闭自动毕业处理,然后
2. 调用调度函数`myadd`以回调调度程序。
如果没有(1),您的调用将无限循环(并且堆栈溢出),因为`myadd`将使您返回此函数(因为最高优先级分配键仍将是自动分级的。)对于(1),自动分级不包括在 一组正在考虑的调度键,我们将转到下一个处理程序,即 CPU 和 CUDA。
如果没有(1),您的调用将无限循环(并且堆栈溢出),因为`myadd`将使您返回此函数(因为最高优先级分配键仍将是自动微分的。)对于(1),自动微分不包括在 一组正在考虑的调度键,我们将转到下一个处理程序,即 CPU 和 CUDA。
现在,我们可以按照注册 CPU / CUDA 函数的相同方式注册此函数:
......@@ -235,7 +235,7 @@ TORCH_LIBRARY_IMPL(myops, Autocast, m) {
没有单独的体操可使后向方法自动广播兼容。 但是,在自定义 autograd 函数中定义的向后方法将以与正向方法的自动广播集相同的 dtype 运行,因此您应该选择既适合于正向方法又适合于向后方法的`<desired dtype>`
### 批量] [docs / modern-java-zh /
### 批量
批量张量允许您按示例方式编写代码,然后在`vmap`调用下运行时自动对其进行批量。 当前正在开发用于编写批量规则的 API,但是一旦稳定该 API,就可以通过在 Batched 调度键处注册内核来为操作员添加对`vmap`的支持。
......
# 分析您的 PyTorch 模块
# 分析您的 PyTorch 模块
> 原文:<https://pytorch.org/tutorials/beginner/profiler.html>
......@@ -22,7 +22,7 @@ import torch.autograd.profiler as profiler
```
## 使用 Profiler 进行性能调试] [docs / modern-java-zh /
## 使用 Profiler 进行性能调试
Profiler 有助于识别模型中的性能瓶颈。 在此示例中,我们构建了一个自定义模块,该模块执行两个子任务:
......@@ -75,7 +75,7 @@ with profiler.profile(with_stack=True, profile_memory=True) as prof:
```
## 打印分析器结果] [docs / modern-java-zh /
## 打印分析器结果
最后,我们打印分析器结果。 `profiler.key_averages`通过操作员名称,以及可选地通过输入形状和/或堆栈跟踪事件来聚合结果。 按输入形状分组有助于识别模型使用哪些张量形状。
......@@ -131,7 +131,7 @@ Self CPU time total: 5.931s
```
## 提高内存性能] [docs / modern-java-zh /
## 提高内存性能
请注意,就内存和时间而言,最昂贵的操作位于`forward (10)`,代表 MASK INDICES 中的操作。 让我们尝试先解决内存消耗问题。 我们可以看到第 12 行的`.to()`操作消耗 953.67 Mb。 该操作将`mask`复制到 CPU。 `mask`使用`torch.double`数据类型初始化。 我们可以通过将其转换为`torch.float`来减少内存占用吗?
......
# 使用 Ray Tune 进行超参数调整
# 使用 Ray Tune 进行超参数调整
> 原文:<https://pytorch.org/tutorials/beginner/hyperparameter_tuning_tutorial.html>
......@@ -64,7 +64,7 @@ def load_data(data_dir="./data"):
```
## 可配置神经网络] [docs / modern-java-zh /
## 可配置神经网络
我们只能调整那些可配置的参数。 在此示例中,我们可以指定全连接层的层大小:
......@@ -90,7 +90,7 @@ class Net(nn.Module):
```
## 火车功能] [docs / modern-java-zh /
## 火车功能
现在变得有趣了,因为我们对 PyTorch 文档中的示例[进行了一些更改。](https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html)
......@@ -158,7 +158,7 @@ tune.report(loss=(val_loss / val_steps), accuracy=correct / total)
保存检查点是可选的,但是,如果我们想使用高级调度程序,例如[基于人口的训练](https://docs.ray.io/en/master/tune/tutorials/tune-advanced-tutorial.html),则有必要。 另外,通过保存检查点,我们可以稍后加载经过训练的模型并在测试集上对其进行验证。
### 完整的训练功能] [docs / modern-java-zh /
### 完整的训练功能
完整的代码示例如下所示:
......
# 修剪教程
# 修剪教程
> 原文:<https://pytorch.org/tutorials/intermediate/pruning_tutorial.html>
......@@ -20,7 +20,7 @@ import torch.nn.functional as F
```
## 创建模型] [docs / modern-java-zh /
## 创建模型
在本教程中,我们使用 LeCun 等人,1998 年的 [LeNet](http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf) 架构。
......@@ -426,7 +426,7 @@ odict_keys(['conv1.weight_orig', 'conv1.bias_orig', 'conv1.weight_mask', 'conv1.
```
## 删除修剪重新参数化] [docs / modern-java-zh /
## 删除修剪重新参数化
要使修剪永久化,请删除`weight_orig``weight_mask`的重新参数化,然后删除`forward_pre_hook`,我们可以使用`torch.nn.utils.prune``remove`功能。 请注意,这不会撤消修剪,好像从未发生过。 而是通过将参数`weight`重新分配给模型参数(修剪后的版本)来使其永久不变。
......@@ -590,7 +590,7 @@ print(list(module.named_buffers()))
```
## 修剪模型中的多个参数] [docs / modern-java-zh /
## 修剪模型中的多个参数
通过指定所需的修剪技术和参数,我们可以轻松地修剪网络中的多个张量,也许根据它们的类型,如在本示例中将看到的那样。
......
......@@ -42,7 +42,7 @@ yes y | pip install --pre torch -f https://download.pytorch.org/whl/nightly/cu10
```
### 1.2 导入必要的模块] [docs / modern-java-zh /
### 1.2 导入必要的模块
在这一步中,我们将导入本教程所需的 Python 模块。
......@@ -88,7 +88,7 @@ print(torch.__config__.parallel_info())
```
### 1.3 了解辅助函数] [docs / modern-java-zh /
### 1.3 了解辅助函数
帮助器功能内置在转换器库中。 我们主要使用以下辅助函数:一个用于将文本示例转换为特征向量的函数; 另一个用于测量预测结果的 F1 分数。
......@@ -144,7 +144,7 @@ python ./run_glue.py \
我们在此处为 MRPC 任务[提供了经过微调的 BERT 模型。 为了节省时间,您可以将模型文件(〜400 MB)直接下载到本地文件夹`$OUT_DIR`中。](https://download.pytorch.org/tutorial/MRPC.zip)
### 2.1 设置全局配置] [docs / modern-java-zh /
### 2.1 设置全局配置
在这里,我们设置了用于在动态量化之前和之后评估微调 BERT 模型的全局配置。
......@@ -186,7 +186,7 @@ set_seed(42)
```
### 2.2 加载经过微调的 BERT 模型] [docs / modern-java-zh /
### 2.2 加载经过微调的 BERT 模型
我们从`configs.output_dir`加载标记器和经过微调的 BERT 序列分类器模型(FP32)。
......@@ -199,7 +199,7 @@ model.to(configs.device)
```
### 2.3 定义标记化和评估函数] [docs / modern-java-zh /
### 2.3 定义标记化和评估函数
我们重用了 [Huggingface](https://github.com/huggingface/transformers/blob/master/examples/run_glue.py) 中的标记化和评估函数。
......@@ -355,7 +355,7 @@ print(quantized_model)
```
### 3.1 检查模型大小] [docs / modern-java-zh /
### 3.1 检查模型大小
首先,检查模型尺寸。 我们可以观察到模型大小的显着减小(FP32 总大小:438 MB; INT8 总大小:181 MB):
......@@ -406,7 +406,7 @@ time_model_evaluation(quantized_model, configs, tokenizer)
请注意,在本教程中,为了进行单线程比较,我们将线程数设置为 1。 我们还为这些量化的 INT8 运算符支持运算内并行化。 用户现在可以通过`torch.set_num_threads(N)`设置多线程(`N`是内部运算并行线程的数量)。 启用帧内并行支持的一项初步要求是使用正确的[后端](https://pytorch.org/docs/stable/notes/cpu_threading_torchscript_inference.html#build-options)(例如 OpenMP,Native 或 TBB)构建 PyTorch。 您可以使用`torch.__config__.parallel_info()`检查并行化设置。 在使用 PyTorch 和本机后端进行并行化的同一台 MacBook Pro 上,我们可以花大约 46 秒的时间来处理 MRPC 数据集的评估。
### 3.3 序列化量化模型] [docs / modern-java-zh /
### 3.3 序列化量化模型
跟踪模型后,我们可以使用 <cite>torch.jit.save</cite> 序列化并保存量化模型,以备将来使用。
......
# (beta)在 PyTorch 中使用 Eager 模式进行静态量化
# (beta)在 PyTorch 中使用 Eager 模式进行静态量化
> 原文:<https://pytorch.org/tutorials/advanced/static_quantization_tutorial.html#>
......
# (beta)计算机视觉教程的量化迁移学习
# (beta)计算机视觉教程的量化迁移学习
> 原文:<https://pytorch.org/tutorials/intermediate/quantized_transfer_learning_tutorial.html>
......@@ -39,7 +39,7 @@ plt.ion()
```
### 安装每夜构建] [docs / modern-java-zh /
### 安装每夜构建
因为您将使用 PyTorch 的 Beta 部分,所以建议安装最新版本的`torch``torchvision`。 您可以在中找到有关本地安装[的最新说明。 例如,要在没有 GPU 支持的情况下进行安装:](https://pytorch.org/get-started/locally/)
......@@ -102,7 +102,7 @@ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
```
### 可视化一些图像] [docs / modern-java-zh /
### 可视化一些图像
让我们可视化一些训练图像,以了解数据扩充。
......
# PyTorch 分布式概述
# PyTorch 分布式概述
> 原文:<https://pytorch.org/tutorials/beginner/dist_overview.html>
......@@ -11,7 +11,7 @@
从 PyTorch v1.6.0 开始,`torch.distributed`中的功能可以分为三个主要组件:
* [分布式数据并行训练](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html)(DDP)是一种广泛采用的单程序多数据训练范例。 使用 DDP,可以在每个流程上复制模型,并且每个模型副本都将获得一组不同的输入数据样本。 DDP 负责梯度通信,以保持模型副本同步,并使其与梯度计算重叠,以加快训练速度。
* [基于 RPC 的分布式训练](https://pytorch.org/docs/master/rpc.html)(RPC)开发来支持无法适应数据并行训练的常规训练结构,例如分布式管道并行性,参数服务器范式以及 DDP 与其他训练范式的组合。 它有助于管理远程对象的生命周期,并将自动分级引擎扩展到机器范围之外。
* [基于 RPC 的分布式训练](https://pytorch.org/docs/master/rpc.html)(RPC)开发来支持无法适应数据并行训练的常规训练结构,例如分布式管道并行性,参数服务器范式以及 DDP 与其他训练范式的组合。 它有助于管理远程对象的生命周期,并将自动微分引擎扩展到机器范围之外。
* [集体通信](https://pytorch.org/docs/stable/distributed.html)(c10d)库支持跨组内的进程发送张量。 它提供了集体通信 API(例如 [all_reduce](https://pytorch.org/docs/stable/distributed.html#torch.distributed.all_reduce)[all_gather](https://pytorch.org/docs/stable/distributed.html#torch.distributed.all_gather) )和 P2P 通信 API(例如[发送](https://pytorch.org/docs/stable/distributed.html#torch.distributed.send)[isend](https://pytorch.org/docs/stable/distributed.html#torch.distributed.isend) )。 从 v1.6.0 开始,DDP 和 RPC( [ProcessGroup Backend](https://pytorch.org/docs/master/rpc.html#process-group-backend) )建立在 c10d 上,其中前者使用集体通信,而后者使用 P2P 通信。 通常,开发人员无需直接使用此原始通信 API,因为上述 DDP 和 RPC 功能可以满足许多分布式训练方案的需求。 但是,在某些情况下,此 API 仍然很有帮助。 一个示例是分布式参数平均,其中应用程序希望在向后传递之后计算所有模型参数的平均值,而不是使用 DDP 来传递梯度。 这可以使通信与计算脱钩,并允许对通信内容进行更细粒度的控制,但另一方面,它也放弃了 DDP 提供的性能优化。 [用 PyTorch 编写分布式应用程序](https://pytorch.org/tutorials/intermediate/dist_tuto.html)显示了使用 c10d 通信 API 的示例。
现有的大多数文档都是为 DDP 或 RPC 编写的,本页面的其余部分将详细介绍这两个组件的材料。
......@@ -57,7 +57,7 @@ DDP 材料如下:
* [RPC](https://pytorch.org/docs/master/rpc.html#rpc) 支持在远程工作者上运行给定功能。
* [RRef](https://pytorch.org/docs/master/rpc.html#rref) 帮助管理远程对象的生存期。 参考计数协议在 [RRef 注释](https://pytorch.org/docs/master/rpc/rref.html#remote-reference-protocol)中提供。
* [分布式自动分级](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework)将自动分级引擎扩展到机器范围之外。 有关更多详细信息,请参考[分布式自动毕业设计](https://pytorch.org/docs/master/rpc/distributed_autograd.html#distributed-autograd-design)
* [分布式自动微分](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework)将自动微分引擎扩展到机器范围之外。 有关更多详细信息,请参考[分布式自动毕业设计](https://pytorch.org/docs/master/rpc/distributed_autograd.html#distributed-autograd-design)
* [分布式优化器](https://pytorch.org/docs/master/rpc.html#module-torch.distributed.optim),它使用分布式自动毕业引擎计算的梯度自动与所有参与的工作人员联系以更新参数。
RPC 教程如下:
......@@ -68,6 +68,6 @@ RPC 教程如下:
4. [使用异步执行实现批量 RPC](../intermediate/rpc_async_execution.html) 教程演示了如何使用 [@ rpc.functions.async_execution](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution) 装饰器实现 RPC 批量。这可以帮助加速推理和训练。 它使用了以上教程 1 和 2 中采用的类似 RL 和 PS 示例。
5. [将分布式 DataParallel 与分布式 RPC 框架结合](../advanced/rpc_ddp_tutorial.html)教程演示了如何将 DDP 与 RPC 结合使用分布式数据并行性和分布式模型并行性来训练模型。
## PyTorch 分布式开发人员] [docs / modern-java-zh /
## PyTorch 分布式开发人员
如果您想为 PyTorch Distributed 做出贡献,请参阅我们的[开发人员指南](https://github.com/pytorch/pytorch/blob/master/torch/distributed/CONTRIBUTING.md)
\ No newline at end of file
# 单机模型并行最佳实践
# 单机模型并行最佳实践
> 原文:<https://pytorch.org/tutorials/intermediate/model_parallel_tutorial.html>
......@@ -34,7 +34,7 @@ class ToyModel(nn.Module):
```
请注意,除了五个`to(device)`调用将线性层和张量放置在适当的设备上之外,上述`ToyModel`看起来非常类似于在单个 GPU 上实现它的方式。 那是模型中唯一需要更改的地方。 `backward()``torch.optim`将自动处理渐变,就像模型在一个 GPU 上一样。 调用损失函数时,只需确保标签与输出位于同一设备上。
请注意,除了五个`to(device)`调用将线性层和张量放置在适当的设备上之外,上述`ToyModel`看起来非常类似于在单个 GPU 上实现它的方式。 那是模型中唯一需要更改的地方。 `backward()``torch.optim`将自动处理梯度,就像模型在一个 GPU 上一样。 调用损失函数时,只需确保标签与输出位于同一设备上。
```py
model = ToyModel()
......@@ -174,7 +174,7 @@ plot([mp_mean, rn_mean],
结果表明,模型并行实现的执行时间比现有的单 GPU 实现长`4.02/3.75-1=7%`。 因此,我们可以得出结论,在 GPU 之间来回复制张量大约有 7% 的开销。 有待改进的地方,因为我们知道两个 GPU 之一在整个执行过程中处于空闲状态。 一种选择是将每个批量进一步划分为拆分流水线,以便当一个拆分到达第二子网时,可以将下一个拆分馈入第一子网。 这样,两个连续的拆分可以在两个 GPU 上同时运行。
## 通过流水线输入加快速度] [docs / modern-java-zh /
## 通过流水线输入加快速度
在以下实验中,我们将每个 120 图像批量进一步分为 20 图像分割。 当 PyTorch 异步启动 CUDA 操作时,该实现无需生成多个线程即可实现并发。
......
# 分布式数据并行入门
# 分布式数据并行入门
> 原文:<https://pytorch.org/tutorials/intermediate/ddp_tutorial.html>
......@@ -12,7 +12,7 @@
* [DistributedDataParallel API 文档](https://pytorch.org/docs/master/generated/torch.nn.parallel.DistributedDataParallel.html)
* [DistributedDataParallel 注意事项](https://pytorch.org/docs/master/notes/ddp.html)
[DistributedDataParallel](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel) (DDP)在模块级别实现可在多台计算机上运行的数据并行性。 使用 DDP 的应用程序应产生多个进程,并为每个进程创建一个 DDP 实例。 DDP 在[火炬。分布式](https://pytorch.org/tutorials/intermediate/dist_tuto.html)程序包中使用集体通信来同步渐变和缓冲区。 更具体地说,DDP 为`model.parameters()`给定的每个参数注册一个 autograd 挂钩,当在后向传递中计算相应的梯度时,挂钩将触发。 然后,DDP 使用该信号触发跨进程的梯度同步。 有关更多详细信息,请参考 [DDP 设计说明](https://pytorch.org/docs/master/notes/ddp.html)
[DistributedDataParallel](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel) (DDP)在模块级别实现可在多台计算机上运行的数据并行性。 使用 DDP 的应用程序应产生多个进程,并为每个进程创建一个 DDP 实例。 DDP 在[火炬。分布式](https://pytorch.org/tutorials/intermediate/dist_tuto.html)程序包中使用集体通信来同步梯度和缓冲区。 更具体地说,DDP 为`model.parameters()`给定的每个参数注册一个 autograd 挂钩,当在后向传递中计算相应的梯度时,挂钩将触发。 然后,DDP 使用该信号触发跨进程的梯度同步。 有关更多详细信息,请参考 [DDP 设计说明](https://pytorch.org/docs/master/notes/ddp.html)
推荐的使用 DDP 的方法是为每个模型副本生成一个进程,其中一个模型副本可以跨越多个设备。 DDP 进程可以放在同一台计算机上,也可以在多台计算机上,但是 GPU 设备不能在多个进程之间共享。 本教程从一个基本的 DDP 用例开始,然后演示了更高级的用例,包括检查点模型以及将 DDP 与模型并行结合。
......
......@@ -10,7 +10,7 @@
在这个简短的教程中,我们将介绍 PyTorch 的分布式软件包。 我们将了解如何设置分布式设置,如何使用不同的交流策略以及如何查看软件包的一些内部内容。
## 设置] [docs / modern-java-zh /
## 设置
PyTorch 中包含的分布式软件包(即`torch.distributed`)使研究人员和从业人员可以轻松地并行化他们在跨进程和机器集群的计算。 为此,它利用了传递消息的语义,从而允许每个进程将数据传递给任何其他进程。 与多处理(HTG1)包相反,进程可以使用不同的通信后端,而不仅限于在同一台计算机上执行。
......@@ -109,7 +109,7 @@ def run(rank, size):
当我们希望对流程的通信进行精细控制时,点对点通信非常有用。 它们可用于实现精美的算法,例如[百度的 DeepSpeech](https://github.com/baidu-research/baidu-allreduce)[Facebook 的大规模实验](https://research.fb.com/publications/imagenet1kin1h/)中使用的算法。(请参阅 [4.1 节](#our-own-ring-allreduce)
## 集体交流] [docs / modern-java-zh /
## 集体交流
<colgroup><col width="50%"> <col width="50%"></colgroup>
| [![Scatter](img/3aa3584628cb0526c8b0e9d02b15d876.png)](../_img/scatter.png)分散 | [![Gather](img/7e8670a3b7cdc7848394514ef1da090a.png)](../_img/gather.png)收集 |
......
# 分布式 RPC 框架入门
# 分布式 RPC 框架入门
> 原文:<https://pytorch.org/tutorials/intermediate/rpc_tutorial.html>
......@@ -390,7 +390,7 @@ class RNNModel(nn.Module):
现在,我们准备实施训练循环。 初始化模型参数后,我们创建`RNNModel``DistributedOptimizer`。 分布式优化器将采用参数`RRefs`的列表,查找所有不同的所有者工作器,并在每个所有者工作器上创建给定的本地优化器(即,在这种情况下,您也可以使用其他本地优化器`SGD`) 使用给定的参数(即`lr=0.05`)。
在训练循环中,它首先创建一个分布式 autograd 上下文,这将帮助分布式 autograd 引擎查找渐变和涉及的 RPC 发送/接收功能。 分布式 autograd 引擎的设计详细信息可以在其[设计说明](https://pytorch.org/docs/master/notes/distributed_autograd.html)中找到。 然后,它像本地模型一样开始前向传递,并运行分布式后向传递。 对于后向分布,您只需要指定一个根列表,在这种情况下,就是损失`Tensor`。 分布式 autograd 引擎将自动遍历分布式图形并正确编写渐变。 接下来,它在分布式优化器上运行`step`功能,该功能将与所有涉及的本地优化器联系以更新模型参数。 与本地训练相比,一个较小的差异是您不需要运行`zero_grad()`,因为每个 autograd 上下文都有专用的空间来存储梯度,并且在每次迭代创建上下文时,来自不同迭代的那些梯度不会累积到 同一组`Tensors`
在训练循环中,它首先创建一个分布式 autograd 上下文,这将帮助分布式 autograd 引擎查找梯度和涉及的 RPC 发送/接收功能。 分布式 autograd 引擎的设计详细信息可以在其[设计说明](https://pytorch.org/docs/master/notes/distributed_autograd.html)中找到。 然后,它像本地模型一样开始前向传递,并运行分布式后向传递。 对于后向分布,您只需要指定一个根列表,在这种情况下,就是损失`Tensor`。 分布式 autograd 引擎将自动遍历分布式图形并正确编写梯度。 接下来,它在分布式优化器上运行`step`功能,该功能将与所有涉及的本地优化器联系以更新模型参数。 与本地训练相比,一个较小的差异是您不需要运行`zero_grad()`,因为每个 autograd 上下文都有专用的空间来存储梯度,并且在每次迭代创建上下文时,来自不同迭代的那些梯度不会累积到 同一组`Tensors`
```py
def run_trainer():
......
# 使用分布式 RPC 框架实现参数服务器
# 使用分布式 RPC 框架实现参数服务器
> 原文:<https://pytorch.org/tutorials/intermediate/rpc_param_server_tutorial.html>
......
......@@ -90,7 +90,7 @@ class BatchUpdateParameterServer(object):
```
对于训练师,它们都使用来自 PS 的相同参数集进行初始化。 在每次迭代中,每位训练师首先进行前进和后退操作,以局部生成梯度。 然后,每个训练师都使用 RPC 向 PS 报告其渐变,并通过同一 RPC 请求的返回值取回更新的参数。 在训练师的实施中,目标功能是否标记有`@rpc.functions.async_execution`都没有关系。 训练师只需使用`rpc_sync`调用`update_and_fetch_model`,这会阻塞训练师,直到返回更新的模型。
对于训练师,它们都使用来自 PS 的相同参数集进行初始化。 在每次迭代中,每位训练师首先进行前进和后退操作,以局部生成梯度。 然后,每个训练师都使用 RPC 向 PS 报告其梯度,并通过同一 RPC 请求的返回值取回更新的参数。 在训练师的实施中,目标功能是否标记有`@rpc.functions.async_execution`都没有关系。 训练师只需使用`rpc_sync`调用`update_and_fetch_model`,这会阻塞训练师,直到返回更新的模型。
```py
batch_size, image_w, image_h = 20, 64, 64
......
# 将分布式 DataParallel 与分布式 RPC 框架相结合
# 将分布式 DataParallel 与分布式 RPC 框架相结合
> 原文:<https://pytorch.org/tutorials/advanced/rpc_ddp_tutorial.html>
......@@ -23,8 +23,8 @@
2. 然后,主持人开始在训练师上进行训练循环,并将嵌入表 RRef 传递给训练师。
3. 训练师创建一个`HybridModel`,该`HybridModel`首先使用主机提供的嵌入表 RRef 执行嵌入查找,然后执行包装在 DDP 中的 FC 层。
4. 训练者执行模型的正向传递,并使用 [Distributed Autograd](https://pytorch.org/docs/master/rpc.html#distributed-autograd-framework) 使用损失执行反向传递。
5. 作为向后遍历的一部分,将首先计算 FC 层的渐变,并通过 DDP 中的 allreduce 将其同步到所有训练器。
6. 接下来,Distributed Autograd 将渐变传播到参数服务器,在该服务器中更新嵌入表的渐变
5. 作为向后遍历的一部分,将首先计算 FC 层的梯度,并通过 DDP 中的 allreduce 将其同步到所有训练器。
6. 接下来,Distributed Autograd 将梯度传播到参数服务器,在该服务器中更新嵌入表的梯度
7. 最后,[分布式优化器](https://pytorch.org/docs/master/rpc.html#module-torch.distributed.optim)用于更新所有参数。
注意
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册