提交 d4df4d3c 编写于 作者: W wizardforcel

2021-01-24 23:06:43

上级 b29e3ba3
......@@ -499,7 +499,7 @@ for i in range(100):
前面的输出显示周期号以及损失函数的值,可以看出,该函数正在减小。 这意味着训练过程使损失函数最小化,这意味着模型能够理解输入特征和目标之间的关系。
5. 绘制线图以显示每个期的损失函数的值:
5. 绘制线图以显示每个期的损失函数的值:
```py
plt.plot(range(0,20), losses)
......
......@@ -452,9 +452,9 @@ batch_size = 100
从前面的片段中可以看出,第一步是定义在训练网络时将使用的所有变量。
接下来,循环的第一个**用于遍历我们之前定义的期数。**
接下来,循环的第一个**用于遍历我们之前定义的期数。**
请记住,**时期**是指整个数据集通过网络架构前后传递的次数。`batch_size`是指单个批量(数据集的一部分)中训练示例的数量。 最后,**迭代**是指完成一个时期所需的批量数量。
请记住,**周期**是指整个数据集通过网络架构前后传递的次数。`batch_size`是指单个批量(数据集的一部分)中训练示例的数量。 最后,**迭代**是指完成一个周期所需的批量数量。
第二个`for`循环遍历总数据集的每个批量,直到完成一个周期为止。 在此循环中,发生以下计算:
......@@ -549,15 +549,15 @@ batch_size = 100
注意
即使使用种子,考虑到训练集在每个期之前都经过了改组,该活动的确切结果也无法重现。
即使使用种子,考虑到训练集在每个期之前都经过了改组,该活动的确切结果也无法重现。
2. 读取先前准备的数据集,该数据集应已命名为`dccc_prepared.csv`
3. 将特征与目标分开。
4. 使用 scikit-learn 的`train_test_split`函数,将数据集分为训练,验证和测试集。 使用 60:20:20 的分配比例。 将`random_state`设置为`0`
5. 考虑到特征矩阵应为浮点型,而目标矩阵则应为非浮点型,将验证和测试集转换为张量。 目前暂时不要转换训练集,因为它们将进行进一步的转换。
6. 构建用于定义网络层的自定义模块类。 包括一个正向函数,该函数指定将应用于每层输出的激活函数。 对于除输出之外的所有层,请使用 **ReLU**,在此处应使用`log_softmax`
7. 实例化模型并定义训练模型所需的所有变量。 将期数设置为`50`,并将批大小设置为`128`。 使用`0.001`的学习率。
8. 使用训练集的数据训练网络。 使用验证集来衡量表现。 为此,请保存每个期中训练集和验证集的损失和准确率。
7. 实例化模型并定义训练模型所需的所有变量。 将期数设置为`50`,并将批大小设置为`128`。 使用`0.001`的学习率。
8. 使用训练集的数据训练网络。 使用验证集来衡量表现。 为此,请保存每个期中训练集和验证集的损失和准确率。
注意
......@@ -658,7 +658,7 @@ batch_size = 100
2. 确定提高模型准确率所需的操作。
为了提高模型的表现,可以遵循的两个操作过程是增加期数并增加隐藏层数和/或单元数(每层中的神经元)。
为了提高模型的表现,可以遵循的两个操作过程是增加期数并增加隐藏层数和/或单元数(每层中的神经元)。
据此,可以执行一组测试以便获得最佳结果。
......@@ -674,7 +674,7 @@ batch_size = 100
1. 导入与上一个活动相同的库。
2. 加载数据并从目标拆分特征。 接下来,使用 60:20:20 的分割比例将数据分割为三个子集(训练,验证和测试)。 最后,将验证和测试集转换为 PyTorch 张量,就像在上一个活动中一样。
3. 考虑到该模型存在较高的偏差,因此重点应放在通过向每个层添加其他层或单元来增加期数或网络规模。 目的应该是将测试范围内的准确率近似为 80%。
3. 考虑到该模型存在较高的偏差,因此重点应放在通过向每个层添加其他层或单元来增加期数或网络规模。 目的应该是将测试范围内的准确率近似为 80%。
注意
......
......@@ -576,7 +576,7 @@ test_loader = torch.utils.data.DataLoader(test_data, \
有关此活动的解决方案,请参见第 262 页。
由于数据在每个期都经过重新排序,因此结果将无法完全重现。 但是,您应该能够获得与本书所获得的结果相似的结果。
由于数据在每个期都经过重新排序,因此结果将无法完全重现。 但是,您应该能够获得与本书所获得的结果相似的结果。
这段代码可能需要一些时间才能运行,这就是为什么在本书的 GitHub 存储库中提供了等效的 GPU 版本解决方案的原因。
......@@ -678,7 +678,7 @@ test_data = datasets.CIFAR10('data', train=False, download=True, \
![Figure 4.18: Resulting plot showing the loss of the sets ](img/B15778_04_18.jpg)
图 4.18:结果图显示集合的
图 4.18:结果图显示集合的
![Figure 4.19: Resulting plot showing the accuracy of the sets ](img/B15778_04_19.jpg)
......@@ -686,7 +686,7 @@ test_data = datasets.CIFAR10('data', train=False, download=True, \
注意
由于每个时代的数据改组,结果将无法精确再现。 但是,您应该能够得到类似的结果。
由于每个周期的数据改组,结果将无法精确再现。 但是,您应该能够得到类似的结果。
4. 计算测试集上所得模型的准确率。
......@@ -764,11 +764,11 @@ class CNN(nn.Module):
![Figure 4.21: Resulting plot showing the loss of the sets ](img/B15778_04_21.jpg)
图 4.21:结果图显示了集合的
图 4.21:结果图显示了集合的
![Figure 4.22: Resulting plot showing the loss of the sets ](img/B15778_04_22.jpg)
图 4.22:结果图显示了集合的
图 4.22:结果图显示了集合的
4. 计算结果模型在测试集上的准确率--它应该是 78% 左右。
......@@ -776,7 +776,7 @@ class CNN(nn.Module):
此活动的解决方案可以在第 274 页上找到。
由于在每个期对数据进行混洗,结果将无法完全重现。 但是,您应该能够获得与本书所获得的结果相似的结果。
由于在每个期对数据进行混洗,结果将无法完全重现。 但是,您应该能够获得与本书所获得的结果相似的结果。
这段代码可能需要一些时间才能运行,这就是为什么在本书的 GitHub 存储库中提供了等效的 GPU 版本解决方案的原因。
......
......@@ -383,7 +383,7 @@ for index, layer in model._modules.items():
要创建字典,我们使用上一步的输出,该输出显示网络中的每个层。 在那里,可以观察到第一堆叠的第一层标记为`0`,而第二堆叠的第一层标记为`5`,依此类推。
4. 创建一个函数,从输入图像中提取相关特征(仅从相关层中提取的特征)。将其命名为`features_extractor`,并确保它将图像、模型和我们之前创建的字典作为输入。
4. 创建一个函数,从输入图像中提取相关特征(仅从相关层中提取的特征)。将其命名为`features_extractor`,并确保它将图像、模型和我们之前创建的字典作为输入。
```py
def features_extractor(x, model, layers):
......
......@@ -242,11 +242,11 @@ for i in range(1, epochs+1):
        optimizer.step()
```
对于每个时期,隐藏状态都初始化为`None`。 这是因为,在每个时期,网络都会尝试将输入映射到目标(给定一组参数时)。 该映射应该与数据集中之前的运行没有任何偏差(隐藏状态)地发生。
对于每个周期,隐藏状态都初始化为`None`。 这是因为,在每个周期,网络都会尝试将输入映射到目标(给定一组参数时)。 该映射应该与数据集中之前的运行没有任何偏差(隐藏状态)地发生。
接下来,`for`循环遍历不同批量的数据。 在此循环内,将进行预测并保存隐藏状态,该状态将用作下一批的输入。
最后,计算损失函数,该函数用于更新网络参数。 然后,该过程再次开始,直到达到所需的期数。
最后,计算损失函数,该函数用于更新网络参数。 然后,该过程再次开始,直到达到所需的期数。
## 活动 6.01:使用简单 RNN 的时间序列预测
......@@ -269,9 +269,9 @@ for i in range(1, epochs+1):
5. 创建一个包含网络架构的类; 请注意,全连接层的输出大小应为 1。
6. 实例化包含模型的类函数。 输入输入大小,每个循环层中的神经元数(10)和循环层数(1)。
7. 定义损失函数,优化算法和训练网络的期数。 为此,请使用均方误差损失函数,Adam 优化器和 10,000 个周期。
8. 使用`for`循环通过遍历所有时期来执行训练过程。 在每个时期,都必须进行预测,以及随后的损失函数计算和网络参数优化。 然后,保存每个时期的损失。
9. 绘制所有期的损失。
7. 定义损失函数,优化算法和训练网络的期数。 为此,请使用均方误差损失函数,Adam 优化器和 10,000 个周期。
8. 使用`for`循环通过遍历所有周期来执行训练过程。 在每个周期,都必须进行预测,以及随后的损失函数计算和网络参数优化。 然后,保存每个周期的损失。
9. 绘制所有期的损失。
0. 使用散点图,显示在训练过程的最后一个周期中获得的预测值与真实情况值(即上周的销售交易)的对比。
注意
......@@ -579,7 +579,7 @@ onehot = onehot_flat.reshape((batch.shape[0],\
与任何其他网络一样,`forward`函数定义了在`forward`传递中通过层移动数据的方式。
最后,定义一个函数以在每个期将隐藏状态和单元状态初始化为零。 这是通过`next(self.parameters()).data.new()`实现的,该方法获取模型的第一个参数,并在括号内创建具有指定尺寸的相同类型的新张量, 然后用零填充。 将`hidden``cell`状态都作为元组输入模型。
最后,定义一个函数以在每个期将隐藏状态和单元状态初始化为零。 这是通过`next(self.parameters()).data.new()`实现的,该方法获取模型的第一个参数,并在括号内创建具有指定尺寸的相同类型的新张量, 然后用零填充。 将`hidden``cell`状态都作为元组输入模型。
## 训练模型
......@@ -619,8 +619,8 @@ for e in range(1, epochs+1):
如前面的代码所示,步骤如下:
1. 为了获得更好的模型,有必要遍历数据多次,因此需要设置多个期。
2. 在每个期,必须初始化隐藏状态和单元状态。 这是通过调用该类中先前创建的函数来实现的。
1. 为了获得更好的模型,有必要遍历数据多次,因此需要设置多个期。
2. 在每个期,必须初始化隐藏状态和单元状态。 这是通过调用该类中先前创建的函数来实现的。
3. 使用循环`for`将数据分批馈入模型。 `if`语句用于确定它是否是最后一批,以便在句末添加句点,以表示句点。
4. 输入数据被转换为一热矩阵。 输入和目标都将转换为 PyTorch 张量。
5. 通过对一批数据调用模型来获得网络的输出。 然后,计算损失函数,并优化参数。
......@@ -692,9 +692,9 @@ while starter[-1] != "." and counter < 50:
注意
根据您的资源,训练过程将花费很长时间,这就是为什么建议仅运行 20 个周期的原因。 但是,本书的 GitHub 存储库中提供了可以在 GPU 上运行的代码的等效版本。 这将使您运行更多的时代并获得出色的表现。
根据您的资源,训练过程将花费很长时间,这就是为什么建议仅运行 20 个周期的原因。 但是,本书的 GitHub 存储库中提供了可以在 GPU 上运行的代码的等效版本。 这将使您运行更多的周期并获得出色的表现。
0. 在每一个时代,数据必须被划分为 50 个序列长度的批次。这意味着每个时代将有 100 个序列,每个序列的长度为 50。
0. 在每一个周期,数据必须被划分为 50 个序列长度的批次。这意味着每个周期将有 100 个序列,每个序列的长度为 50。
注意
......@@ -805,7 +805,7 @@ class LSTM(nn.Module):
## 训练模型
最后,在定义了损失函数和优化算法之后,训练模型的过程与任何其他神经网络相同。 根据研究的需要和目的,可以将数据分为不同的组。 接下来,您必须设置时期数和将数据分成批量的方法。 通常在处理每批数据时保留网络内存,但随后在每个时期将其初始化为零。 通过对一批数据调用模型来获得网络的输出。 然后,计算损失函数,并优化参数。
最后,在定义了损失函数和优化算法之后,训练模型的过程与任何其他神经网络相同。 根据研究的需要和目的,可以将数据分为不同的组。 接下来,您必须设置周期数和将数据分成批量的方法。 通常在处理每批数据时保留网络内存,但随后在每个周期将其初始化为零。 通过对一批数据调用模型来获得网络的输出。 然后,计算损失函数,并优化参数。
## 活动 6.03:用于情感分析的 NLP
......@@ -835,8 +835,8 @@ class LSTM(nn.Module):
由于在训练过程中不会批量输入数据,因此无需返回`forward`函数中的状态。 但是,这并不意味着该模型将没有内存,而是因为该内存不依赖于下一个审阅,因此该内存用于单独处理每个审阅。
7. 使用 3 个 LSTM 层的 64 个嵌入尺寸和 128 个神经元实例化模型。
8. 定义损失函数,优化算法以及要训练的时期数。 例如,您可以将二进制交叉熵损失用作损失函数,Adam 优化器,并训练 10 个历元
9. 创建一个`for`循环,该循环将经历不同的期并分别经历每个审核。 对于每次审核,都要进行预测,计算损失函数并更新网络参数。 此外,根据该训练数据计算网络的准确率。
8. 定义损失函数,优化算法以及要训练的周期数。 例如,您可以将二进制交叉熵损失用作损失函数,Adam 优化器,并训练 10 个周期
9. 创建一个`for`循环,该循环将经历不同的期并分别经历每个审核。 对于每次审核,都要进行预测,计算损失函数并更新网络参数。 此外,根据该训练数据计算网络的准确率。
0. 随时间绘制损失和准确率。
最终的精度图将如下所示:
......
......@@ -396,7 +396,7 @@
batch_size = 128
```
8. 使用训练集的数据来训练网络。使用验证集来衡量表现。要做到这一点,请保存每个时代的训练集和验证集的损失和准确率。
8. 使用训练集的数据来训练网络。使用验证集来衡量表现。要做到这一点,请保存每个周期的训练集和验证集的损失和准确率。
```py
train_losses, dev_losses, \
......@@ -541,7 +541,7 @@
        return out
```
接下来,定义训练过程的不同参数。 这包括损失函数,优化算法,批量大小和期数,如以下代码所示:
接下来,定义训练过程的不同参数。 这包括损失函数,优化算法,批量大小和期数,如以下代码所示:
```py
model = Classifier(X_train.shape[1])
......@@ -1074,7 +1074,7 @@
![Figure 4.23: Resulting plot showing the loss of the sets ](img/B15778_04_23.jpg)
图 4.23:结果图显示了集合的
图 4.23:结果图显示了集合的
要绘制精度,请使用以下代码:
......@@ -1091,7 +1091,7 @@
图 4.24:结果图显示了集合的准确率
可以看出,在第 15 个期之后,过拟合开始影响模型。
可以看出,在第 15 个期之后,过拟合开始影响模型。
0. 在测试集上检查模型的准确率。
......@@ -1172,7 +1172,7 @@
![Figure 4.25: Resulting plot showing the loss of the sets ](img/B15778_04_25.jpg)
图 4.25:结果图显示了集合的
图 4.25:结果图显示了集合的
![Figure 4.26: Resulting plot showing the accuracy of the sets ](img/B15778_04_26.jpg)
......@@ -1237,11 +1237,11 @@
![Figure 4.27: Resulting plot showing the loss of the sets ](img/B15778_04_27.jpg)
图 4.27:结果图显示集合的
图 4.27:结果图显示集合的
![Figure 4.28: Resulting plot showing the loss of the sets ](img/B15778_04_28.jpg)
图 4.28:结果图显示集合的
图 4.28:结果图显示集合的
尽管过拟合再次引入了模型,但是我们可以看到两组的表现都有所提高。
......@@ -1372,7 +1372,7 @@
    param.requires_grad_(False)
```
7. 创建一个字典,用于将相关层的索引(键)映射到名称(值)。然后,创建一个函数来提取相关层的特征图。用它们来提取两个输入图像的特征。
7. 创建一个字典,用于将相关层的索引(键)映射到名称(值)。然后,创建一个函数来提取相关层的特征图。用它们来提取两个输入图像的特征。
以下函数应为每个相关层提取给定图像的特征:
......@@ -1664,7 +1664,7 @@
![Figure 6.28: Plot displaying the losses of all epochs ](img/B15778_06_28.jpg)
图 6.28:显示所有期的损失的图
图 6.28:显示所有期的损失的图
0. 使用散点图,显示在训练过程的最后一个周期中获得的预测值与真实情况值(即上周的销售交易)的对比。
......@@ -1837,13 +1837,13 @@
epochs = 20
```
如果您的机器有可用的 GPU,请尝试运行`500`期的训练过程:
如果您的机器有可用的 GPU,请尝试运行`500`期的训练过程:
```py
epochs = 500
```
0. 在每个时代,数据必须被划分为序列长度为 50 的批次。这意味着每个时代将有 100 个批次,每个批次的序列长度为 50。
0. 在每个周期,数据必须被划分为序列长度为 50 的批次。这意味着每个周期将有 100 个批次,每个批次的序列长度为 50。
```py
losses = []
......@@ -1950,7 +1950,7 @@
图 6.30:显示损失函数进度的图表
如我们所见,在 20 个历元之后,损失函数仍然可以减少,这就是为什么强烈建议训练更多历元以便从模型中获得良好结果的原因。
如我们所见,在 20 个周期之后,损失函数仍然可以减少,这就是为什么强烈建议训练更多周期以便从模型中获得良好结果的原因。
2. 将下面的句子`starter`输入到训练好的模型中,让它来完成这个句子:`"So she was considering in her own mind "`
......
......@@ -1058,7 +1058,7 @@ plot_loss(train_loss,val_loss)
![](img/97d99dae-968d-45c3-9d2f-13cf0b663c2b.png)
在本节中,我们探索了使用 MNIST 数据集的连体网络的实现以及使用 Omniglot 数据集的匹配网络架构。 在连体网络编码练习中,我们创建了一个小的卷积层,并由一个全连接层姐妹架构进行了扩展。 训练模型后,我们还绘制了模型获得的二维嵌入图,并观察了某些数字如何聚类在一起。 同样,在匹配网络编码练习中,我们为匹配网络的每个模块实现了小型架构,例如嵌入提取器,注意力模型和完全上下文嵌入。 我们还观察到,仅用 100 个期,我们就可以达到约 86% 的精度,并绘制了匹配网络架构的精度和损失图。
在本节中,我们探索了使用 MNIST 数据集的连体网络的实现以及使用 Omniglot 数据集的匹配网络架构。 在连体网络编码练习中,我们创建了一个小的卷积层,并由一个全连接层姐妹架构进行了扩展。 训练模型后,我们还绘制了模型获得的二维嵌入图,并观察了某些数字如何聚类在一起。 同样,在匹配网络编码练习中,我们为匹配网络的每个模块实现了小型架构,例如嵌入提取器,注意力模型和完全上下文嵌入。 我们还观察到,仅用 100 个期,我们就可以达到约 86% 的精度,并绘制了匹配网络架构的精度和损失图。
您可能还观察到某些模型是从头开始训练的-我们可能已经使用了迁移学习架构,或者增加了 LSTM 架构的隐藏大小,或者也许被认为是加权的交叉熵损失函数。 总是有实验和改进的空间。 如果您想进一步尝试使用该模型,建议您访问本书的 GitHub 页面。
......
......@@ -24,7 +24,7 @@
当给出有限数量的数据时,梯度下降算法无法优化神经网络的主要原因有两个:
* 对于每个新任务,神经网络必须从其参数的随机初始化开始,这会导致后期收敛。 迁移学习已通过使用预训练的网络来缓解此问题,但由于数据应具有相似的域而受到限制。
* 即使是梯度下降的权重更新步骤方法(例如 AdaGrad,Adam,RMS 等)的变体也无法在较少的期内表现良好。 这些算法不能保证收敛,特别是在用于非凸优化时。
* 即使是梯度下降的权重更新步骤方法(例如 AdaGrad,Adam,RMS 等)的变体也无法在较少的期内表现良好。 这些算法不能保证收敛,特别是在用于非凸优化时。
真正有用的是学习一些可以在所有域中使用的通用初始化,这是初始化的一个好地方。 梯度下降算法的关键思想是基于下一步的方向,该方向是根据概率分布假设选择的。 因此,如果我们能够以某种方式完全近似概率分布,则仅需几个步骤就可以优化网络。 这是一次/小样本学习基于优化的算法的基本思想。
......
......@@ -199,11 +199,11 @@ ReLU 是非常简单的非线性函数,当`x <= 0`,返回`y = 0`;当`x > 0
## 神经网络中的过拟合
我们看到,在回归的情况下,可以添加太多特征,从而有可能使网络过拟合。 这样一来,模型可以很好地拟合训练数据,但不能很好地推广到看不见的测试数据集。 这是神经网络中的一个普遍问题,因为模型复杂性的提高意味着通常有可能将函数拟合到不一定要泛化的数据训练集中。 以下是数据集每次向前和反向传播(称为历元)后训练和测试数据集上的总损失的图:
我们看到,在回归的情况下,可以添加太多特征,从而有可能使网络过拟合。 这样一来,模型可以很好地拟合训练数据,但不能很好地推广到看不见的测试数据集。 这是神经网络中的一个普遍问题,因为模型复杂性的提高意味着通常有可能将函数拟合到不一定要泛化的数据训练集中。 以下是数据集每次向前和反向传播(称为周期)后训练和测试数据集上的总损失的图:
![Figure 1.14 – Test and training epochs ](img/B12365_01_14.jpg)
图 1.14 –测试和训练
图 1.14 –测试和训练
在这里,我们可以看到随着我们继续训练网络,随着我们向总损失最小化的方向靠近,训练损失会随着时间的推移而减小。 虽然这可以很好地推广到测试数据集,但一段时间后,由于我们的函数过度适合训练集中的数据,测试数据集上的总损失开始增加。 一种解决方案是**提前停止**。 因为我们希望我们的模型对之前从未见过的数据做出良好的预测,所以我们可以在测试损失最小的时候停止训练我们的模型。 经过全面训练的 NLP 模型可能能够轻松地对以前见过的句子进行分类,但是,对真正了解到某些东西的模型的衡量标准是能够对看不见的数据进行预测。
......
......@@ -331,7 +331,7 @@ Loss(y) = -log(y)
print ('Epoch [%d/%d] Loss: %.4f' %(epoch+1, 50, loss.data.item()))
```
一般而言,我们预计损失会在每个期减少。 我们的输出将如下所示:
一般而言,我们预计损失会在每个期减少。 我们的输出将如下所示:
![Figure 2.14 – Training epochs ](img/B12365_02_14.jpg)
......@@ -493,7 +493,7 @@ print((correct/preds)*100)
## 训练分类器
首先,我们建立一个循环,该循环由希望模型运行的期数组成。 在这种情况下,我们将选择 100 个周期。
首先,我们建立一个循环,该循环由希望模型运行的期数组成。 在这种情况下,我们将选择 100 个周期。
在此循环中,我们首先将梯度归零(否则,PyTorch 会累积计算梯度),然后对于每个句子/标签对,分别将其转换为词袋向量和目标。 然后,通过使数据向前通过模型的当前状态,我们计算出该特定句子对的预测输出。
......
......@@ -279,7 +279,7 @@ X = ["is", "a", "learning", "framework"]; y = "deep"
图 3.11 –张量值
0. 现在,我们训练我们的网络。我们循环通过 100 个周期,对于每一个通道,我们循环通过我们所有的上下文词,也就是目标词对。对于这些对,我们使用`make_sentence_vector()`加载上下文句子,并使用我们当前的模型状态来获得预测。我们根据我们的实际目标评估这些预测,以获得我们的损失。我们反推计算梯度,并通过我们的优化器来更新权重。最后,我们将该时代的所有损失相加并打印出来。在这里,我们可以看到,我们的损失正在减少,这表明我们的模型正在学习。
0. 现在,我们训练我们的网络。我们循环通过 100 个周期,对于每一个通道,我们循环通过我们所有的上下文词,也就是目标词对。对于这些对,我们使用`make_sentence_vector()`加载上下文句子,并使用我们当前的模型状态来获得预测。我们根据我们的实际目标评估这些预测,以获得我们的损失。我们反推计算梯度,并通过我们的优化器来更新权重。最后,我们将该周期的所有损失相加并打印出来。在这里,我们可以看到,我们的损失正在减少,这表明我们的模型正在学习。
```py
for epoch in range(100):
......
......@@ -395,7 +395,7 @@ valid_data = TensorDataset(valid_x, valid_y)
test_data = TensorDataset(test_x, test_y)
```
然后,我们使用这些数据集创建 PyTorch `DataLoader`对象。 `DataLoader`允许我们使用`batch_size`参数批量处理数据集,从而可以轻松地将不同的批量大小传递给我们的模型。 在这种情况下,我们将使其保持简单,并设置`batch_size = 1`,这意味着我们的模型将针对单个句子进行训练,而不是使用大量数据。 我们还选择随机调整`DataLoader`对象,以便数据以随机顺序(而不是每个期相同)通过神经网络传递,从而有可能从训练顺序中消除任何有偏差的结果:
然后,我们使用这些数据集创建 PyTorch `DataLoader`对象。 `DataLoader`允许我们使用`batch_size`参数批量处理数据集,从而可以轻松地将不同的批量大小传递给我们的模型。 在这种情况下,我们将使其保持简单,并设置`batch_size = 1`,这意味着我们的模型将针对单个句子进行训练,而不是使用大量数据。 我们还选择随机调整`DataLoader`对象,以便数据以随机顺序(而不是每个期相同)通过神经网络传递,从而有可能从训练顺序中消除任何有偏差的结果:
```py
batch_size = 1
......@@ -431,9 +431,9 @@ for epoch in range(n_epochs):
        optimizer.step()
```
在这里,我们只训练了多个时期的模型,对于每个时期,我们首先使用批量大小参数初始化隐藏层。 在这种情况下,我们设置`batch_size = 1`,因为我们一次只训练我们的模型一个句子。 对于训练装载机中的每批输入语句和标签,我们首先将梯度归零(以防止它们累积),并使用模型的当前状态使用数据的正向传播来计算模型输出。 然后使用此输出,使用模型的预测输出和正确的标签来计算损失。 然后,我们通过网络对该损失进行反向传递,以计算每个阶段的梯度。 接下来,我们使用`grad_clip_norm()`函数裁剪梯度,因为这将阻止梯度爆炸,如本章前面所述。 我们定义了`clip = 5`,这意味着任何给定节点的最大梯度为`5`。 最后,我们通过调用`optimizer.step()`,使用在反向传播中计算出的梯度来更新权重。
在这里,我们只训练了多个周期的模型,对于每个周期,我们首先使用批量大小参数初始化隐藏层。 在这种情况下,我们设置`batch_size = 1`,因为我们一次只训练我们的模型一个句子。 对于训练装载机中的每批输入语句和标签,我们首先将梯度归零(以防止它们累积),并使用模型的当前状态使用数据的正向传播来计算模型输出。 然后使用此输出,使用模型的预测输出和正确的标签来计算损失。 然后,我们通过网络对该损失进行反向传递,以计算每个阶段的梯度。 接下来,我们使用`grad_clip_norm()`函数裁剪梯度,因为这将阻止梯度爆炸,如本章前面所述。 我们定义了`clip = 5`,这意味着任何给定节点的最大梯度为`5`。 最后,我们通过调用`optimizer.step()`,使用在反向传播中计算出的梯度来更新权重。
如果我们自己运行此循环,我们将训练我们的模型。 但是,我们想在每个期之后评估模型的表现,以便根据验证数据集确定模型的表现。 我们这样做如下:
如果我们自己运行此循环,我们将训练我们的模型。 但是,我们想在每个期之后评估模型的表现,以便根据验证数据集确定模型的表现。 我们这样做如下:
```py
if (step % print_every) == 0:            
......@@ -451,7 +451,7 @@ if (step % print_every) == 0:            
            net.train()
```
这意味着在每个期结束时,我们的模型都会调用`net.eval()`冻结模型的权重,并像以前一样使用我们的数据进行正向传播。 请注意,当我们处于评估模式时,也不会应用丢弃。 但是,这次,我们使用验证加载程序,而不是使用训练数据加载程序。 通过这样做,我们可以在我们的验证数据集中计算模型当前状态的总损失。 最后,我们打印结果并调用`net.train()`解冻模型的权重,以便我们可以在下一个周期再次进行训练。 我们的输出看起来像,如下所示:
这意味着在每个期结束时,我们的模型都会调用`net.eval()`冻结模型的权重,并像以前一样使用我们的数据进行正向传播。 请注意,当我们处于评估模式时,也不会应用丢弃。 但是,这次,我们使用验证加载程序,而不是使用训练数据加载程序。 通过这样做,我们可以在我们的验证数据集中计算模型当前状态的总损失。 最后,我们打印结果并调用`net.train()`解冻模型的权重,以便我们可以在下一个周期再次进行训练。 我们的输出看起来像,如下所示:
![Figure 5.18 – Training the model ](img/B12365_05_18.jpg)
......@@ -463,7 +463,7 @@ if (step % print_every) == 0:            
torch.save(net.state_dict(), 'model.pkl')
```
在为三个时期训练了我们的模型之后,我们注意到了两个主要方面。 我们将首先从好消息开始-我们的模型正在学习一些东西! 我们的训练损失不仅下降了,而且在每个时期之后,我们在验证集上的损失也下降了。 这意味着我们的模型仅在三个时期后就可以更好地预测看不见的数据的情感! 坏消息是,我们的模型过拟合。 我们的训练损失比验证损失要低得多,这表明虽然我们的模型已经学会了如何很好地预测训练数据集,但这并不能推广到看不见的数据集。 预期会发生这种情况,因为我们使用的训练数据非常少(仅 2,400 个训练语句)。 当我们训练整个嵌入层时,很可能许多单词在训练集中只出现一次,而在验证集中却没有出现,反之亦然,这使得该模型几乎不可能归纳出我们的语料库中所有不同的单词。 在实践中,我们希望在更大的数据集上训练我们的模型,以使我们的模型学习如何更好地归纳。 我们还在很短的时间内训练了该模型,并且没有执行超参数调整来确定模型的最佳迭代。 随意尝试更改模型中的某些参数(例如训练时间,隐藏状态大小,嵌入大小等),以提高模型的表现。
在为三个周期训练了我们的模型之后,我们注意到了两个主要方面。 我们将首先从好消息开始-我们的模型正在学习一些东西! 我们的训练损失不仅下降了,而且在每个周期之后,我们在验证集上的损失也下降了。 这意味着我们的模型仅在三个周期后就可以更好地预测看不见的数据的情感! 坏消息是,我们的模型过拟合。 我们的训练损失比验证损失要低得多,这表明虽然我们的模型已经学会了如何很好地预测训练数据集,但这并不能推广到看不见的数据集。 预期会发生这种情况,因为我们使用的训练数据非常少(仅 2,400 个训练语句)。 当我们训练整个嵌入层时,很可能许多单词在训练集中只出现一次,而在验证集中却没有出现,反之亦然,这使得该模型几乎不可能归纳出我们的语料库中所有不同的单词。 在实践中,我们希望在更大的数据集上训练我们的模型,以使我们的模型学习如何更好地归纳。 我们还在很短的时间内训练了该模型,并且没有执行超参数调整来确定模型的最佳迭代。 随意尝试更改模型中的某些参数(例如训练时间,隐藏状态大小,嵌入大小等),以提高模型的表现。
尽管我们的模型过拟合,但它仍然学到了一些东西。 现在,我们希望在最终的测试数据集上评估我们的模型。 我们使用之前定义的测试加载器对数据执行了最后一次传递。 在此过程中,我们遍历所有测试数据并使用最终模型进行预测:
......
......@@ -392,7 +392,7 @@ def multi_accuracy(preds, y):
    return acc
```
在这里,对于我们的预测,我们的模型使用`torch.max`函数对所有预测返回具有最高预测值的索引。 对于这些预测中的每一个,如果此预测索引与标签的索引相同,则将其视为正确的预测。 然后,我们对所有这些正确的预测进行计数,然后将它们除以预测的总数,以得出多类准确率的度量。 我们可以在训练循环中使用此函数来测量每个期的准确率。
在这里,对于我们的预测,我们的模型使用`torch.max`函数对所有预测返回具有最高预测值的索引。 对于这些预测中的每一个,如果此预测索引与标签的索引相同,则将其视为正确的预测。 然后,我们对所有这些正确的预测进行计数,然后将它们除以预测的总数,以得出多类准确率的度量。 我们可以在训练循环中使用此函数来测量每个期的准确率。
接下来,我们定义训练函数。 最初,我们将时间段的损失和准确率设置为`0`,我们将其称为`model.train()`以允许我们在训练模型时更新模型中的参数:
......@@ -424,7 +424,7 @@ for batch in iterator:
optimizer.step()
```
最后,我们将这一批量的损失和准确率加到整个时期的总损失和准确率中。 在循环遍历该时期内的所有批量之后,我们计算该时期的总损失和准确率并返回:
最后,我们将这一批量的损失和准确率加到整个周期的总损失和准确率中。 在循环遍历该周期内的所有批量之后,我们计算该周期的总损失和准确率并返回:
```py
epoch_loss += loss.item()
......@@ -446,7 +446,7 @@ with torch.no_grad():
这两个步骤将模型设置为评估模式,忽略任何遗漏函数,并确保未计算和更新梯度。 这是因为我们希望在评估表现时冻结模型中的权重,并确保不使用验证数据对模型进行训练,因为我们希望将其与用于训练模型的数据分开保存 。
现在,我们只需要与数据迭代器一起循环调用训练和评估函数,即可训练模型。 我们首先定义希望模型训练的时期数。 我们还定义了我们的模型迄今为止所实现的最低验证损失。 这是因为我们只希望使训练后的模型具有最低的验证损失(即表现最佳的模型)。 这意味着,如果我们的模型训练了多个时期并开始过拟合,那么只有这些模型的最佳表现将被保留,这意味着选择大量时期的后果会更少。
现在,我们只需要与数据迭代器一起循环调用训练和评估函数,即可训练模型。 我们首先定义希望模型训练的周期数。 我们还定义了我们的模型迄今为止所实现的最低验证损失。 这是因为我们只希望使训练后的模型具有最低的验证损失(即表现最佳的模型)。 这意味着,如果我们的模型训练了多个周期并开始过拟合,那么只有这些模型的最佳表现将被保留,这意味着选择大量周期的后果会更少。
我们将最低的验证损失初始化为无穷大,开始于:
......@@ -455,7 +455,7 @@ epochs = 10
lowest_validation_loss = float('inf')
```
接下来,我们定义训练循环,一次将跨一个期。 我们记录训练的开始和结束时间,以便我们可以计算出每个步骤花费的时间。 然后,我们只需使用训练数据迭代器对模型调用训练函数来计算训练损失和准确率,并在此过程中更新模型。 然后,我们使用验证迭代器上的评估函数重复此过程,以计算验证数据的损失和准确率,而无需更新模型:
接下来,我们定义训练循环,一次将跨一个期。 我们记录训练的开始和结束时间,以便我们可以计算出每个步骤花费的时间。 然后,我们只需使用训练数据迭代器对模型调用训练函数来计算训练损失和准确率,并在此过程中更新模型。 然后,我们使用验证迭代器上的评估函数重复此过程,以计算验证数据的损失和准确率,而无需更新模型:
```py
for epoch in range(epochs):
......@@ -467,7 +467,7 @@ for epoch in range(epochs):
    end_time = time.time()
```
此后,我们确定在当前时代之后,我们的模型是否优于目前表现最好的模型:
此后,我们确定在当前周期之后,我们的模型是否优于目前表现最好的模型:
如果有效损失
......@@ -477,9 +477,9 @@ if valid_loss < lowest_validation_loss:
    torch.save(model.state_dict(), 'cnn_model.pt')
```
如果此期之后的损失低于到目前为止的最低验证损失,则将验证损失设置为新的最低验证损失,并保存我们当前的模型权重。
如果此期之后的损失低于到目前为止的最低验证损失,则将验证损失设置为新的最低验证损失,并保存我们当前的模型权重。
最后,我们仅在每个时期之后打印结果。 如果一切工作正常,我们应该看到我们的训练损失在每个时期之后都有所下降,而我们的验证损失有望照此执行:
最后,我们仅在每个周期之后打印结果。 如果一切工作正常,我们应该看到我们的训练损失在每个周期之后都有所下降,而我们的验证损失有望照此执行:
```py
print(f'Epoch: {epoch+1:02} | Epoch Time: {int(end_time - start_time)}s')
......@@ -493,7 +493,7 @@ print(f'\t Val. Loss: {valid_loss:.3f} |  Val. Acc: {valid_acc*100:.2f}%')
图 6.17 –测试模型
值得庆幸的是,我们发现确实存在。 训练和验证损失在每个期都会下降,准确率也会提高,这表明我们的模型确实在学习! 经过多次训练后,我们可以采用最佳模型并进行预测。
值得庆幸的是,我们发现确实存在。 训练和验证损失在每个期都会下降,准确率也会提高,这表明我们的模型确实在学习! 经过多次训练后,我们可以采用最佳模型并进行预测。
## 使用经过训练的 CNN 的预测
......
......@@ -493,7 +493,7 @@ def forward(self, input, h, cell):
lowest_validation_loss = float('inf')
```
1. 然后,我们循环浏览我们的每个时代,并在每个时代内,使用我们的`train()`和·evaluate()函数计算我们的训练和验证损失。我们还通过在训练过程前后调用`time.time()`来计算时间。
1. 然后,我们循环浏览我们的每个周期,并在每个周期内,使用我们的`train()`和·evaluate()函数计算我们的训练和验证损失。我们还通过在训练过程前后调用`time.time()`来计算时间。
```py
for epoch in range(epochs):
......@@ -506,7 +506,7 @@ def forward(self, input, h, cell):
    end_time = time.time()
```
2. 接下来,对于每个时代,我们确定我们刚刚训练的模型是否是我们迄今为止看到的表现最好的模型。如果我们的模型在我们的验证数据上表现最好(如果验证损失是我们迄今为止看到的最低的),我们就保存我们的模型。
2. 接下来,对于每个周期,我们确定我们刚刚训练的模型是否是我们迄今为止看到的表现最好的模型。如果我们的模型在我们的验证数据上表现最好(如果验证损失是我们迄今为止看到的最低的),我们就保存我们的模型。
```py
if valid_loss < lowest_validation_loss:
......
......@@ -717,7 +717,7 @@ for line in lines[:3]:
                        range(n_iteration)]
```
0. 然后,我们创建一些变量,使我们能够计算迭代次数,并跟踪每个时代的总损失。
0. 然后,我们创建一些变量,使我们能够计算迭代次数,并跟踪每个周期的总损失。
```py
print('Starting ...')
......@@ -1033,7 +1033,7 @@ print('Response:', ' '.join(output_words))
图 8.15 –训练模型
您的模型正在训练中! 根据许多因素,例如您将模型设置为训练多少个期以及是否使用 GPU,模型可能需要一些时间来训练。 完成后,您将看到以下输出。 如果一切正常,则模型的平均损失将大大低于开始训练时的损失,这表明模型已经学到了一些有用的信息:
您的模型正在训练中! 根据许多因素,例如您将模型设置为训练多少个期以及是否使用 GPU,模型可能需要一些时间来训练。 完成后,您将看到以下输出。 如果一切正常,则模型的平均损失将大大低于开始训练时的损失,这表明模型已经学到了一些有用的信息:
![Figure 8.16 – Average loss after 4,000 iterations ](img/B12365_08_16.jpg)
......
......@@ -311,7 +311,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
在此秘籍中,我们用对数 softmax 替换了 softmax,以便随后可以使用概率对数而不是概率的对数,这具有很好的理论解释。 这样做有多种原因,包括改进的数值表现和梯度优化。 在训练可能具有计算挑战性和昂贵成本的模型时,这些优势非常重要。 此外,当它没有预测正确的类别时,它具有很高的惩罚作用。
因此,在处理对数 softmax 时,我们会使用负对数似然率,因为 softmax 不兼容。 在`n`类数之间的分类中很有用。 该对数将确保我们不会处理 0 到 1 之间的非常小的值,而负值将确保小于 1 的概率的对数非零。 我们的目标是减少这种负的对数失误差函数。 在 PyTorch 中,损失函数称为**标准**,因此我们将损失函数命名为`criterion`
因此,在处理对数 softmax 时,我们会使用负对数似然率,因为 softmax 不兼容。 在`n`类数之间的分类中很有用。 该对数将确保我们不会处理 0 到 1 之间的非常小的值,而负值将确保小于 1 的概率的对数非零。 我们的目标是减少这种负的对数失误差函数。 在 PyTorch 中,损失函数称为**标准**,因此我们将损失函数命名为`criterion`
# 更多
......@@ -367,7 +367,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
>>optimizer = optim.Adam(model.parameters(), lr=3e-3)
```
5.现在,我们将开始训练我们的模型,从期数开始:
5.现在,我们将开始训练我们的模型,从期数开始:
```py
>>epoch = 10
......@@ -433,7 +433,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
>>running_loss += loss.item()
```
16.最后,我们将在每个期之后打印损失:
16.最后,我们将在每个期之后打印损失:
```py
>>else:
......@@ -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`; 在那里,它评估了预测类与实际类之间的差异。
......@@ -546,7 +546,7 @@ Training loss: 0.2596
# 工作原理
在此秘籍中,我们更改了`__init__()`方法,以 0.25 的丢失率添加了该丢失层,这意味着将应用该丢失的层中 25% 的神经元将被随机关闭。 然后,我们编辑`forward`函数,将其应用于其中具有 256 个单元的第一个隐藏层,然后对第二个层(具有 128 个单元)应用该滤除。 在完成激活函数之后,我们在两个层中都应用了激活。 我们必须牢记,必须仅在隐藏层上应用丢弃,以防止我们丢失输入数据和丢失输出。
在此秘籍中,我们更改了`__init__()`方法,以 0.25 的丢弃率添加了该丢弃层,这意味着将应用该丢弃层中 25% 的神经元将被随机关闭。 然后,我们编辑`forward`函数,将其应用于其中具有 256 个单元的第一个隐藏层,然后对第二个层(具有 128 个单元)应用该滤除。 在完成激活函数之后,我们在两个层中都应用了激活。 我们必须牢记,必须仅在隐藏层上应用丢弃,以防止我们丢失输入数据和丢失输出。
# 更多
......
......@@ -686,7 +686,7 @@ CNN(
# 更多
您可以尝试不同的配置以用于丢,卷积和池化层,甚至可以更改每种类型的层数。
您可以尝试不同的配置以用于丢,卷积和池化层,甚至可以更改每种类型的层数。
# 另见
......@@ -734,7 +734,7 @@ CNN(
>>optimizer = optim.SGD(model.parameters(), lr=0.01)
```
6.现在,我们将通过设置期数来开始训练循环:
6.现在,我们将通过设置期数来开始训练循环:
```py
>>n_epochs = 30
......@@ -808,14 +808,14 @@ for batch_idx, (data, target) in enumerate(valid_loader):
valid_loss += loss.item()*data.size(0)
```
17.然后,我们将计算每个期的损失:
17.然后,我们将计算每个期的损失:
```py
train_loss = train_loss/len(train_loader.sampler)
valid_loss = valid_loss/len(valid_loader.sampler)
```
18.最后,我们在每个期打印模型表现:
18.最后,我们在每个期打印模型表现:
```py
print(f'| Epoch: {epoch:02} | Train Loss: {train_loss:.3f} | Val. Loss: {valid_loss:.3f} |')
......@@ -865,7 +865,7 @@ valid_loss = valid_loss/len(valid_loader.sampler)
然后,我们定义了损失函数,也称为`criterion`。 由于这是一个分类问题,因此我们使用了交叉熵损失。 然后,我们选择 SGD 优化器在反向传播时更新模型权重,学习率为 0.01,并使用`model.parameters()`传入模型参数。 然后,我们将模型运行了 30 个周期,尽管我们可以选择任何合理的数目来执行此操作。 在循环中,我们将训练和验证损失重置为 0,并将模型设置为训练模式,然后遍历训练数据集中的每个批量。 我们首先将批量移至设备,这样,如果我们的 GPU 内存有限,则并非所有数据都不会完全加载到 GPU 内存中。 然后,我们将输入张量传递到模型中,并获取输出,并将其传递到损失函数中,以评估预测标签和真实标签之间的差异。
此后,我们使用`loss.backward()`进行了反向传播,并使用`optimizer.step()`步骤更新了模型权重。 然后,我们使用总历时损失来汇总批量中的损失。 然后,我们使用`model.eval()`将模型转换为评估模型,因为该模型的表现需要在验证集上进行评估,并且该模型在此阶段中不会学习,因此我们也需要关闭退出项。 遍历验证批量,我们获得了模型输出,并在整个时期累积了验证批量之间的损失。 此后,我们格式化了模型表现,以查看每个时期模型的变化。 我们注意到,模型训练和验证损失随时间的推移而减少,这表明模型正在学习。
此后,我们使用`loss.backward()`进行了反向传播,并使用`optimizer.step()`步骤更新了模型权重。 然后,我们使用总历时损失来汇总批量中的损失。 然后,我们使用`model.eval()`将模型转换为评估模型,因为该模型的表现需要在验证集上进行评估,并且该模型在此阶段中不会学习,因此我们也需要关闭退出项。 遍历验证批量,我们获得了模型输出,并在整个周期累积了验证批量之间的损失。 此后,我们格式化了模型表现,以查看每个周期模型的变化。 我们注意到,模型训练和验证损失随时间的推移而减少,这表明模型正在学习。
# 更多
......
......@@ -269,7 +269,7 @@ pip install torchtext
# 开发迭代器
迭代器用于从数据集中加载一批数据。 它们提供了使加载数据和将数据移动到适当设备的方法更加容易。 我们可以使用这些迭代器对象遍历历元时对数据进行迭代。 在本秘籍中,我们将从数据集中开发这些迭代器。 您将需要完成“开发数据集”秘籍中的步骤,因为我们将在此处使用该秘籍中的`Dataset`对象。
迭代器用于从数据集中加载一批数据。 它们提供了使加载数据和将数据移动到适当设备的方法更加容易。 我们可以使用这些迭代器对象遍历周期时对数据进行迭代。 在本秘籍中,我们将从数据集中开发这些迭代器。 您将需要完成“开发数据集”秘籍中的步骤,因为我们将在此处使用该秘籍中的`Dataset`对象。
# 操作步骤
......
......@@ -106,7 +106,7 @@ return model
# 实现模型训练
在本秘籍中,我们将实现一个在单个期内训练模型的函数。 此函数进一步记录模型的训练指标并将其绘制到 TensorBoard 上。 我们将传入模型,训练数据,优化器和模型训练准则,并将返回训练损失。
在本秘籍中,我们将实现一个在单个期内训练模型的函数。 此函数进一步记录模型的训练指标并将其绘制到 TensorBoard 上。 我们将传入模型,训练数据,优化器和模型训练准则,并将返回训练损失。
# 操作步骤
......@@ -151,15 +151,15 @@ return model
# 工作原理
在此秘籍中,我们定义了执行训练期的函数。 在开始训练过程之前,我们使用`.train()`将模型设置为训练模式,并将训练损失设置为`0`。 然后,我们遍历训练数据并将输入数据点及其对应的标签移到可用设备(CPU 或 GPU)上。
在此秘籍中,我们定义了执行训练期的函数。 在开始训练过程之前,我们使用`.train()`将模型设置为训练模式,并将训练损失设置为`0`。 然后,我们遍历训练数据并将输入数据点及其对应的标签移到可用设备(CPU 或 GPU)上。
然后,我们清除梯度,进行模型预测,然后将其传递给准则以确定训练损失。 然后,我们对损失进行了反向传播,并更新了模型的权重。 由于模型是冻结的,因此它仅更新模型中分类器的权重。
最后,我们使用 TensorBoard 中`SummaryWriter`对象中的`SummaryWriter`对象中的`add_scalar()`方法在 TensorBoard 中记录了训练指标-我们在其中传递了一个标签,一个标量值和一个计数器,在本例中为历元数 。
最后,我们使用 TensorBoard 中`SummaryWriter`对象中的`SummaryWriter`对象中的`add_scalar()`方法在 TensorBoard 中记录了训练指标-我们在其中传递了一个标签,一个标量值和一个计数器,在本例中为周期数 。
# 实现模型测试
在此秘籍中,我们将定义一个函数以在一个期内根据验证数据测试模型。 此函数还将测试指标记录到 TensorBoard 上。 我们还将添加工具函数,通过绘制图像并以可读的方式标记这些图像来记录模型中的一些错误分类。
在此秘籍中,我们将定义一个函数以在一个期内根据验证数据测试模型。 此函数还将测试指标记录到 TensorBoard 上。 我们还将添加工具函数,通过绘制图像并以可读的方式标记这些图像来记录模型中的一些错误分类。
# 操作步骤
......@@ -405,7 +405,7 @@ tensorboard --logdir=log_dir/ --port 6006
# 训练模型和解冻层
在本秘籍中,我们将为数据集的预定义迭代次数完成模型训练。 我们将在模型训练期间保存最佳模型。 一旦针对给定的期数训练了模型,我们将使用最佳模型的权重加载模型。 然后,我们将解冻模型的先前冻结的 ResNet 层,并训练模型以较低的学习率微调权重。
在本秘籍中,我们将为数据集的预定义迭代次数完成模型训练。 我们将在模型训练期间保存最佳模型。 一旦针对给定的期数训练了模型,我们将使用最佳模型的权重加载模型。 然后,我们将解冻模型的先前冻结的 ResNet 层,并训练模型以较低的学习率微调权重。
# 操作步骤
......@@ -425,7 +425,7 @@ tensorboard --logdir=log_dir/ --port 6006
>>optimizer = optim.Adam(model.parameters())
```
3. 我们将定义一个函数来跨期训练我们的模型:
3. 我们将定义一个函数来跨期训练我们的模型:
```py
>>def train_epochs(model, device, dataloaders, criterion, optimizer,epochs, writer):
......@@ -563,13 +563,13 @@ Epoch | Training Loss | Test Loss | Accuracy |
# 工作原理
在此秘籍中,我们创建了模型并将其移至可用设备,并分别使用负对数损失和 Adam 作为我们的标准和优化器。 `train_epochs()`方法用于在定义的时期范围内训练模型。 在每个时期结束时,我们使用`writer.flush()`方法来确保所有未决事件已写入磁盘。 最后,我们使用`writer.close()`刷新关闭编写器。 我们还在此函数中保存了最佳模型,以供日后重新加载。
在此秘籍中,我们创建了模型并将其移至可用设备,并分别使用负对数损失和 Adam 作为我们的标准和优化器。 `train_epochs()`方法用于在定义的周期范围内训练模型。 在每个周期结束时,我们使用`writer.flush()`方法来确保所有未决事件已写入磁盘。 最后,我们使用`writer.close()`刷新关闭编写器。 我们还在此函数中保存了最佳模型,以供日后重新加载。
然后,我们从到目前为止的训练中重新加载了最佳模型,并对其进行了冻结以进行微调。 解冻后,所有模型参数均可用于训练。 我们将优化器设置为较低的学习率,对该未冻结的模型进行了更多的训练,并记录了模型的表现。 我们看到,通过微调,我们的模型表现更好。
从 TensorBoard 图中,我们看到冻结模型中的指标为橙色,解冻后的指标为蓝色,这表明模型解冻后的表现有所提高。 然后,我们从训练数据中采样了图像网格图,并从各个期对分类错误的示例进行了采样。
从 TensorBoard 图中,我们看到冻结模型中的指标为橙色,解冻后的指标为蓝色,这表明模型解冻后的表现有所提高。 然后,我们从训练数据中采样了图像网格图,并从各个期对分类错误的示例进行了采样。
我们看到训练和测试损失在各个期都减少了,准确率提高了。
我们看到训练和测试损失在各个期都减少了,准确率提高了。
# 更多
......
......@@ -551,7 +551,7 @@ Epoch : | 005 / 050 |
然后,我们开始训练生成器,并且生成器应该能够欺骗判别器。 生成器必须纠正鉴别者正确预测生成的图像为假的情况。 因此,只要来自判别器的预测将生成的图像标记为伪造,就会增加生成器损失`gerror`。 然后,我们计算梯度并更新生成器权重。
然后,我们定期显示模型指标,并保存固定噪声生成器生成的图像,以可视化模型在各个期的表现。
然后,我们定期显示模型指标,并保存固定噪声生成器生成的图像,以可视化模型在各个期的表现。
# 更多
......
......@@ -80,7 +80,7 @@ output_size = 4
hidden_size = 100
```
我们需要在程序顶部定义输入和输出大小,这将帮助我们在不同的地方使用输入和输出大小,例如网络设计函数。 隐藏大小是隐藏层中神经元的数量。 如果要手动设计神经网络,则权重矩阵的大小为`input_size` x `hidden_size`,这会将您输入的大小`input_size`转换为大小`hidden_size``epoch`是通过网络进行迭代的计数器值。 `epoch`的概念最终取决于程序员如何定义迭代过程。 通常,对于每个时期,您都要遍历整个数据集,然后对每个时期重复一次。
我们需要在程序顶部定义输入和输出大小,这将帮助我们在不同的地方使用输入和输出大小,例如网络设计函数。 隐藏大小是隐藏层中神经元的数量。 如果要手动设计神经网络,则权重矩阵的大小为`input_size` x `hidden_size`,这会将您输入的大小`input_size`转换为大小`hidden_size``epoch`是通过网络进行迭代的计数器值。 `epoch`的概念最终取决于程序员如何定义迭代过程。 通常,对于每个周期,您都要遍历整个数据集,然后对每个周期重复一次。
```py
for i in epoch:
......@@ -226,7 +226,7 @@ for epoch in range(epochs):
b2 -= lr * b2.grad
```
前面的代码段与在第 1 章,“深度学习演练和 PyTorch 简介”中看到的相同,其中解释了静态和动态计算图,但在这里我们从另一个角度来看一下代码:模型说明。 它从循环遍历每个期的批量开始,并使用我们正在构建的模型处理每个批量。 与基于静态计算图的框架不同,我们尚未构建图。 我们刚刚定义了超参数,并根据我们的数据制作了张量。
前面的代码段与在第 1 章,“深度学习演练和 PyTorch 简介”中看到的相同,其中解释了静态和动态计算图,但在这里我们从另一个角度来看一下代码:模型说明。 它从循环遍历每个期的批量开始,并使用我们正在构建的模型处理每个批量。 与基于静态计算图的框架不同,我们尚未构建图。 我们刚刚定义了超参数,并根据我们的数据制作了张量。
##### 构建图
......
......@@ -290,7 +290,7 @@ print(next(iter(test_iter)))
`sort_key`使用我们传递的`lambda`函数对数据集进行排序。 在某些情况下,对数据集进行排序会有所帮助,而在大多数情况下,随机性会帮助网络学习一般情况。 `Iterator`足够聪明,可以使用通过参数传递的批量大小来批量输入数据集,但是它并不止于此。 它可以动态地将所有序列填充到每批最长序列的长度。 `Iterator`的输出(如`print`语句所示)为`TEXT`数据,其大小为`16x99`,其中`99`是我们为测试数据集传递的批量大小,而 16 是该数据集的长度。 该特定批量中最长的序列。
如果`Iterator`类需要更巧妙地处理事情怎么办? 如果数据集用于语言建模,并且我们需要一个数据集来进行**时间上的反向传播****BPTT**),那该怎么办? `torchtext`也为这些模块抽象了模块,这些模块继承自我们刚刚使用的`Iterator`类。 `BucketIterator`模块将序列进行更智能的分组,以便将具有相同长度的序列归为一组,并且此减少了将噪声引入数据集的不必要填充的长度。 `BucketIterator`还可以在每个期对批量进行混洗,并在数据集中保持足够的随机性,从而使网络无法从数据集中的顺序中学习,这实际上并没有在教授任何现实世界的信息。
如果`Iterator`类需要更巧妙地处理事情怎么办? 如果数据集用于语言建模,并且我们需要一个数据集来进行**时间上的反向传播****BPTT**),那该怎么办? `torchtext`也为这些模块抽象了模块,这些模块继承自我们刚刚使用的`Iterator`类。 `BucketIterator`模块将序列进行更智能的分组,以便将具有相同长度的序列归为一组,并且此减少了将噪声引入数据集的不必要填充的长度。 `BucketIterator`还可以在每个期对批量进行混洗,并在数据集中保持足够的随机性,从而使网络无法从数据集中的顺序中学习,这实际上并没有在教授任何现实世界的信息。
`BPTTIterator`是从`Iterator`类继承的另一个模块,可帮助语言建模数据集,并且需要为`t`的每个输入从`t + 1`获取标签。`t`是时间。 `BPTTIterator`接受输入数据的连续流和输出数据的连续流(在翻译网络的情况下,输入流和输出流可以不同,在语言建模网络的情况下,输入流和输出流可以相同)并将其转换为迭代器,它遵循前面描述的时间序列规则。
......@@ -421,7 +421,7 @@ python -m torch.utils.bottleneck /path/to/source/script.py [args]
```
瓶颈可以找到有关环境的更多信息,还可以从`autograd.profiler`和 cProfiler 提供配置文件信息。 但是对于两者而言,瓶颈都会两次执行该程序,因此减少的期数是使程序在相当长的时间内停止执行的一个好选择。 我在第二章的同一程序上使用了瓶颈,这是输出屏幕:
瓶颈可以找到有关环境的更多信息,还可以从`autograd.profiler`和 cProfiler 提供配置文件信息。 但是对于两者而言,瓶颈都会两次执行该程序,因此减少的期数是使程序在相当长的时间内停止执行的一个好选择。 我在第二章的同一程序上使用了瓶颈,这是输出屏幕:
![Bottleneck and profiling](img/B09475_03_05.jpg)
......@@ -492,11 +492,11 @@ evaluator.run(val_loader)
函数`create_supervised_trainer``create_supervised_evaluator`返回一个`Engine`对象,该对象具有类似于`training_loop`的函数来执行代码的公共模式,如先前给出的那样。 除了给定的参数,这两个函数还接受一个设备(CPU 或 GPU),该设备返回在我们指定的设备上运行的训练器或评估器`Engine`实例。 现在情况越来越好了吧? 我们传递了定义的模型,所需的优化器以及正在使用的损失函数,但是在有了训练器和`evaluator`对象之后我们该怎么办?
`Engine`对象定义了`run`方法,该方法使循环根据传递给`run`函数的时期和加载器开始执行。 与往常一样,`run`方法使`trainer`循环从零到历元数。 对于每次迭代,我们的训练器都会通过加载程序进行梯度更新。
`Engine`对象定义了`run`方法,该方法使循环根据传递给`run`函数的周期和加载器开始执行。 与往常一样,`run`方法使`trainer`循环从零到周期数。 对于每次迭代,我们的训练器都会通过加载程序进行梯度更新。
训练完成后,`evaluator``val_loader`开始,并通过使用评估数据集运行相同的模型来确保情况得到改善。
那很有趣,但仍然缺少一些片段。 如果用户需要在每个期之后运行`evaluator`,或者如果用户需要训练器将模型的精度打印到终端,或者将其绘制到 Visdom,Turing 或 Network 图上,该怎么办? 在前面的设置中,有没有办法让知道验证准确率是什么? 您可以通过覆盖`Engine`的默认记录器来完成大部分操作,该记录器本质上是保存在`trainer_logger`变量中的 Python 记录器,但实际的答案是事件。
那很有趣,但仍然缺少一些片段。 如果用户需要在每个期之后运行`evaluator`,或者如果用户需要训练器将模型的精度打印到终端,或者将其绘制到 Visdom,Turing 或 Network 图上,该怎么办? 在前面的设置中,有没有办法让知道验证准确率是什么? 您可以通过覆盖`Engine`的默认记录器来完成大部分操作,该记录器本质上是保存在`trainer_logger`变量中的 Python 记录器,但实际的答案是事件。
#### 事件
......@@ -529,13 +529,13 @@ def run_evaluator_on_validation_data(engine):
evaluator.run(val_loader)
```
到目前为止,我必须已经使您相信 Ignite 是工具箱中的必备工具。 在前面的示例中,已为三个事件设置了`@trainer.on`装饰器; 实际上,在两个事件上,我们在`EPOCH_COMPLETED`事件上设置了两个函数。 使用第一个函数,我们可以将训练状态打印到终端上。 但是有些事情我们还没有看到。 状态是`Engine`用来保存有关执行信息的`state`变量。 在示例中,我们看到状态保存了有关期,迭代乃至输出的信息,这实际上是训练循环的损失。 `state`属性包含周期,迭代,当前数据,指标(如果有)(我们将很快了解指标); 调用`run`函数时设置的最大周期,以及`training_loop`函数的输出。
到目前为止,我必须已经使您相信 Ignite 是工具箱中的必备工具。 在前面的示例中,已为三个事件设置了`@trainer.on`装饰器; 实际上,在两个事件上,我们在`EPOCH_COMPLETED`事件上设置了两个函数。 使用第一个函数,我们可以将训练状态打印到终端上。 但是有些事情我们还没有看到。 状态是`Engine`用来保存有关执行信息的`state`变量。 在示例中,我们看到状态保存了有关期,迭代乃至输出的信息,这实际上是训练循环的损失。 `state`属性包含周期,迭代,当前数据,指标(如果有)(我们将很快了解指标); 调用`run`函数时设置的最大周期,以及`training_loop`函数的输出。
##### 注意
**注意**:在`create_supervised_trainer`的情况下,`training_loop`函数返回损失,在`create_supervised_evaluator`的情况下,`training_loop`函数返回模型的输出。 但是,如果我们定义一个自定义`training_loop`函数,则此函数返回的内容将是`Engine.state.output`保留的内容。
第二和第三事件处理器正在`EPOCH_COMPLETED`上运行`evaluator`,但具有不同的数据集。 在第一个函数中,`evaluator`使用训练数据集,在第二个函数中,它使用评估数据集。 太好了,因为现在我们可以在每个期完成时运行`evaluator`,而不是像第一个示例那样在整个执行结束时运行。 但是,除了运行它之外,处理器实际上并没有做任何事情。 通常,这里是我们检查平均准确率和平均损失的地方,并且我们会进行更复杂的分析,例如混淆度量的创建,我们将在后面看到。 但是,目前的主要收获是:可以为单个事件设置`n`处理器数量,Ignite 会毫不犹豫地依次调用所有这些处理器。 接下来是事件的内部`_fire_event`函数,该事件在`training_loop`函数的每个事件中触发。
第二和第三事件处理器正在`EPOCH_COMPLETED`上运行`evaluator`,但具有不同的数据集。 在第一个函数中,`evaluator`使用训练数据集,在第二个函数中,它使用评估数据集。 太好了,因为现在我们可以在每个期完成时运行`evaluator`,而不是像第一个示例那样在整个执行结束时运行。 但是,除了运行它之外,处理器实际上并没有做任何事情。 通常,这里是我们检查平均准确率和平均损失的地方,并且我们会进行更复杂的分析,例如混淆度量的创建,我们将在后面看到。 但是,目前的主要收获是:可以为单个事件设置`n`处理器数量,Ignite 会毫不犹豫地依次调用所有这些处理器。 接下来是事件的内部`_fire_event`函数,该事件在`training_loop`函数的每个事件中触发。
```py
def _fire_event(self, event_name, *event_args):
......@@ -606,7 +606,7 @@ def run_evaluator_on_validation_data(engine):
from ignite.handlers import EngineCheckpoint
```
Ignite 的检查点保护程序具有非常简单的 API。 用户需要定义检查点的保存位置,检查点的保存频率以及除默认参数(如迭代计数,用于恢复操作的期数)以外的对象要保存的内容。 在该示例中,我们为每一百次迭代检查点。 然后可以将定义的值作为参数传递给`EngineCheckpoint`模块,以获取检查点事件处理器对象。
Ignite 的检查点保护程序具有非常简单的 API。 用户需要定义检查点的保存位置,检查点的保存频率以及除默认参数(如迭代计数,用于恢复操作的期数)以外的对象要保存的内容。 在该示例中,我们为每一百次迭代检查点。 然后可以将定义的值作为参数传递给`EngineCheckpoint`模块,以获取检查点事件处理器对象。
返回的处理器具有常规事件处理器的所有功能,并且可以为 Ignite 触发的任何事件进行设置。 在以下示例中,我们将其设置为`ITERATION_COMPLETED`事件:
......
......@@ -519,7 +519,7 @@ g_optimizer = optim.Adam(generator.parameters(), lr=0.0002)
loss = nn.BCELoss()
```
接下来是简单 GAN 在不同期生成的输出,该图显示了网络如何学会将输入随机分布映射到输出真实分布。
接下来是简单 GAN 在不同期生成的输出,该图显示了网络如何学会将输入随机分布映射到输出真实分布。
![Simple GAN](img/B09475_06_16.jpg)
......
......@@ -623,7 +623,7 @@ valid_dl = DataLoader(valid_ds, batch_size=bs * 2)
```
我们将在每个期结束时计算并打印验证损失。
我们将在每个期结束时计算并打印验证损失。
(请注意,我们总是在训练之前调用`model.train()`,并在推理之前调用`model.eval()`,因为诸如`nn.BatchNorm2d``nn.Dropout`之类的层会使用它们,以确保这些不同阶段的行为正确。)
......@@ -675,7 +675,7 @@ def loss_batch(model, loss_func, xb, yb, opt=None):
```
`fit`运行必要的操作来训练我们的模型,并计算每个期的训练和验证损失。
`fit`运行必要的操作来训练我们的模型,并计算每个期的训练和验证损失。
```py
import numpy as np
......@@ -775,7 +775,7 @@ fit(epochs, model, loss_func, opt, train_dl, valid_dl)
`torch.nn`还有另一个方便的类,可以用来简化我们的代码:[`Sequential`](https://pytorch.org/docs/stable/nn.html#torch.nn.Sequential)`Sequential`对象以顺序方式运行其中包含的每个模块。 这是编写神经网络的一种简单方法。
为了利用这一点,我们需要能够从给定的函数轻松定义**自定义层**。 例如,PyTorch 没有视层,我们需要为我们的网络创建一个层。 `Lambda`将创建一个层,然后在使用`Sequential`定义网络时可以使用该层。
为了利用这一点,我们需要能够从给定的函数轻松定义**自定义层**。 例如,PyTorch 没有视层,我们需要为我们的网络创建一个层。 `Lambda`将创建一个层,然后在使用`Sequential`定义网络时可以使用该层。
```py
class Lambda(nn.Module):
......
......@@ -350,7 +350,7 @@ def main():
```
您应该获得第一个期的输出:
您应该获得第一个期的输出:
```py
Epoch: [0] [ 0/60] eta: 0:01:18 lr: 0.000090 loss: 2.5213 (2.5213) loss_classifier: 0.8025 (0.8025) loss_box_reg: 0.2634 (0.2634) loss_mask: 1.4265 (1.4265) loss_objectness: 0.0190 (0.0190) loss_rpn_box_reg: 0.0099 (0.0099) time: 1.3121 data: 0.3024 max mem: 3485
......@@ -400,9 +400,9 @@ IoU metric: segm
```
因此,经过一个期的训练,我们获得了 60.6 的 COCO 风格 mAP 和 70.4 的遮罩 mAP。
因此,经过一个期的训练,我们获得了 60.6 的 COCO 风格 mAP 和 70.4 的遮罩 mAP。
经过 10 个期的训练,我得到了以下指标
经过 10 个期的训练,我得到了以下指标
```py
IoU metric: bbox
......
......@@ -76,7 +76,7 @@ Random Seed: 999
* `nz`-潜向量的长度
* `ngf`-与通过生成器传送的特征图的深度有关
* `ndf`-设置通过判别器传播的特征图的深度
* `num_epochs`-要运行的训练期数。 训练更长的时间可能会导致更好的结果,但也会花费更长的时间
* `num_epochs`-要运行的训练期数。 训练更长的时间可能会导致更好的结果,但也会花费更长的时间
* `lr`-训练的学习率。 如 DCGAN 文件中所述,此数字应为 0.0002
* `beta1`-Adam 优化器的`beta1`超参数。 如论文所述,该数字应为 0.5
* `ngpu`-可用的 GPU 数量。 如果为 0,则代码将在 CPU 模式下运行。 如果此数字大于 0,它将在该数量的 GPU 上运行
......@@ -391,7 +391,7 @@ optimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))
如原始论文所述,我们希望通过最小化`log(1 - D(G(z)))`来训练生成器,以产生更好的假货。 如前所述,Goodfellow 证明这不能提供足够的梯度,尤其是在学习过程的早期。 作为解决方法,我们希望最大化`log D(G(z))`。 在代码中,我们通过以下步骤来实现此目的:将第 1 部分的生成器输出与判别器进行分类,使用实数标签`GT`计算`G`的损失,反向计算`G`的梯度,最后使用优化器步骤更新`G`的参数。 将真实标签用作损失函数的`GT`标签似乎是违反直觉的,但这使我们可以使用 BCELoss 的`log(x)`部分(而不是`log(1 - x)`部分),这正是我们想要的。
最后,我们将进行一些统计报告,并在每个期结束时,将我们的`fixed_noise`批量推送到生成器中,以直观地跟踪`G`的训练进度。 报告的训练统计数据是:
最后,我们将进行一些统计报告,并在每个期结束时,将我们的`fixed_noise`批量推送到生成器中,以直观地跟踪`G`的训练进度。 报告的训练统计数据是:
* `Loss_D`-判别器损失,计算为所有真实批量和所有假批量的损失总和(`log D(x) + log D(G(z))`)。
* `Loss_G`-生成器损失计算为`log D(G(z))`
......@@ -654,7 +654,7 @@ Starting Training Loop...
## 结果
最后,让我们看看我们是如何做到的。 在这里,我们将看三个不同的结果。 首先,我们将了解`D``G`的损失在训练过程中如何变化。 其次,我们将在每个期将`G`的输出显示为`fixed_noise`批量。 第三,我们将查看一批真实数据以及来自`G`的一批伪数据。
最后,让我们看看我们是如何做到的。 在这里,我们将看三个不同的结果。 首先,我们将了解`D``G`的损失在训练过程中如何变化。 其次,我们将在每个期将`G`的输出显示为`fixed_noise`批量。 第三,我们将查看一批真实数据以及来自`G`的一批伪数据。
**损失与训练迭代**
......
......@@ -270,7 +270,7 @@ scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.1) # red
## 训练和测试网络
现在,我们定义一个训练函数,它将训练数据输入模型中,并执行反向传播和优化步骤。 对于训练,我们将使用的损失是负对数可能性。 然后,在每个期之后将对网络进行测试,以查看训练期间准确率如何变化。
现在,我们定义一个训练函数,它将训练数据输入模型中,并执行反向传播和优化步骤。 对于训练,我们将使用的损失是负对数可能性。 然后,在每个期之后将对网络进行测试,以查看训练期间准确率如何变化。
```py
def train(model, epoch, log_interval):
......@@ -335,7 +335,7 @@ def test(model, epoch):
```
最后,我们可以训练和测试网络。 我们将训练网络十个时期,然后降低学习率,再训练十个时期。 在每个时期之后将对网络进行测试,以查看训练过程中准确率如何变化。
最后,我们可以训练和测试网络。 我们将训练网络十个周期,然后降低学习率,再训练十个周期。 在每个周期之后将对网络进行测试,以查看训练过程中准确率如何变化。
```py
log_interval = 20
......
......@@ -216,7 +216,7 @@ def evaluate(eval_model, data_source):
```
循环遍历。 如果验证损失是迄今为止迄今为止最好的,请保存模型。 在每个期之后调整学习率。
循环遍历。 如果验证损失是迄今为止迄今为止最好的,请保存模型。 在每个期之后调整学习率。
```py
best_val_loss = float("inf")
......
......@@ -676,7 +676,7 @@ torch::optim::Adam discriminator_optimizer(
在撰写本文时,C++ 前端提供了实现 Adagrad,Adam,LBBFG,RMSprop 和 SGD 的优化器。 [文档](https://pytorch.org/cppdocs/api/namespace_torch__optim.html)具有最新列表。
接下来,我们需要更新我们的训练循环。 我们将添加一个外循环以在每个期耗尽数据加载器,然后编写 GAN 训练代码:
接下来,我们需要更新我们的训练循环。 我们将添加一个外循环以在每个期耗尽数据加载器,然后编写 GAN 训练代码:
```py
for (int64_t epoch = 1; epoch <= kNumberOfEpochs; ++epoch) {
......
......@@ -750,7 +750,7 @@ Training: * Acc@1 63.000 Acc@5 81.333
```
在这里,我们只对少数几个期执行量化感知训练。 尽管如此,量化感知的训练在整个 imagenet 数据集上的准确率仍超过 71%,接近浮点精度 71.9%。
在这里,我们只对少数几个期执行量化感知训练。 尽管如此,量化感知的训练在整个 imagenet 数据集上的准确率仍超过 71%,接近浮点精度 71.9%。
有关量化感知的训练的更多信息:
......
......@@ -184,7 +184,7 @@ def _run_trainer(emb_rref, rank):
```
现在,我们准备介绍在每个训练器上运行的主要训练循环。 `get_next_batch`只是一个辅助函数,用于生成随机输入和训练目标。 我们针对多个期和每个批量运行训练循环:
现在,我们准备介绍在每个训练器上运行的主要训练循环。 `get_next_batch`只是一个辅助函数,用于生成随机输入和训练目标。 我们针对多个期和每个批量运行训练循环:
1. 为分布式 Autograd 设置[分布式 Autograd 上下文](https://pytorch.org/docs/master/rpc.html#torch.distributed.autograd.context)
2. 运行模型的正向传播并检索其输出。
......
......@@ -324,8 +324,8 @@ ReLU 的导数图,对于`x <= 0`,`f'(x) = 1`,对于`x > 0`,`f'(x) = 0`
先前`m`个样本数据集的伪代码为:
1. 初始化学习率`α`期数`e`的值
2. 循环遍历多个时期`e`'(每次完整的数据集将分批通过)
1. 初始化学习率`α`期数`e`的值
2. 循环遍历多个周期`e`(每次完整的数据集将分批通过)
3.`J`(成本函数)和`b`(偏差)初始化为 0,对于`W1``W2`,您可以使用随机正态或 **xavier 初始化**(在下一节中说明)
在此,`a``y_hat``dw1``∂J/∂w[1]``dw2``∂J/∂w[2]``db``∂J/∂b`。 每个迭代都包含一个循环遍历`m`个示例的循环。
......@@ -651,7 +651,7 @@ Inception 由 Google 团队于 2014 年创建。其主要思想是创建更广
* 减少使用 Sigmoid 和 tanh 激活函数
* 使用基于动量的随机梯度下降
* 权重和偏差的正确初始化,例如 xavier 初始化
* 正则化(将正则化丢失与数据丢失一起添加并最小化)
* 正则化(将正则化损失与数据损失一起添加并最小化)
有关更多详细信息,以及消失和梯度爆炸的数学表示,您可以阅读本文:[《智能信号:不稳定的深度学习,为什么以及如何解决它们》](https://medium.com/@sayondutta/intelligent-signals-unstable-deep-learning-why-and-how-to-solve-them-295dc12a7fb0)
......
......@@ -389,7 +389,7 @@ end for
| 上,上,下,下,下,下,上 | 输 | 坏 |
| 下,上,上,下,上,上 | 赢 | 好 |
因此,我们能够创建示例数据,在这些示例中,我们认为赢得的案例是该操作的正确标签。 因此,我们将增加这些动作的对数概率,即`log p(y[i], x[i])`,并且丢失每个动作的情况将被视为错误标签。 因此,在这些情况下,我们将减少这些操作的对数概率。
因此,我们能够创建示例数据,在这些示例中,我们认为赢得的案例是该操作的正确标签。 因此,我们将增加这些动作的对数概率,即`log p(y[i], x[i])`,并且每个动作失败的情况将被视为错误标签。 因此,在这些情况下,我们将减少这些操作的对数概率。
因此,在收集了一批轨迹之后,我们将最大化优势与对数概率的乘积,即`Σ[i] A[i] x log p(y[i], x[i])`
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册