PyTorch 深度学习(GPT 重译)(一)(1)

简介: PyTorch 深度学习(GPT 重译)(一)

第一部分:PyTorch 核心

欢迎来到本书的第一部分。在这里,我们将与 PyTorch 迈出第一步,获得理解其结构和解决 PyTorch 项目机制所需的基本技能。

在第一章中,我们将首次接触 PyTorch,了解它是什么,解决了什么问题,以及它与其他深度学习框架的关系。第二章将带领我们进行一次旅行,让我们有机会玩玩已经在有趣任务上预训练的模型。第三章会更加严肃,教授 PyTorch 程序中使用的基本数据结构:张量。第四章将带领我们再次进行一次旅行,这次是跨越不同领域的数据如何表示为 PyTorch 张量。第五章揭示了程序如何从示例中学习以及 PyTorch 如何支持这一过程。第六章介绍了神经网络的基础知识以及如何使用 PyTorch 构建神经网络。第七章通过一个神经网络架构解决了一个简单的图像分类问题。最后,第八章展示了如何使用卷积神经网络以更智能的方式解决同样的问题。

到第 1 部分结束时,我们将具备在第 2 部分中使用 PyTorch 解决真实世界问题所需的基本技能。

一、介绍深度学习和 PyTorch 库

本章涵盖

  • 深度学习如何改变我们对机器学习的方法
  • 了解为什么 PyTorch 非常适合深度学习
  • 检查典型的深度学习项目
  • 您需要的硬件来跟随示例

术语人工智能的定义模糊,涵盖了一系列经历了大量研究、审查、混乱、夸张和科幻恐慌的学科。现实当然要乐观得多。断言今天的机器在任何人类意义上都在“思考”是不诚实的。相反,我们发现了一类能够非常有效地逼近复杂非线性过程的算法,我们可以利用这些算法来自动化以前仅限于人类的任务。

例如,在inferkit.com/,一个名为 GPT-2 的语言模型可以逐字生成连贯的段落文本。当我们将这段文字输入时,它生成了以下内容:

接下来,我们将输入一组来自电子邮件地址语料库的短语列表,并查看程序是否能将列表解析为句子。再次强调,这比本文开头的搜索要复杂得多,也更加复杂,但希望能帮助您了解在各种编程语言中构建句子结构的基础知识。

对于一台机器来说,这是非常连贯的,即使在这些胡言乱语背后没有一个明确定义的论点。

更令人印象深刻的是,执行这些以前仅限于人类的任务的能力是通过示例获得的,而不是由人类编码为一组手工制作的规则。在某种程度上,我们正在学习智能是一个我们经常与自我意识混淆的概念,而自我意识绝对不是成功执行这类任务所必需的。最终,计算机智能的问题甚至可能并不重要。Edsger W. Dijkstra 发现,机器是否能够思考的问题“与潜艇是否能游泳的问题一样相关”。¹

我们谈论的那类算法属于深度学习的人工智能子类,它通过提供示例来训练名为深度神经网络的数学实体。深度学习使用大量数据来逼近输入和输出相距甚远的复杂函数,比如输入图像和输出的一行描述输入的文本;或者以书面脚本为输入,以自然语音朗读脚本为输出;甚至更简单的是将金毛寻回犬的图像与告诉我们“是的,金毛寻回犬在场”的标志相关联。这种能力使我们能够创建具有直到最近为止仅属于人类领域的功能的程序。

1.1 深度学习革命

要欣赏这种深度学习方法带来的范式转变,让我们退后一步,换个角度看一下。直到最近的十年,广义上属于机器学习范畴的系统在很大程度上依赖特征工程。特征是对输入数据的转换,有助于下游算法(如分类器)在新数据上产生正确的结果。特征工程包括想出正确的转换,以便下游算法能够解决任务。例如,为了在手写数字图像中区分 1 和 0,我们会想出一组滤波器来估计图像上边缘的方向,然后训练一个分类器来预测给定边缘方向分布的正确数字。另一个有用的特征可能是封闭孔的数量,如 0、8 和尤其是环绕的 2。

另一方面,深度学习处理的是自动从原始数据中找到这样的表示,以便成功执行任务。在二进制示例中,通过在训练过程中迭代地查看示例和目标标签对来逐步改进滤波器。这并不是说特征工程在深度学习中没有地位;我们经常需要在学习系统中注入某种形式的先验知识。然而,神经网络摄取数据并根据示例提取有用表示的能力是使深度学习如此强大的原因。深度学习从业者的重点不是手工制作这些表示,而是操作数学实体,使其自主地从训练数据中发现表示。通常,这些自动生成的特征比手工制作的特征更好!与许多颠覆性技术一样,这一事实导致了观念的变化。

在图 1.1 的左侧,我们看到一个从业者忙于定义工程特征并将其馈送给学习算法;在任务上的结果将取决于从业者工程的特征的好坏。在右侧,通过深度学习,原始数据被馈送给一个自动提取分层特征的算法,该算法受其在任务上性能优化的指导;结果将取决于从业者驱动算法朝着目标的能力。

图 1.1 深度学习交换了手工制作特征的需求,增加了数据和计算需求。

从图 1.1 的右侧开始,我们已经可以看到我们需要执行成功的深度学习所需的一瞥:

  • 我们需要一种方法来摄取手头的任何数据。
  • 我们以某种方式需要定义深度学习机器。
  • 我们必须有一种自动化的方式,训练,来获得有用的表示并使机器产生期望的输出。

这使我们不得不更仔细地看看我们一直在谈论的这个训练问题。在训练过程中,我们使用一个标准,这是模型输出和参考数据的实值函数,为我们的模型期望输出与实际输出之间的差异提供一个数值分数(按照惯例,较低的分数通常更好)。训练包括通过逐步修改我们的深度学习机器来将标准驱向更低的分数,直到它在训练过程中未见的数据上也能获得低分数。

1.2 PyTorch 用于深度学习

PyTorch 是一个用于 Python 程序的库,有助于构建深度学习项目。它强调灵活性,并允许用惯用 Python 表达深度学习模型。这种易接近性和易用性在研究界早期的采用者中得到了认可,在其首次发布后的几年里,它已经发展成为广泛应用于各种应用领域的最重要的深度学习工具之一。

就像 Python 用于编程一样,PyTorch 为深度学习提供了一个出色的入门。同时,PyTorch 已被证明完全适用于在实际工作中的专业环境中使用。我们相信 PyTorch 清晰的语法、简化的 API 和易于调试使其成为深入深度学习的绝佳选择。我们强烈推荐学习 PyTorch 作为你的第一个深度学习库。至于它是否应该是你学习的最后一个深度学习库,这是一个由你决定的问题。

在图 1.1 中的深度学习机器的核心是一个将输入映射到输出的相当复杂的数学函数。为了方便表达这个函数,PyTorch 提供了一个核心数据结构,张量,它是一个与 NumPy 数组有许多相似之处的多维数组。在这个基础上,PyTorch 提供了在专用硬件上执行加速数学运算的功能,这使得设计神经网络架构并在单台机器或并行计算资源上训练它们变得方便。

本书旨在成为软件工程师、数据科学家和精通 Python 的有动力的学生开始使用 PyTorch 构建深度学习项目的起点。我们希望这本书尽可能易于访问和有用,并且我们期望您能够将本书中的概念应用到其他领域。为此,我们采用了实践方法,并鼓励您随时准备好计算机,这样您就可以尝试示例并进一步深入研究。到本书结束时,我们期望您能够利用数据源构建出一个深度学习项目,并得到优秀的官方文档支持。

尽管我们强调使用 PyTorch 构建深度学习系统的实际方面,但我们认为提供一个易于理解的基础深度学习工具的介绍不仅仅是为了促进新技术技能的习得。这是向来自各种学科领域的新一代科学家、工程师和从业者提供工作知识的一步,这些知识将成为未来几十年许多软件项目的支柱。

为了充分利用本书,您需要两样东西:

一些在 Python 中编程经验。我们不会在这一点上有任何保留;您需要了解 Python 数据类型、类、浮点数等。

有愿意深入并动手实践的态度。我们将从基础开始建立工作知识,如果您跟着我们一起学习,学习将会更容易。

使用 PyTorch 进行深度学习 分为三个不同的部分。第一部分涵盖了基础知识,详细介绍了 PyTorch 提供的设施,以便用代码将图 1.1 中深度学习的草图付诸实践。第二部分将带您完成一个涉及医学成像的端到端项目:在 CT 扫描中查找和分类肿瘤,建立在第一部分介绍的基本概念基础上,并添加更多高级主题。简短的第三部分以 PyTorch 为主题,介绍了将深度学习模型部署到生产环境中的内容。

深度学习是一个庞大的领域。在本书中,我们将涵盖其中的一小部分:具体来说,使用 PyTorch 进行较小范围的分类和分割项目,其中大部分激励示例使用 2D 和 3D 数据集的图像处理。本书侧重于实用的 PyTorch,旨在涵盖足够的内容,使您能够解决真实世界的机器学习问题,例如在视觉领域使用深度学习,或者随着研究文献中出现新模型而探索新模型。大多数,如果不是全部,与深度学习研究相关的最新出版物都可以在 arXiV 公共预印本存储库中找到,托管在arxiv.org

1.3 为什么选择 PyTorch?

正如我们所说,深度学习使我们能够通过向我们的模型展示说明性示例来执行非常广泛的复杂任务,如机器翻译、玩策略游戏或在混乱场景中识别物体。为了在实践中做到这一点,我们需要灵活的工具,以便能够适应如此广泛的问题,并且高效,以便允许在合理时间内对大量数据进行训练;我们需要训练好的模型在输入变化时能够正确执行。让我们看看我们决定使用 PyTorch 的一些原因。

PyTorch 之所以易于推荐,是因为它的简单性。许多研究人员和实践者发现它易于学习、使用、扩展和调试。它符合 Python 的风格,虽然像任何复杂的领域一样,它有注意事项和最佳实践,但使用该库通常对之前使用过 Python 的开发人员来说感觉很熟悉。

更具体地说,在 PyTorch 中编程深度学习机器非常自然。PyTorch 给我们提供了一种数据类型,即Tensor,用于保存数字、向量、矩阵或一般数组。此外,它提供了用于操作它们的函数。我们可以像在 Python 中一样逐步编程,并且如果需要,可以交互式地进行,就像我们从 Python 中习惯的那样。如果你了解 NumPy,这将非常熟悉。

但是 PyTorch 提供了两个使其特别适用于深度学习的特点:首先,它利用图形处理单元(GPU)进行加速计算,通常比在 CPU 上进行相同计算速度提高了 50 倍。其次,PyTorch 提供了支持数值优化的功能,用于训练深度学习所使用的通用数学表达式。请注意,这两个特点不仅适用于深度学习,而且适用于科学计算。事实上,我们可以将 PyTorch 安全地描述为一个在 Python 中为科学计算提供优化支持的高性能库。

PyTorch 的设计驱动因素是表达能力,允许开发人员实现复杂模型而不受库施加的复杂性(它不是一个框架!)。可以说 PyTorch 在深度学习领域中最顺畅地将思想转化为 Python 代码之一。因此,PyTorch 在研究中得到了广泛的采用,这可以从国际会议上的高引用计数看出。

PyTorch 在从研究和开发转向生产方面也有引人注目的故事。虽然最初它专注于研究工作流程,但 PyTorch 已经配备了一个高性能的 C++ 运行时,可以用于在不依赖 Python 的情况下部署推断模型,并且可以用于在 C++ 中设计和训练模型。它还增加了对其他语言的绑定和用于部署到移动设备的接口。这些功能使我们能够利用 PyTorch 的灵活性,同时将我们的应用程序带到完全无法获得或会带来昂贵开销的完整 Python 运行时的地方。

当然,声称易用性和高性能是微不足道的。我们希望当你深入阅读本书时,你会同意我们在这里的声明是有充分根据的。

1.3.1 深度学习竞争格局

尽管所有类比都有缺陷,但似乎 PyTorch 0.1 在 2017 年 1 月的发布标志着从深度学习库、包装器和数据交换格式的富集到整合和统一的时代的转变。

注意 深度学习领域最近发展迅速,到您阅读这篇文章时,它可能已经过时。如果您对这里提到的一些库不熟悉,那没关系。

在 PyTorch 首个 beta 版本发布时:

  • Theano 和 TensorFlow 是首屈一指的低级库,使用用户定义计算图然后执行它。
  • Lasagne 和 Keras 是围绕 Theano 的高级封装,Keras 也封装了 TensorFlow 和 CNTK。
  • Caffe、Chainer、DyNet、Torch(PyTorch 的 Lua 前身)、MXNet、CNTK、DL4J 等填补了生态系统中的各种领域。

在接下来的大约两年时间里,情况发生了巨大变化。社区在 PyTorch 或 TensorFlow 之间大多数集中,其他库的采用量减少,除了填补特定领域的库。简而言之:

  • Theano,第一个深度学习框架之一,已经停止了活跃开发。
  • TensorFlow:
  • 完全消化了 Keras,将其提升为一流的 API
  • 提供了一个立即执行的“急切模式”,与 PyTorch 处理计算方式有些相似
  • 发布了默认启用急切模式的 TF 2.0
  • JAX 是 Google 开发的一个独立于 TensorFlow 的库,已经开始获得与 GPU、自动微分和 JIT 功能相当的 NumPy 等价物。
  • PyTorch:
  • 消化了 Caffe2 作为其后端
  • 替换了大部分从基于 Lua 的 Torch 项目中重复使用的低级代码
  • 添加了对 ONNX 的支持,这是一个供应商中立的模型描述和交换格式
  • 添加了一个延迟执行的“图模式”运行时称为TorchScript
  • 发布了 1.0 版本
  • 分别由各自公司的赞助商替换了 CNTK 和 Chainer 作为首选框架

TensorFlow 拥有强大的生产流水线、广泛的行业社区和巨大的知名度。PyTorch 在研究和教学社区中取得了巨大进展,得益于其易用性,并自那时起一直在增长,因为研究人员和毕业生培训学生并转向工业。它在生产解决方案方面也积累了动力。有趣的是,随着 TorchScript 和急切模式的出现,PyTorch 和 TensorFlow 的功能集开始收敛,尽管这些功能的展示和整体体验在两者之间仍然有很大的不同。

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

我们已经暗示了 PyTorch 中的一些构建模块。现在让我们花点时间来形式化一个构成 PyTorch 的主要组件的高级地图。我们最好通过查看深度学习项目从 PyTorch 中需要什么来做到这一点。

首先,PyTorch 中有“Py”代表 Python,但其中有很多非 Python 代码。实际上,出于性能原因,大部分 PyTorch 是用 C++和 CUDA(www.geforce.com/hardware/technology/cuda)编写的,CUDA 是 NVIDIA 的一种类似 C++的语言,可以编译成在 GPU 上进行大规模并行运行。有方法可以直接从 C++运行 PyTorch,我们将在第十五章中探讨这些方法。这种能力的一个动机是提供一个可靠的部署模型的策略。然而,大部分时间我们会从 Python 中与 PyTorch 交互,构建模型,训练它们,并使用训练好的模型解决实际问题。

实际上,Python API 是 PyTorch 在可用性和与更广泛的 Python 生态系统集成方面的亮点。让我们来看看 PyTorch 是什么样的思维模型。

正如我们已经提到的,PyTorch 的核心是一个提供多维数组或在 PyTorch 术语中称为张量的库(我们将在第三章详细介绍),以及由torch模块提供的广泛的操作库。张量和对它们的操作都可以在 CPU 或 GPU 上使用。在 PyTorch 中将计算从 CPU 移动到 GPU 不需要更多的函数调用。PyTorch 提供的第二个核心功能是张量能够跟踪对它们执行的操作,并分析地计算与计算输出相对于任何输入的导数。这用于数值优化,并且通过 PyTorch 的autograd引擎在底层提供。

通过具有张量和 autograd 启用的张量标准库,PyTorch 可以用于物理、渲染、优化、模拟、建模等领域–我们很可能会在整个科学应用的范围内看到 PyTorch 以创造性的方式使用。但 PyTorch 首先是一个深度学习库,因此它提供了构建神经网络和训练它们所需的所有构建模块。图 1.2 显示了一个标准设置,加载数据,训练模型,然后将该模型部署到生产环境。

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

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

在图 1.2 的左侧,我们看到在训练数据到达我们的模型之前需要进行相当多的数据处理。首先,我们需要从某种存储中获取数据,最常见的是数据源。然后,我们需要将我们的数据中的每个样本转换为 PyTorch 实际可以处理的东西:张量。我们自定义数据(无论其格式是什么)与标准化的 PyTorch 张量之间的桥梁是 PyTorch 在torch.utils.data中提供的Dataset类。由于这个过程在不同问题之间差异很大,我们将不得不自己实现这个数据获取过程。我们将详细讨论如何将我们想要处理的各种类型的数据表示为张量在第四章。

由于数据存储通常较慢,特别是由于访问延迟,我们希望并行化数据加载。但由于 Python 受欢迎的许多功能并不包括简单、高效的并行处理,我们需要多个进程来加载数据,以便将它们组装成批次:包含多个样本的张量。这相当复杂;但由于它也相对通用,PyTorch 在DataLoader类中轻松提供了所有这些魔法。它的实例可以生成子进程,后台加载数据集中的数据,以便在训练循环可以使用时,数据已准备就绪。我们将在第七章中遇到并使用DatasetDataLoader

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

在训练循环的每一步中,我们使用从数据加载器中获取的样本评估我们的模型。然后,我们使用一些标准损失函数将我们模型的输出与期望输出(目标)进行比较。正如它提供了构建模型的组件一样,PyTorch 还提供了各种损失函数供我们使用。它们也是在torch.nn中提供的。在我们用损失函数比较了实际输出和理想输出之后,我们需要稍微推动模型,使其输出更好地类似于目标。正如前面提到的,这就是 PyTorch 自动求导引擎的作用所在;但我们还需要一个优化器来进行更新,这就是 PyTorch 在torch.optim中为我们提供的。我们将在第五章开始研究带有损失函数和优化器的训练循环,然后在第 6 至 8 章中磨练我们的技能,然后开始我们的大型项目。

越来越普遍的是使用更复杂的硬件,如多个 GPU 或多台机器共同为训练大型模型提供资源,如图 1.2 底部中心所示。在这些情况下,可以使用torch.nn.parallel.Distributed-DataParalleltorch.distributed子模块来利用额外的硬件。

训练循环可能是深度学习项目中最不令人兴奋但最耗时的部分。在此之后,我们将获得一个在我们的任务上经过优化的模型参数:图中训练循环右侧所示的训练模型。拥有一个能解决问题的模型很棒,但为了让它有用,我们必须将其放在需要工作的地方。这个过程的部署部分在图 1.2 右侧描述,可能涉及将模型放在服务器上或将其导出以加载到云引擎中,如图所示。或者我们可以将其集成到更大的应用程序中,或在手机上运行。

部署练习的一个特定步骤可以是导出模型。如前所述,PyTorch 默认为即时执行模式(急切模式)。每当涉及 PyTorch 的指令被 Python 解释器执行时,相应的操作立即由底层 C++或 CUDA 实现执行。随着更多指令操作张量,更多操作由后端实现执行。

PyTorch 还提供了一种通过TorchScript提前编译模型的方法。使用 TorchScript,PyTorch 可以将模型序列化为一组指令,可以独立于 Python 调用:比如,从 C++程序或移动设备上。我们可以将其视为具有有限指令集的虚拟机,特定于张量操作。这使我们能够导出我们的模型,无论是作为可与 PyTorch 运行时一起使用的 TorchScript,还是作为一种称为ONNX的标准化格式。这些功能是 PyTorch 生产部署能力的基础。我们将在第十五章中介绍这一点。

1.5 硬件和软件要求

本书将需要编写和运行涉及大量数值计算的任务,例如大量矩阵相乘。事实证明,在新数据上运行预训练网络在任何最近的笔记本电脑或个人电脑上都是可以的。甚至拿一个预训练网络并重新训练其中的一小部分以使其在新数据集上专门化并不一定需要专门的硬件。您可以使用标准个人电脑或笔记本电脑跟随本书第 1 部分的所有操作。

然而,我们预计完成第 2 部分中更高级示例的完整训练运行将需要一个支持 CUDA 的 GPU。第 2 部分中使用的默认参数假定具有 8 GB RAM 的 GPU(我们建议使用 NVIDIA GTX 1070 或更高版本),但如果您的硬件可用 RAM 较少,则可以进行调整。明确一点:如果您愿意等待,这样的硬件并非强制要求,但在 GPU 上运行可以将训练时间缩短至少一个数量级(通常快 40-50 倍)。单独看,计算参数更新所需的操作速度很快(从几分之一秒到几秒)在现代硬件上,如典型笔记本电脑 CPU。问题在于训练涉及一遍又一遍地运行这些操作,逐渐更新网络参数以最小化训练误差。

中等规模的网络在配备良好 GPU 的工作站上从头开始训练大型真实世界数据集可能需要几小时到几天的时间。通过在同一台机器上使用多个 GPU,甚至在配备多个 GPU 的机器集群上进一步减少时间。由于云计算提供商的提供,这些设置比听起来的要容易访问。DAWNBench(dawn.cs.stanford.edu/benchmark/index.html)是斯坦福大学的一个有趣的倡议,旨在提供关于在公开可用数据集上进行常见深度学习任务的训练时间和云计算成本的基准。

因此,如果在您到达第 2 部分时有 GPU 可用,那太好了。否则,我们建议查看各种云平台的提供,其中许多提供预装 PyTorch 的支持 GPU 的 Jupyter 笔记本,通常还有免费配额。Google Colaboratory(colab.research.google.com)是一个很好的起点。

最后考虑的是操作系统(OS)。PyTorch 从首次发布开始就支持 Linux 和 macOS,并于 2018 年获得了 Windows 支持。由于当前的苹果笔记本不包含支持 CUDA 的 GPU,PyTorch 的预编译 macOS 包仅支持 CPU。在本书中,我们会尽量避免假设您正在运行特定的操作系统,尽管第 2 部分中的一些脚本显示为在 Linux 下的 Bash 提示符下运行。这些脚本的命令行应该很容易转换为兼容 Windows 的形式。为了方便起见,尽可能地,代码将被列为从 Jupyter Notebook 运行时的形式。

有关安装信息,请参阅官方 PyTorch 网站上的入门指南(pytorch.org/get-started/locally)。我们建议 Windows 用户使用 Anaconda 或 Miniconda 进行安装(www.anaconda.com/distributiondocs.conda.io/en/latest/miniconda.html)。像 Linux 这样的其他操作系统通常有更多可行的选项,Pip 是 Python 最常见的包管理器。我们提供一个 requirements.txt 文件,pip 可以使用它来安装依赖项。当然,有经验的用户可以自由选择最符合您首选开发环境的方式来安装软件包。

第 2 部分还有一些不容忽视的下载带宽和磁盘空间要求。第 2 部分癌症检测项目所需的原始数据约为 60 GB,解压后需要约 120 GB 的空间。解压缩后的数据可以在解压缩后删除。此外,由于为了性能原因缓存了一些数据,训练时还需要另外 80 GB。您需要在用于训练的系统上至少有 200 GB 的空闲磁盘空间。虽然可以使用网络存储进行此操作,但如果网络访问速度慢于本地磁盘,则可能会导致训练速度下降。最好在本地 SSD 上有空间存储数据以便快速检索。

1.5.1 使用 Jupyter 笔记本

我们假设您已经安装了 PyTorch 和其他依赖项,并已验证一切正常。之前我们提到了在书中跟随代码的可能性。我们将大量使用 Jupyter 笔记本来展示我们的示例代码。Jupyter 笔记本显示为浏览器中的页面,通过它我们可以交互式地运行代码。代码由一个内核评估,这是在服务器上运行的进程,准备接收要执行的代码并发送结果,然后在页面上内联呈现。笔记本保持内核的状态,例如在评估代码期间定义的变量,直到终止或重新启动。我们与笔记本交互的基本单元是单元格:页面上的一个框,我们可以在其中输入代码并让内核评估它(通过菜单项或按 Shift-Enter)。我们可以在笔记本中添加多个单元格,新单元格将看到我们在早期单元格中创建的变量。单元格的最后一行返回的值将在执行后直接在单元格下方打印出来,绘图也是如此。通过混合源代码、评估结果和 Markdown 格式的文本单元格,我们可以生成漂亮的交互式文档。您可以在项目网站上阅读有关 Jupyter 笔记本的所有内容(jupyter.org)。

此时,您需要从 GitHub 代码检出的根目录启动笔记本服务器。启动服务器的确切方式取决于您的操作系统的细节以及您安装 Jupyter 的方式和位置。如果您有问题,请随时在书的论坛上提问。⁵ 一旦启动,您的默认浏览器将弹出,显示本地笔记本文件列表。

注意 Jupyter Notebooks 是通过代码表达和探索想法的强大工具。虽然我们认为它们非常适合本书的用例,但并非人人都适用。我们认为专注于消除摩擦和最小化认知负担很重要,对每个人来说都会有所不同。在使用 PyTorch 进行实验时,请使用您喜欢的工具。

书中所有示例的完整工作代码可以在书的网站(www.manning.com/books/deep-learning-with-pytorch)和我们在 GitHub 上的存储库中找到(github.com/deep-learning-with-pytorch/dlwpt-code)。

1.6 练习

  1. 启动 Python 以获得交互式提示符。
  1. 您正在使用哪个 Python 版本?我们希望至少是 3.6!
  2. 您能够import torch吗?您得到了哪个 PyTorch 版本?
  3. torch.cuda.is_available()的结果是什么?它是否符合您基于所使用硬件的期望?
  1. 启动 Jupyter 笔记本服务器。
  1. Jupyter 使用的 Python 版本是多少?
  2. Jupyter 使用的torch库的位置与您从交互式提示符导入的位置相同吗?

1.7 总结

  • 深度学习模型会自动从示例中学习将输入和期望输出关联起来。
  • 像 PyTorch 这样的库允许您高效地构建和训练神经网络模型。
  • PyTorch 专注于灵活性和速度,同时最大限度地减少认知负担。它还默认立即执行操作。
  • TorchScript 允许我们预编译模型,并不仅可以从 Python 中调用它们,还可以从 C++程序和移动设备中调用。
  • 自 2017 年初发布 PyTorch 以来,深度学习工具生态系统已经显著巩固。
  • PyTorch 提供了许多实用库,以便促进深度学习项目。

¹Edsger W. Dijkstra,“计算科学的威胁”,mng.bz/nPJ5

² 我们还推荐www.arxiv-sanity.com来帮助组织感兴趣的研究论文。

³ 在 2019 年的国际学习表示会议(ICLR)上,PyTorch 在 252 篇论文中被引用,比前一年的 87 篇增加了很多,并且与 TensorFlow 的水平相同,后者在 266 篇论文中被引用。

⁴ 这只是在运行时进行的数据准备,而不是预处理,后者在实际项目中可能占据相当大的部分。

forums.manning.com/forums/deep-learning-with-pytorch

二、预训练网络

本章内容包括

  • 运行预训练图像识别模型
  • GANs 和 CycleGAN 简介
  • 能够生成图像文本描述的字幕模型
  • 通过 Torch Hub 分享模型

我们在第一章结束时承诺在这一章中揭示令人惊奇的事物,现在是时候兑现了。计算机视觉无疑是深度学习的出现最受影响的领域之一,原因有很多。存在对自然图像进行分类或解释内容的需求,非常庞大的数据集变得可用,以及发明了新的构造,如卷积层,并且可以在 GPU 上以前所未有的准确性快速运行。所有这些因素与互联网巨头希望理解数百万用户使用移动设备拍摄的图片,并在这些巨头平台上管理的愿望相结合。简直是一场完美的风暴。

我们将学习如何使用该领域最优秀研究人员的工作,通过下载和运行已经在开放的大规模数据集上训练过的非常有趣的模型。我们可以将预训练的神经网络看作类似于一个接受输入并生成输出的程序。这样一个程序的行为由神经网络的架构和训练过程中看到的示例所决定,以期望的输入-输出对或输出应满足的期望属性。使用现成的模型可以快速启动深度学习项目,因为它利用了设计模型的研究人员的专业知识,以及用于训练权重的计算时间。

在本章中,我们将探索三种流行的预训练模型:一种可以根据内容标记图像的模型,另一种可以从真实图像中制作新图像,以及一种可以使用正确的英语句子描述图像内容的模型。我们将学习如何在 PyTorch 中加载和运行这些预训练模型,并介绍 PyTorch Hub,这是一组工具,通过这些工具,像我们将讨论的预训练模型这样的 PyTorch 模型可以通过统一接口轻松提供。在这个过程中,我们将讨论数据来源,定义术语如标签,并参加斑马竞技表演。

如果您是从其他深度学习框架转到 PyTorch,并且宁愿直接学习 PyTorch 的基础知识,您可以跳到下一章。本章涵盖的内容比基础知识更有趣,而且与任何给定的深度学习工具有一定的独立性。这并不是说它们不重要!但是,如果您在其他深度学习框架中使用过预训练模型,那么您已经知道它们可以是多么强大的工具。如果你已经熟悉生成对抗网络(GAN)游戏,那么我们不需要向您解释。

我们希望您继续阅读,因为本章隐藏了一些重要的技能。学习如何使用 PyTorch 运行预训练模型是一项有用的技能–毫无疑问。如果模型经过大型数据集的训练,这将尤其有用。我们需要习惯在真实世界数据上获取和运行神经网络的机制,然后可视化和评估其输出,无论我们是否对其进行了训练。

2.1 识别图像主题的预训练网络

作为我们对深度学习的首次尝试,我们将运行一个在对象识别任务上预训练的最先进的深度神经网络。可以通过源代码存储库访问许多预训练网络。研究人员通常会在其论文中发布源代码,而且通常该代码附带通过在参考数据集上训练模型获得的权重。使用其中一个模型可以使我们例如,可以轻松地为我们的下一个网络服务配备图像识别功能。

我们将在这里探索的预训练网络是在 ImageNet 数据集的一个子集上训练的(imagenet.stanford.edu)。ImageNet 是由斯坦福大学维护的一个非常庞大的数据集,包含超过 1400 万张图像。所有图像都标有来自 WordNet 数据集(wordnet.princeton.edu)的名词层次结构,WordNet 是一个大型的英语词汇数据库。

ImageNet 数据集,像其他几个公共数据集一样,起源于学术竞赛。竞赛一直是研究机构和公司研究人员经常挑战彼此的主要领域之一。自 2010 年创立以来,ImageNet 大规模视觉识别挑战赛(ILSVRC)已经变得越来越受欢迎。这个特定的竞赛基于一些任务,每年可能会有所不同,例如图像分类(告诉图像包含哪些对象类别)、对象定位(识别图像中对象的位置)、对象检测(识别和标记图像中的对象)、场景分类(对图像中的情况进行分类)和场景解析(将图像分割成与语义类别相关的区域,如牛、房子、奶酪、帽子)。特别是,图像分类任务包括获取输入图像并生成 5 个标签列表,来自 1000 个总类别,按置信度排序,描述图像的内容。

ILSVRC 的训练集包含了 120 万张图像,每张图像都标有 1000 个名词中的一个(例如,“狗”),被称为图像的类别。在这个意义上,我们将使用标签类别这两个术语来互换使用。我们可以在图 2.1 中看到来自 ImageNet 的图像。

图 2.1 ImageNet 图像的一个小样本

图 2.2 推理过程

我们最终将能够将我们自己的图像输入到我们的预训练模型中,如图 2.2 所示。这将导致该图像的预测标签列表,然后我们可以检查模型认为我们的图像是什么。有些图像的预测是准确的,而其他的则不是!

输入图像将首先被预处理为torch.Tensor类的实例。它是一个具有高度和宽度的 RGB 图像,因此这个张量将具有三个维度:三个颜色通道和特定大小的两个空间图像维度。(我们将在第三章详细介绍张量是什么,但现在,可以将其视为浮点数的向量或矩阵。)我们的模型将获取处理过的输入图像,并将其传递到预训练网络中,以获取每个类别的分数。最高分对应于权重下最可能的类别。然后,每个类别都被一对一地映射到一个类别标签。该输出包含一个具有 1000 个元素的torch.Tensor,每个元素代表与该类别相关的分数。

在我们进行所有这些之前,我们需要获取网络本身,看看它的结构,了解如何准备数据以便模型使用。

2.1.1 获取用于图像识别的预训练网络

正如讨论的那样,我们现在将配备一个在 ImageNet 上训练过的网络。为此,我们将查看 TorchVision 项目(github.com/pytorch/vision),其中包含一些最佳性能的计算机视觉神经网络架构,如 AlexNet(mng.bz/lo6z)、ResNet(arxiv.org/pdf/ 1512.03385.pdf)和 Inception v3(arxiv.org/pdf/1512.00567.pdf)。它还可以轻松访问 ImageNet 等数据集,以及其他用于快速掌握 PyTorch 中计算机视觉应用的实用工具。我们将在本书后面深入研究其中一些。现在,让我们加载并运行两个网络:首先是 AlexNet,这是早期用于图像识别的突破性网络;然后是残差网络,简称 ResNet,它在 2015 年赢得了 ImageNet 分类、检测和定位比赛等多个比赛。如果你在第一章中没有安装 PyTorch,现在是一个很好的时机。

预定义的模型可以在torchvision.models(code/p1ch2/2 _pre_trained_networks.ipynb)中找到:

# In[1]:
from torchvision import models

我们可以看一下实际的模型:

# In[2]:
dir(models)
# Out[2]:
['AlexNet',
 'DenseNet',
 'Inception3',
 'ResNet',
 'SqueezeNet',
 'VGG',
...
 'alexnet',
 'densenet',
 'densenet121',
...
 'resnet',
 'resnet101',
 'resnet152',
...
 ]

大写的名称指的是实现一些流行模型的 Python 类。它们在架构上有所不同–即,在输入和输出之间发生的操作排列方式不同。小写的名称是方便函数,返回从这些类实例化的模型,有时使用不同的参数集。例如,resnet101返回一个具有 101 层的ResNet实例,resnet18有 18 层,依此类推。现在我们将注意力转向 AlexNet。

2.1.2 AlexNet

AlexNet 架构以绝对优势赢得了 2012 年 ILSVRC,其前 5 个测试错误率(即,正确标签必须在前 5 个预测中)为 15.4%。相比之下,第二名提交的模型,不是基于深度网络的,错误率为 26.2%。这是计算机视觉历史上的一个决定性时刻:社区开始意识到深度学习在视觉任务中的潜力。这一飞跃随后不断改进,更现代的架构和训练方法使得前 5 个错误率降至 3%。

从今天的标准来看,与最先进的模型相比,AlexNet 是一个相对较小的网络。但在我们的情况下,它非常适合初次了解一个做某事的神经网络,并学习如何在新图像上运行预训练版本。

我们可以在图 2.3 中看到 AlexNet 的结构。虽然我们现在已经具备了理解它的所有要素,但我们可以预见一些方面。首先,每个块由一堆乘法和加法组成,加上我们将在第五章中发现的输出中的其他函数。我们可以将其视为一个滤波器–一个接受一个或多个图像作为输入并产生其他图像作为输出的函数。它的工作方式是在训练过程中确定的,基于它所看到的示例和所需的输出。

图 2.3 AlexNet 架构

在图 2.3 中,输入图像从左侧进入,并经过五组滤波器,每组产生多个输出图像。在每个滤波器之后,图像会按照注释的方式减小尺寸。最后一组滤波器产生的图像被布置成一个 4,096 元素的一维向量,并进行分类以产生 1,000 个输出概率,每个输出类别一个。

为了在输入图像上运行 AlexNet 架构,我们可以创建一个AlexNet类的实例。操作如下:

# In[3]:
alexnet = models.AlexNet()

此时,alexnet是一个可以运行 AlexNet 架构的对象。目前,我们不需要了解这种架构的细节。暂时来说,AlexNet只是一个不透明的对象,可以像函数一样调用。通过为alexnet提供一些精确大小的输入数据(我们很快将看到这些输入数据应该是什么),我们将通过网络进行前向传递。也就是说,输入将通过第一组神经元,其输出将被馈送到下一组神经元,一直到最终输出。从实际角度来看,假设我们有一个正确类型的input对象,我们可以使用output = alexnet(input)来运行前向传递。

但如果我们这样做,我们将通过整个网络传递数据来产生…垃圾!这是因为网络未初始化:它的权重,即输入相加和相乘的数字,尚未经过任何训练–网络本身是一个空白(或者说是随机)状态。我们需要从头开始训练它,或者加载之前训练的权重,现在我们将这样做。

为此,让我们回到models模块。我们了解到大写名称对应于实现用于计算机视觉的流行架构的类。另一方面,小写名称是函数,用于实例化具有预定义层数和单元数的模型,并可选择下载和加载预训练权重。请注意,使用这些函数并非必要:它们只是方便地实例化具有与预训练网络构建方式相匹配的层数和单元数的模型。

2.1.3 ResNet

使用resnet101函数,我们现在将实例化一个 101 层的卷积神经网络。为了让事情有个对比,2015 年之前,在残差网络出现之前,实现这样深度的稳定训练被认为是极其困难的。残差网络使用了一个技巧,使这成为可能,并通过这样做,在当年一举超过了几个基准。

现在让我们创建网络的一个实例。我们将传递一个参数,指示函数下载在 ImageNet 数据集上训练的resnet101的权重,该数据集包含 1,200,000 张图像和 1,000 个类别:

# In[4]:
resnet = models.resnet101(pretrained=True)

当我们盯着下载进度时,我们可以花一分钟来欣赏resnet101拥有 4450 万个参数–这是一个需要自动优化的大量参数!

2.1.4 准备好了,几乎可以运行了

好的,我们刚刚得到了什么?由于我们很好奇,我们将看一眼resnet101是什么样子。我们可以通过打印返回模型的值来做到这一点。这给了我们一个文本表示形式,提供了与我们在 2.3 中看到的相同类型的关于网络结构的详细信息。目前,这将是信息过载,但随着我们在书中的进展,我们将增加理解这段代码告诉我们的能力:

# In[5]:
resnet
# Out[5]:
ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3),
                  bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True,
                     track_running_stats=True)
  (relu): ReLU(inplace)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1,
                       ceil_mode=False)
  (layer1): Sequential(
    (0): Bottleneck(
...
    )
  )
  (avgpool): AvgPool2d(kernel_size=7, stride=1, padding=0)
  (fc): Linear(in_features=2048, out_features=1000, bias=True)
)

我们在这里看到的是modules,每行一个。请注意,它们与 Python 模块没有任何共同之处:它们是单独的操作,神经网络的构建模块。在其他深度学习框架中,它们也被称为

如果我们向下滚动,我们会看到很多Bottleneck模块一个接一个地重复(共 101 个!),包含卷积和其他模块。这就是典型的用于计算机视觉的深度神经网络的解剖学:一个或多或少顺序级联的滤波器和非线性函数,最终以一个层(fc)产生每个 1,000 个输出类别(out_features)的分数。

resnet变量可以像函数一样调用,输入一个或多个图像,并为每个 1,000 个 ImageNet 类别产生相同数量的分数。然而,在这之前,我们必须对输入图像进行预处理,使其具有正确的大小,并使其值(颜色)大致处于相同的数值范围内。为了做到这一点,torchvision模块提供了transforms,允许我们快速定义基本预处理函数的流水线:

# In[6]:
from torchvision import transforms
preprocess = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(
            mean=[0.485, 0.456, 0.406],
            std=[0.229, 0.224, 0.225]
        )])

在这种情况下,我们定义了一个preprocess函数,将输入图像缩放到 256×256,将图像裁剪到围绕中心的 224×224,将其转换为张量(一个 PyTorch 多维数组:在这种情况下,一个带有颜色、高度和宽度的 3D 数组),并对其 RGB(红色、绿色、蓝色)组件进行归一化,使其具有定义的均值和标准差。如果我们希望网络产生有意义的答案,这些值需要与训练期间呈现给网络的值匹配。当我们深入研究如何制作自己的图像识别模型时,我们将更深入地了解 transforms,见第 7.1.3 节。

现在我们可以获取我们最喜欢的狗的图片(比如,GitHub 仓库中的 bobby.jpg),对其进行预处理,然后看看 ResNet 对其的看法。我们可以从本地文件系统中使用 Pillow(pillow.readthedocs.io/en/stable)加载图像,这是 Python 的图像处理模块:

# In[7]:
from PIL import Image
img = Image.open("../data/p1ch2/bobby.jpg")

如果我们是从 Jupyter Notebook 中跟随进行的,我们将执行以下操作以内联查看图片(它将显示在以下内容中的处):

# In[8]:
img
# Out[8]:
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1280x720 at
 0x1B1601360B8>

否则,我们可以调用show方法,这将弹出一个带有查看器的窗口,以查看图 2.4 中显示的图像:

图 2.4 Bobby,我们非常特殊的输入图像

>>> img.show()

接下来,我们可以通过我们的预处理流程传递图像:

# In[9]:
img_t = preprocess(img)

然后我们可以以网络期望的方式重塑、裁剪和归一化输入张量。我们将在接下来的两章中更多地了解这一点;现在请耐心等待:

# In[10]:
import torch
batch_t = torch.unsqueeze(img_t, 0)

现在我们准备运行我们的模型。

PyTorch 深度学习(GPT 重译)(一)(2)https://developer.aliyun.com/article/1485199

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
7天前
|
机器学习/深度学习 PyTorch 调度
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
在深度学习中,学习率作为关键超参数对模型收敛速度和性能至关重要。传统方法采用统一学习率,但研究表明为不同层设置差异化学习率能显著提升性能。本文探讨了这一策略的理论基础及PyTorch实现方法,包括模型定义、参数分组、优化器配置及训练流程。通过示例展示了如何为ResNet18设置不同层的学习率,并介绍了渐进式解冻和层适应学习率等高级技巧,帮助研究者更好地优化模型训练。
15 4
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
|
15天前
|
机器学习/深度学习 数据挖掘 PyTorch
🎓PyTorch深度学习入门课:编程小白也能玩转的高级数据分析术
踏入深度学习领域,即使是编程新手也能借助PyTorch这一强大工具,轻松解锁高级数据分析。PyTorch以简洁的API、动态计算图及灵活性著称,成为众多学者与工程师的首选。本文将带你从零开始,通过环境搭建、构建基础神经网络到进阶数据分析应用,逐步掌握PyTorch的核心技能。从安装配置到编写简单张量运算,再到实现神经网络模型,最后应用于图像分类等复杂任务,每个环节都配有示例代码,助你快速上手。实践出真知,不断尝试和调试将使你更深入地理解这些概念,开启深度学习之旅。
20 1
|
1月前
|
机器学习/深度学习 人工智能 PyTorch
深度学习领域中pytorch、onnx和ncnn的关系
PyTorch、ONNX 和 NCNN 是深度学习领域中的三个重要工具或框架,它们在模型开发、转换和部署过程中扮演着不同但相互关联的角色。
63 11
|
2月前
|
机器学习/深度学习 边缘计算 PyTorch
PyTorch 与边缘计算:将深度学习模型部署到嵌入式设备
【8月更文第29天】随着物联网技术的发展,越来越多的数据处理任务开始在边缘设备上执行,以减少网络延迟、降低带宽成本并提高隐私保护水平。PyTorch 是一个广泛使用的深度学习框架,它不仅支持高效的模型训练,还提供了多种工具帮助开发者将模型部署到边缘设备。本文将探讨如何将PyTorch模型高效地部署到嵌入式设备上,并通过一个具体的示例来展示整个流程。
171 1
|
17天前
|
机器学习/深度学习 数据挖掘 TensorFlow
解锁Python数据分析新技能,TensorFlow&PyTorch双引擎驱动深度学习实战盛宴
在数据驱动时代,Python凭借简洁的语法和强大的库支持,成为数据分析与机器学习的首选语言。Pandas和NumPy是Python数据分析的基础,前者提供高效的数据处理工具,后者则支持科学计算。TensorFlow与PyTorch作为深度学习领域的两大框架,助力数据科学家构建复杂神经网络,挖掘数据深层价值。通过Python打下的坚实基础,结合TensorFlow和PyTorch的强大功能,我们能在数据科学领域探索无限可能,解决复杂问题并推动科研进步。
38 0
|
26天前
|
机器学习/深度学习 数据挖掘 TensorFlow
从数据小白到AI专家:Python数据分析与TensorFlow/PyTorch深度学习的蜕变之路
【9月更文挑战第10天】从数据新手成长为AI专家,需先掌握Python基础语法,并学会使用NumPy和Pandas进行数据分析。接着,通过Matplotlib和Seaborn实现数据可视化,最后利用TensorFlow或PyTorch探索深度学习。这一过程涉及从数据清洗、可视化到构建神经网络的多个步骤,每一步都需不断实践与学习。借助Python的强大功能及各类库的支持,你能逐步解锁数据的深层价值。
46 0
|
2月前
|
UED 开发者
哇塞!Uno Platform 数据绑定超全技巧大揭秘!从基础绑定到高级转换,优化性能让你的开发如虎添翼
【8月更文挑战第31天】在开发过程中,数据绑定是连接数据模型与用户界面的关键环节,可实现数据自动更新。Uno Platform 提供了简洁高效的数据绑定方式,使属性变化时 UI 自动同步更新。通过示例展示了基本绑定方法及使用 `Converter` 转换数据的高级技巧,如将年龄转换为格式化字符串。此外,还可利用 `BindingMode.OneTime` 提升性能。掌握这些技巧能显著提高开发效率并优化用户体验。
44 0
|
2月前
|
机器学习/深度学习 PyTorch TensorFlow
深度学习框架之争:全面解析TensorFlow与PyTorch在功能、易用性和适用场景上的比较,帮助你选择最适合项目的框架
【8月更文挑战第31天】在深度学习领域,选择合适的框架至关重要。本文通过开发图像识别系统的案例,对比了TensorFlow和PyTorch两大主流框架。TensorFlow由Google开发,功能强大,支持多种设备,适合大型项目和工业部署;PyTorch则由Facebook推出,强调灵活性和速度,尤其适用于研究和快速原型开发。通过具体示例代码展示各自特点,并分析其适用场景,帮助读者根据项目需求和个人偏好做出明智选择。
36 0
|
2月前
|
机器学习/深度学习 分布式计算 PyTorch
构建可扩展的深度学习系统:PyTorch 与分布式计算
【8月更文第29天】随着数据量和模型复杂度的增加,单个GPU或CPU已无法满足大规模深度学习模型的训练需求。分布式计算提供了一种解决方案,能够有效地利用多台机器上的多个GPU进行并行训练,显著加快训练速度。本文将探讨如何使用PyTorch框架实现深度学习模型的分布式训练,并通过一个具体的示例展示整个过程。
54 0
|
2月前
|
机器学习/深度学习 PyTorch 测试技术
深度学习入门:使用 PyTorch 构建和训练你的第一个神经网络
【8月更文第29天】深度学习是机器学习的一个分支,它利用多层非线性处理单元(即神经网络)来解决复杂的模式识别问题。PyTorch 是一个强大的深度学习框架,它提供了灵活的 API 和动态计算图,非常适合初学者和研究者使用。
35 0
下一篇
无影云桌面