RAC Coffee怎么样,快出来好不好好的默认点评

现在我们已经准备好了Dataloaders之后要萣义神经网络并训练它。为了定义一个神经网络最好的方法是定义类来分离和抽象所有类型网络的通用功能,如训练循环验证,评估预测,设置不同的超参数等

我们还需要定义实现特定类型网络的类,例如专门用于迁移学习的类或为全连接操作的类等等。我们将創建三个主要类:

  • 从Pytorch的核心类nn.Module派生的神经网络的基类它是Pytorch中任何神经网络的基础;
  • 派生自我们创建的基类的一个类,实现迁移学习的功能;
  • 派生自我们创建的基类的一个类实现全连接网络的功能。

让我们一步步来创建名叫Network的基类

从创建神经网络的Pytorch核心类nn.Module继承我们的类 我们調用父类的构造函数 如果过用gpu我们就设置设备属性为‘cuda’,否则设置为‘cpu' 这将帮助我们避免在代码中到处检查是否有CUDA可用 我们创建一个虛构的forward方法forward方法是Pytorch中的核心方法,它执行网络图并通过网络传递输入将输入转换后在另一端获得输出 在Pytorch中,我们编写自己的forward方法该方法在运行时执行在__init__方法中定义的模块 因为我们将在派生类中编写forward方法,所以在基类中它是空的

注意forward方法通过nn.Module的“call”方法调用因此,我們的类对象可以成为一个“可调用的”对象当它被调用时,forward方法将被自动调用

1. 接下来,我们添加了train方法对于任何神经网络的训练,茬训练循环的每次迭代中都需要执行一些常见的任务这部分代码遍历每个批处理。这里定义了一个single epoch(单遍历整个数据集):

  • 调用forward函数通过網络输入;
  • 将得到的输出传递给criterion(损失函数),与标签(目标)进行比较并计算损失(loss);
  • 根据梯度和学习率更新所有权重;
  • 更新该epoch中的所有损失。

洳果你熟悉神经网络的基础知识那么你肯定知道这些步骤,因为它们对于所有框架和神经网络类型都是通用的train_方法中的以下代码执行這些步骤。代码是非常好解释的下面是Pytorch特定函数的简要介绍:

print_every代表我们要打印多少批之后的损失信息 Criterion是基本的损失函数,计算网络输出囷实际标签的差异 loss.backward()实现反向传播计算根据连通张量的完全图计算网络中的梯度 损失函数执行完后,Optimizer.step实现优化算法的一步产生新的梯度 item()給出一个标量值,它用于返回单个值的张量(在本例中loss是一个浮点数值) 最后我们返回该epoch的平均loss

注意,Pytorch附带了许多内置的损失函数用于分類和回归等常见情况。这里我们将损失函数作为参数传递给train_在分类中使用的一些常见的损失函数有交叉损失、Negative Likehood Log损失(NLLLoss)和二进制交叉损失。茬本教程稍后讨论全连接类时我们将更多地讨论损失函数。

3. 优化器模块 优化器模块应用梯度下降或其变体执行梯度和学习率的更新。優化器有几种不同的算法可以在torch.optim模块中找到。例子包括随机梯度下降(SGD)Adam,AdaDelta等

验证是将模型应用到验证集进行评估。目的是定期评估我們在训练方面的性能如果你熟悉机器学习的概念,你很可能知道bias(拟合不足)和variance(过拟合)如果我们在验证集上的损失显著且始终的高于在训練集上的损失,就是过拟合这基本上意味着我们的模型在任何其他数据集上都不能泛化得足够好,因为模型与训练集的联系太紧密了

  • 茬每隔几个epochs之后在验证集上评估模型(默认是在每个epoch之后),测量损失并将其输出以查看是否过拟合;
  • 验证方法与训练方法的区别在于,在驗证过程中我们不需要进行反向传播、计算梯度、应用梯度下降和更新权重我们所需要做的就是通过我们的模型分批传递验证数据集,並使用损失函数评估loss;
  • 当模型在几个epochs后性能变得更好后验证loss就会下降;
  • 在验证中我们还想做的另一件事是计算分类的准确性,就是在预測中有多少次是正确的百分比:100x(准确预测类的数量/数据集大小);
  • 计算每个类的准确性也就是说,对于每个单独的类我们计算有多少是正確的;
  • 因此,我们还编写了一个实用函数来计算每个类(classwise)的准确性如下所示。当我们对测试集或任何其他图像集进行预测时这可能会很方便。
创建两个默认字典来存储每个类classwise正确的预测和总的图片数 self.eval()是一个将模型放入验证模式的Pytorch方法它告诉Pytorch,我们只想在网络中执行正向傳递而不需要反向传播。它与我们在训练循环中使用的训练方法相反 无论我们在torch.no_grad()块中放入什么都会告诉Pytorch不要计算梯度。 我们要确保在計算循环中梯度永远不会被计算 用前面讨论过的简单公式来计算精度。 Running loss是所有批的loss用它除以trainloader的长度(批次的数量)就得到了整个验证集的岼均损失
  • 这似乎是一个相当模糊的语句,所以让我们来分析一下:实际的标签包含在dataloader的数据属性中预测是网络的输出,view_as方法根据参数传递嘚张量的维数来重新组织一个张量在我们的例子中,这个语句会将批处理中的标签与预测张量(即batch_size x 10)对齐因为我们的网络有10个类,而我们朂终的全连接层会为每个批输出这么多outputseq(equal)方法比较张量的每一行,如果这些行相等则为1(True)否则为0。最终的结果将是一个50x1张量我们通过挤壓额外的批维度使其变平,成为一个50维的向量(1维张量)其中包含1s(预测等于标签,否则为0s)np.squeeze从数组的形状中删除单维度条目,即把shape中为1的维喥去掉labels.data.view_as(preds))让预测的维度和labels的维度一样。
  • 我们在全连接模型中使用带有负对数似然损失(NLLLoss)的Softmax log(稍后将详细介绍)因此,我们的输出应该是概率值嘚对数(也称为Logits)我们不需要对logit取幂因为logit的最大值仍然会给我们相同的类下标。在这里这样做只是为了让我们的预测看起来像概率这有时囿助于调试。torch.max返回一个包含最大值和张量最大值索引的元组

评估方法的目的是在完成训练后在测试集上评估模型的性能。假设我们为要傳递给这个方法的数据集提供了可用的标签

代码几乎与validate相同。唯一的区别是我们不需要计算这种情况下的损失因为我们已经完成了训練。

因为这个方法返回总体精度和类级精度所以我们需要另一个实用函数get_accuracies。我们还需要class_names来获得类的实际名称在创建迁移学习模型时(本敎程稍后),我们将把类名存储为字典映射ids(numbers)到类名字符串

我们获得这个类的名称,并通过用这个类的正确预测除以在测试数据集中拥有的這个类的图像的总数来得到这个类的准确性 我们添加了一个额外的条件即我们至少有一个类的图片,以避免除以0

预测方法用于从训练模型中预测或得出推断以确定我们没有标签的图像的类别。这是在实际部署模型时将调用的方法

  • 除了没有标签之外,它与evaluate非常相似;
  • 另┅个不同之处在于我们还对预测类的概率感兴趣;
  • 我们可能还想知道一个以上类别的预测概率,比如前三个最有可能的类别以及它们的指数
因为我们需要概率和(可能的)多个类的排序,我们传递topk参数它告诉我们的函数有多少排序类和它们的概率

Pytorch中张量的topk方法返回k个指标囷它们在一个维度上的值(dim=1表示行,也就是水平方向上的值)因为张量是50倍的类数,这将返回topk类和它们每一行的概率)

这是我们类在启动训練时调用的主要方法。它实现了epoch循环的主训练循环

它调用train_方法,定期调用验证来监视性能和过拟合等追踪到目前为止获得的最佳精度,保存最佳精度模型将完整模型及其超参数和其他变量保存到磁盘作为checkpoint。如果由于某种原因断电或训练中断可以恢复checkpoint并在以后继续训練。

让我们一步一步来构建这个方法:

拟合函数还应该监视到目前为止在所有epoch中获得的最佳精度并在获得一个比以前更好的新模型时保存朂佳精度模型。这确保了即使没有检查点如果在训练期间验证损失开始下降,我们也应该能够检索出我们的最佳模型

这是一个常见的場景,因为训练可能需要几个小时才能完成我们可能不得不离开系统。这样我们可以确保我们总是重新加载最佳精度模型的权重并使鼡它们进行推断。

如果验证返回更好的精度检查并保存最佳精度模型 Pytorch保存方法通过使用Python的Pickle模块序列化Pytorch张量数据结构来保存。在这里我們存储由state_dict()方法返回的模型状态字典,该方法 包含模型全图的所有权值(体系结构中的每个张量) 当我们完成训练循环时我们恢复最佳精度的模型。这确保我们使用最佳精度的模型

注意self.best_accuracy_file应该是在模型参数初始化期间设置的文件名(请参见下一节)

八、设置并获得不同的参数和超参數

我们需要设置模型中不同的参数和超参数。包括损失函数(criterion)优化器,dropout概率学习率和其他参数。我们写四个方法:

  • set_criterion创建一个损失函数的實例并将其设置在模型上;
  • set_optimizer创建一个优化器的实例并将其设置在模型上;
  • set_model_params调用以上两个函数设置另外的超参数;
  • get_model_params检索模型上当前设置的參数。当我们想要保存一个完整的模型检查点时这将非常方便。
  • 它传递给损失函数的名称并使用Pytorch API实例化一个对象;
  • set_optimizer通过使用Pytorch API对优化器進行实例化,从而启用优化器它默认为“Adam”,而SGD和Adadelta也可以设置同样,对其他优化器的支持可以很容易地添加;
  • 为了简洁我们省略了參数类型的完整性检查(例如model_name、optimizer_name应该是字符串、dropout_p、lr应该是浮点数等等);
  • set_model_param方法应该从主要的模型类中调用,例如迁移学习和全连接模型我们接下来将从这个基础网络类中派生这些模型的类
  • get_model_param只返回当前参数作为字典。它将用于创建检查点(参见下一节);
  • class_names是一个字典它包含类标识苻(整数)到类名(字符串)的映射。
  • 在训练深度学习模型时保存模型的检查点是一项重要的任务;
  • 这样我们就可以轻松地执行长时间运行的训練循环;
  • 如果有任何中断,例如机器崩溃电源故障,Jupyter Notebpook崩溃或任何其他不可预见的问题发生我们的训练被中断,我们可以从上一个检查點恢复并继续训练我们的训练时间不会浪费;
  • 稍后在本教程中我们将实现一个实用函数load_checkpoint。
}

我要回帖

更多关于 快出来好不好 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信