PyTorch深度学习实战
上QQ阅读APP看书,第一时间看更新

1.4 PyTorch如何支持深度学习概述

我们已经提及了PyTorch的一些构成要素,接下来我们将正式介绍PyTorch的主要组件的高级映射。我们可以通过查看一个PyTorch深度学习项目所需要的组件来更好地了解这些内容。

首先,正如Python一样,PyTorch有一个扩展名为“.py”的文件,但在该文件中有很多非Python代码。事实上,由于性能原因,PyTorch大部分是用C++和CUDA编写的,CUDA是一种来自英伟达的类C++的语言,可以被编译并在GPU上以并行方式运行。有一些方法可以直接在C++环境中运行PyTorch,我们将在第15章中讨论这些方法。此功能的动机之一是为生产环境中部署模型提供可靠的策略。但是,大多数情况下我们都是使用Python来与PyTorch交互的,包括构建模型、训练模型以及使用训练过的模型解决实际问题等。

实际上,Python API正是PyTorch在可用性以及与更广泛Python生态系统集成方面的亮点。让我们来看看PyTorch的心智模型。

正如我们前面已经提到的那样,PyTorch的核心是一个提供多维数组(张量)以及由torch模块提供大量操作的库。张量及操作可以在CPU或GPU上使用。在PyTorch中,将运算从CPU转移到GPU不需要额外的函数调用。PyTorch提供的第2个核心功能是张量可以跟踪对其执行的操作的能力,并分析和计算任何输入对应的输出的导数。该功能用于数值优化,是由张量自身提供的,通过PyTorch底层自动求导引擎来调度。

通过使用张量以及张量自动求导的标准库,PyTorch可以用于物理学、渲染、优化、仿真、建模等,而且我们很可能会看到PyTorch在科学应用的各个领域以创造性的方式使用。但PyTorch首先是一个深度学习库,因此它提供了构建和训练神经网络所需的所有构建模块。图1.2展示了完成一个深度学习项目的标准步骤,从加载数据到训练模型,最后将该模型部署到生产中。

用于构建神经网络的PyTorch核心模块位于torch.nn中,它提供了通用的神经网络层和其他架构组件。全连接层、卷积层、激活函数和损失函数都可以在这里找到(在本书剩余部分,我们将详细地介绍这些内容)。这些组件可用于构建和初始化图1.2所示的未训练的模型。为了训练模型,我们需要一些额外的东西:模型训练的数据源、一个使模型适应训练数据的优化器,以及一种把模型和数据传输到硬件的方法,该硬件用于执行模型训练所需的计算。

图1.2 PyTorch项目的基础、高级结构,包括数据加载、训练和生产部署等

在图1.2的左侧,我们看到训练数据在到达模型之前,需要进行大量的数据处理[4]。首先,我们需要从外部获取数据,通常是从作为数据源的某种存储中获取数据。然后我们需要将数据中的每个样本转换成PyTorch可以处理的张量。数据预处理是我们自定义数据(无论什么样的格式)与PyTorch中torch.utils.data包下的Dataset类提供的标准张量之间的桥梁。由于不同问题处理过程截然不同,因此我们需要自己定义数据源。在第4章中,我们将详细介绍如何将各种类型的数据表示为张量。

由于数据存储通常很慢,还存在访问延迟,因此我们希望并行化数据加载。但是,由于Python提供的许多操作都不具有简单、高效的并行处理能力,因此我们需要多个进程来加载我们的数据,以便将它们组装成一个批次,即组装成一个包含多个样本的张量。这是相当复杂的,但由于它也是相对通用的,PyTorch很容易在DataLoader类中实现这些功能。它的实例可以生成子进程在后台从数据集中加载数据,提前将数据准备就绪,一旦训练循环开始就可以立即使用。我们将在第7章介绍和使用Dataset和DataLoader。

有了获取成批样本的机制,我们可以转向图1.2中心的训练循环。通常训练循环被实现为标准的Python for循环。在最简单的情况下,模型在本地CPU或单个GPU上执行所需的计算,一旦训练循环获得数据,计算就可以立即开始。很可能这就是你的基本设置,也是我们在本书中假设的设置。

在训练循环的每个步骤中,我们根据从数据加载器获得的样本来评估模型。然后我们使用某种准则或损失函数将模型的输出与期望的输出(目标)进行比较。PyTorch除了提供构建模型的组件,也有各种损失函数供我们使用,torch.nn包中也提供这些函数。在我们用损失函数将实际输出与期望的输出进行比较之后,我们需要稍微修改模型以使其输出更接近目标。正如前面提到的,这正是PyTorch底层的自动求导引擎的用武之地。但是我们还需要一个优化器来进行更新,这是PyTorch在torch.optiom中为我们提供的。在第5章中,我们将开始研究带有损失函数和优化器的训练循环,然后在第2部分开始我们的大项目之前,即在第6章到第8章中先训练一下我们使用PyTorch的技能。

使用更精细的硬件越来越普遍,如多GPU或多个服务器,将这些资源用于训练大型模型,如图1.2的底部中间部分所示。在这些情况下,torch.nn.parallel.DistributedDataParallel和torch. distributed子模块可用于使用附加的硬件。

训练循环可能是深度学习项目中最乏味和耗时的部分。训练循环结束后,我们将得到一个模型,该模型的参数已经在我们的任务上得到了优化,如图1.2训练循环右侧部分所示的训练过的模型。有一个用来解决任务的模型是很好的,但是为了使它有用,我们需要将其放在需要工作的地方。如图1.2所示,在其右侧所示的部署部分可能涉及将模型放在生产服务器上,或将模型导出到云中,或者我们可将它与更大的应用程序集成,抑或在手机上运行它。

部署操作中一个特定的步骤是导出模型。如前所述,PyTorch默认为立即执行模式(急切模式)。每当Python解释器执行一个包含“PyTorch”的指令,相应的操作就会立即被底层的C++或CUDA的实现来执行。随着对张量进行操作的指令越来越多,后端实现将执行更多的操作。

PyTorch还提供了一种通过TorchScript提前编译模型的方法。使用TorchScript,PyTorch可以将模型序列化为一组独立于Python调用,如在C++程序或在移动设备上调用的指令集。我们可以把模型想象成一个具有有限指令集的虚拟机,用于特定的张量操作。这允许我们导出我们的模型,或者将其作为用于PyTorch运行时的TorchScript导出,或者将其以一种称为ONNX的标准格式导出。这些特性是PyTorch生产部署的基础,我们将在第15章中进行介绍。