PyTorch 口袋参考(五)
译者:飞龙
第七章:将 PyTorch 部署到生产环境
到目前为止,本书大部分内容都集中在模型设计和训练上。早期章节向您展示了如何使用 PyTorch 的内置能力设计您的模型,并创建自定义的 NN 模块、损失函数、优化器和其他算法。在上一章中,我们看到了如何使用分布式训练和模型优化来加速模型训练时间,并最大程度地减少运行模型所需的资源。
到目前为止,您已经拥有创建一些经过良好训练、尖端的 NN 模型所需的一切,但不要让您的创新孤立存在。现在是时候通过应用程序将您的模型部署到世界上了。
过去,从研究到生产是一项具有挑战性的任务,需要一个软件工程团队将 PyTorch 模型移至一个框架并将其集成到(通常非 Python)生产环境中。如今,PyTorch 包括内置工具和外部库,支持快速部署到各种生产环境。
在本章中,我们专注于将您的模型部署到推理而非训练,并探讨如何将经过训练的 PyTorch 模型部署到各种应用程序中。首先,我将描述 PyTorch 内置的各种能力和工具,供您用于部署。像 TorchServe 和 TorchScript 这样的工具使您能够轻松地将 PyTorch 模型部署到云端、移动设备或边缘设备。
根据应用程序和环境,您可能有多种部署选项,每种选项都有其自身的权衡。我将向您展示如何在多个云端和边缘环境中部署您的 PyTorch 模型的示例。您将学习如何部署到用于开发和生产规模的 Web 服务器,iOS 和 Android 移动设备,以及基于 ARM 处理器、GPU 和现场可编程门阵列(FPGA)硬件的物联网(IoT)设备。
本章还将提供参考代码,包括我们使用的关键 API 和库的引用,以便轻松入门。当您需要部署模型时,您可以参考本章进行快速查阅,以便在云端或移动环境中展示您的应用程序。
让我们开始回顾 PyTorch 提供的资源,以帮助您部署您的模型。
PyTorch 部署工具和库
PyTorch 包括内置工具和能力,以便将您的模型部署到生产环境和边缘设备。在本节中,我们将探索这些工具,并在本章的其余部分将它们应用于各种环境中。
PyTorch 的部署能力包括其自然的 Python API,以及 TorchServe、TorchScript、ONNX 和移动库。由于 PyTorch 的自然 API 基于 Python,PyTorch 模型可以在任何支持 Python 的环境中直接部署。
表 7-1 总结了可用于部署的各种资源,并指示如何适当地使用每种资源。
表 7-1. 部署 PyTorch 资源
| 资源 | 使用 |
|---|---|
| Python API | 进行快速原型设计、训练和实验;编写 Python 运行时程序。 |
| TorchScript | 提高性能和可移植性(例如,在 C++中加载和运行模型);编写非 Python 运行时或严格的延迟和性能要求。 |
| TorchServe | 一个快速的生产环境工具,具有模型存储、A/B 测试、监控和 RESTful API。 |
| ONNX | 部署到具有 ONNX 运行时或 FPGA 设备的系统。 |
| 移动库 | 部署到 iOS 和 Android 设备。 |
以下各节为每个部署资源提供参考和一些示例代码。在每种情况下,我们将使用相同的示例模型,接下来将对其进行描述。
常见示例模型
对于本章提供的每个部署资源示例和应用程序,以及参考代码,我们将使用相同的模型。对于我们的示例,我们将使用一个使用 ImageNet 数据预训练的 VGG16 模型来部署一个图像分类器。这样,每个部分都可以专注于使用的部署方法,而不是模型本身。对于每种方法,您可以用自己的模型替换 VGG16 模型,并按照相同的工作流程来实现您自己设计的结果。
以下代码实例化了本章中将要使用的模型:
from torchvision.models import vgg16
model = vgg16(pretrained=True)
我们之前使用过 VGG16 模型。为了让您了解模型的复杂性,让我们使用以下代码打印出可训练参数的数量:
import numpy as np
model_parameters = filter(lambda p:
p.requires_grad, model.parameters())
params = sum([np.prod(p.size()) for
p in model_parameters])
print(params)
# out: 138357544
VGG16 模型有 138,357,544 个可训练参数。当我们逐步进行每种方法时,请记住在这个复杂性水平上的性能。您可以将其用作比较您模型复杂性的粗略基准。
在实例化 VGG16 模型后,将其部署到 Python 应用程序中需要很少的工作。事实上,在之前的章节中测试我们的模型时,我们已经这样做了。在我们进入其他方法之前,让我们再次回顾一下这个过程。
Python API
Python API 并不是一个新资源。这是我们在整本书中一直在使用的资源。我在这里提到它是为了指出您可以在不更改代码的情况下部署您的 PyTorch 模型。在这种情况下,您只需从任何 Python 应用程序中以评估模式调用您的模型,如下面的代码所示:
import system
import torch
if __name__ == "__main__":
model = MyModel()
model.load_state_dict(torch.load(PATH))
model.eval()
outputs = model(inputs)
print(outputs)
该代码加载模型,传入输入,并打印输出。这是一个简单的独立 Python 应用程序。您将看到如何在本章后面使用 RESTful API 和 Flask 将模型部署到 Python Web 服务器。使用 Flask Web 服务器,您可以构建一个快速的浏览器应用程序,展示您模型的能力。
Python 并不总是在生产环境中使用,因为它的性能较慢,而且缺乏真正的多线程。如果您的生产环境使用另一种语言(例如 C++、Java、Rust 或 Go),您可以将您的模型转换为 TorchScript 代码。
TorchScript
TorchScript 是一种序列化和优化 PyTorch 模型代码的方式,使得 PyTorch 模型可以在非 Python 运行环境中保存和执行,而不依赖于 Python。TorchScript 通常用于在 C++中运行 PyTorch 模型,并与支持 C++绑定的任何语言一起使用。
TorchScript 代表了一个 PyTorch 模型的格式,可以被 TorchScript 编译器理解、编译和序列化。TorchScript 编译器创建了一个序列化的优化版本的您的模型,可以在 C++应用程序中使用。要在 C++中加载您的 TorchScript 模型,您将使用名为LibTorch的 PyTorch C++ API 库。
有两种方法可以将您的 PyTorch 模型转换为 TorchScript。第一种称为tracing,这是一个过程,在这个过程中,您传入一个示例输入并使用一行代码进行转换。在大多数情况下使用。第二种称为scripting,当您的模型具有更复杂的控制代码时使用。例如,如果您的模型具有依赖于输入本身的条件if语句,您将需要使用 scripting。让我们看一下每种情况的一些参考代码。
由于我们的 VGG16 示例模型没有任何控制流,我们可以使用跟踪来将我们的模型转换为 TorchScript,如下面的代码所示:
import torch
model = vgg16(pretrained=True)
example_input = torch.rand(1, 3, 224, 224)
torchscript_model = torch.jit.trace(model,
example_input)
torchscript_model.save("traced_vgg16_model.pt")
该代码创建了一个 Python 可调用模型torchscript_model,可以使用正常的 PyTorch 方法进行评估,例如output = torchscript_model(inputs)。一旦我们保存了模型,就可以在 C++应用程序中使用它。
注意
在 PyTorch 中评估模型的“正常”方法通常被称为eager mode,因为这是开发中评估模型的最快方法。
如果我们的模型使用了控制流,我们将需要使用注释方法将其转换为 TorchScript。让我们考虑以下模型:
import torch.nn as nn
class ControlFlowModel(nn.Module):
def __init__(self, N):
super(ControlFlowModel, self).__init__()
self.fc = nn.Linear(N,100)
def forward(self, input):
if input.sum() > 0:
output = input
else:
output = -input
return output
model = ControlFlowModel(10)
torchcript_model = torch.jit.script(model)
torchscript_model.save("scripted_vgg16_model.pt")
在这个例子中,ControlFlowModel的输出和权重取决于输入值。在这种情况下,我们需要使用torch.jit.script(),然后我们可以像跟踪一样将模型保存到 TorchScript 中。
现在我们可以在 C++应用程序中使用我们的模型,如下所示的 C++代码:
include <torch/script.h>
#include <iostream>
#include <memory>
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "usage: example-app" >> \
"*`<path-to-exported-script-module>`*\n";
return -1;
}
torch::jit::script::Module model;
model = torch::jit::load(argv[1]);
std::vector<torch::jit::IValue> inputs;
inputs.push_back( \
torch::ones({1, 3, 224, 224}));
at::Tensor output = model.forward(inputs).toTensor();
std::cout \
<< output.slice(/*dim=*/1, \
/*start=*/0, /*end=*/5) \
<< '\n';
}
}
我们将 TorchScript 模块的文件名传递给程序,并使用torch::jit::load()加载模型。然后我们创建一个示例输入向量,将其通过我们的 TorchScript 模型运行,并将输出转换为张量,打印到stdout。
TorchScript API 提供了额外的函数来支持将模型转换为 TorchScript。表 7-2 列出了支持的函数。
表 7-2. TorchScript API 函数
| 函数 | 描述 |
|---|---|
script(obj[, optimize, _frames_up, _rcb]) | 检查源代码,使用TorchScript编译器将其编译为TorchScript代码,并返回一个ScriptModule或ScriptFunction |
trace(func, example_inputs[, optimize, ...]) | 跟踪一个函数并返回一个可执行的或者ScriptFunction,将使用即时编译进行优化 |
script_if_tracing(fn) | 在跟踪期间首次调用fn时编译 |
trace_module(mod, inputs[, optimize, ...]) | 跟踪一个模块并返回一个可执行的ScriptModule,将使用即时编译进行优化 |
fork(func, *args, **kwargs) | 创建一个异步任务,执行func并引用此执行结果的值 |
wait(future) | 强制完成一个torch.jit.Future[T]异步任务,返回任务的结果 |
ScriptModule() | 将脚本封装成 C++ torch::jit::Module |
ScriptFunction() | 与ScriptModule()相同,但表示一个单独的函数,没有任何属性或参数 |
freeze(mod[, preserved_attrs]) | 克隆一个ScriptModule,并尝试将克隆模块的子模块、参数和属性内联为TorchScript IR 图中的常量 |
save(m, f[, _extra_files]) | 保存模块的离线版本,用于在单独的进程中使用 |
load(f[, map_location, _extra_files]) | 加载之前使用torch.jit.save()保存的ScriptModule或ScriptFunction |
ignore([drop]) | 指示编译器忽略一个函数或方法,并保留为 Python 函数 |
unused(fn) | 指示编译器忽略一个函数或方法,并替换为引发异常 |
isinstance(obj, target_type) | 在 TorchScript 中提供容器类型细化 |
在本节中,我们使用 TorchScript 来提高模型在 C++应用程序或绑定到 C++的语言中的性能。然而,规模化部署 PyTorch 模型需要额外的功能,比如打包模型、配置运行环境、暴露 API 端点、日志和监控,以及管理多个模型版本。幸运的是,PyTorch 提供了一个名为 TorchServe 的工具,以便于这些任务,并快速部署您的模型进行规模推理。
TorchServe
TorchServe 是一个开源的模型服务框架,可以轻松部署训练好的 PyTorch 模型。它由 AWS 工程师开发,并于 2020 年 4 月与 Facebook 联合发布,目前由 AWS 积极维护。TorchServe 支持部署模型到生产环境所需的所有功能,包括多模型服务、模型版本控制用于 A/B 测试、日志和监控指标、以及与其他系统集成的 RESTful API。图 7-1 展示了 TorchServe 的工作原理。
图 7-1. TorchServe 架构
客户端应用程序通过多个 API 与 TorchServe 进行交互。推理 API 提供主要的推理请求和预测。客户端应用程序通过 RESTful API 请求发送输入数据,并接收预测结果。管理 API 允许您注册和管理已部署的模型。您可以注册、注销、设置默认模型、配置 A/B 测试、检查状态,并为模型指定工作人员数量。指标 API 允许您监视每个模型的性能。
TorchServe 运行所有模型实例并捕获服务器日志。它处理前端 API 并管理模型存储到磁盘。TorchServe 还为常见应用程序提供了许多默认处理程序,如目标检测和文本分类。处理程序负责将 API 中的数据转换为模型将处理的格式。这有助于加快部署速度,因为您不必为这些常见应用程序编写自定义代码。
警告
TorchServe 是实验性的,可能会发生变化。
要通过 TorchServe 部署您的模型,您需要遵循几个步骤。首先,您需要安装 TorchServe 的工具。然后,您将使用模型存档工具打包您的模型。一旦您的模型被存档,您将运行 TorchServe Web 服务器。一旦 Web 服务器运行,您可以使用其 API 请求预测,管理您的模型,执行监控,或访问服务器日志。让我们看看如何执行每个步骤。
安装 TorchServe 和 torch-model-archiver
AWS 在 Amazon SageMaker 或 Amazon EC2 实例中提供了预安装的 TorchServe 机器。如果您使用不同的云提供商,请在开始之前检查是否存在预安装实例。如果您使用本地服务器或需要安装 TorchServe,请参阅TorchServe 安装说明。
尝试的一个简单方法是使用 conda 或 pip 进行安装,如下所示:
$ `conda` `install` `torchserve` `torch-model-archiver` `-c` `pytorch`
$ `pip` `install` `torchserve` `torch-model-archiver`
如果遇到问题,请参考上述链接中的 TorchServe 安装说明。
打包模型存档
TorchServe 有能力将所有模型工件打包到单个模型存档文件中。为此,我们将使用我们在上一步中安装的 torch-model-archiver 命令行工具。它将模型检查点以及 state_dict 打包到一个 .mar 文件中,TorchServe 服务器将使用该文件来提供模型服务。
您可以使用 torch-model-archiver 来存档您的 TorchScript 模型以及标准的 “eager 模式” 实现,如下所示。
对于 TorchScript 模型,命令行如下:
$ `torch``-``model``-``archiver` `-``-``model``-``name` `vgg16`
`-``-``version` `1.0` `-``-``serialized``-``file` `model``.``pt` `-``-``handler`
`image_classifier`
我们将模型设置为我们的示例 VGG16 模型,并使用保存的序列化文件 model.pt。在这种情况下,我们也可以使用默认的 image_classifier 处理程序。
对于标准的 eager 模式模型,我们将使用以下命令:
$ `torch``-``model``-``archiver` `-``-``model``-``name` `vgg16`
`-``-``version` `1.0` `-``-``model``-``file` `model``.``py` `-``-``serialized``-``file` `model``.``pt`
`-``-``handler` `image_classifier`
这与之前的命令类似,但我们还需要指定模型文件 model.py。
torch-model-archiver 工具的完整选项集如下所示:
$ `torch-model-archiver` `-h`
usage: torch-model-archiver [-h]
--model-name MODEL_NAME
--version MODEL_VERSION_NUMBER
--model-file MODEL_FILE_PATH
--serialized-file MODEL_SERIALIZED_PATH
--handler HANDLER
[--runtime {python,python2,python3}]
[--export-path EXPORT_PATH] [-f]
[--requirements-file]
表 7-3. 模型存档工具选项
| 选项 | 描述 |
|---|---|
-h, --help | 帮助消息。显示帮助消息后,程序将退出。 |
--model-name *MODEL_NAME* | 导出的模型名称。导出的文件将命名为 .mar,如果未指定 --export-path,则将保存在当前工作目录中,否则将保存在导出路径下。 |
--serialized-file *SERIALIZED_FILE* | 指向包含 state_dict 的 .pt 或 .pth 文件的路径,对于 eager 模式,或者包含可执行 ScriptModule 的路径,对于 TorchScript。 |
--model-file *MODEL_FILE* | 指向包含模型架构的 Python 文件的路径。对于 eager 模式模型,此参数是必需的。模型架构文件必须只包含一个从 torch.nn.modules 扩展的类定义。 |
--handler *HANDLER* | TorchServe的默认处理程序名称或处理自定义TorchServe推理逻辑的 Python 文件路径。 |
--extra-files *EXTRA_FILES* | 逗号分隔的额外依赖文件的路径。 |
--runtime *{python, python2, python3}* | 运行时指定要在其上运行推理代码的语言。默认运行时为RuntimeType.PYTHON,但目前支持以下运行时:python,python2和python3。 |
--export-path *EXPORT_PATH* | 导出的 .mar 文件将保存在的路径。这是一个可选参数。如果未指定--export-path,文件将保存在当前工作目录中。 |
--archive-format *{tgz, no-archive, default}* | 存档模型工件的格式。tgz以*.tar.gz格式创建模型存档。如果平台托管需要模型工件为.tar.gz*,请使用此选项。no-archive在*/处创建模型工件的非存档版本。由于此选择,将在该位置创建一个 MANIFEST 文件,而不会对这些模型文件进行归档。default以.mar格式创建模型存档。这是默认的归档格式。以此格式归档的模型将可以轻松托管在TorchServe*上。 |
-f,--force | 当指定-f或--force标志时,将覆盖具有与--model-name中提供的相同名称的现有*.mar*文件,该文件位于--export-path指定的路径中。 |
-v, --version | 模型的版本。 |
-r, --requirements-file | 指定包含要由TorchServe安装的模型特定 Python 包列表的requirements.txt文件的路径,以实现无缝模型服务。 |
我们可以将模型存档*.mar文件保存在/models*文件夹中。我们将使用这个作为我们的模型存储。接下来,让我们运行 TorchServe Web 服务器。
运行 TorchServe
TorchServe 包括一个从命令行运行的内置 Web 服务器。它将一个或多个 PyTorch 模型包装在一组 REST API 中,并提供控件以配置端口、主机和日志记录。以下命令启动 Web 服务器,其中所有模型都位于*/models*文件夹中的模型存储中:
$ `torchserve` `--model-store` `/models` `--start`
`--models` `all`
完整的选项集显示在表 7-4 中。
表 7-4. TorchServe 选项
| 选项 | 描述 |
|---|---|
--model-store +MODEL_STORE+ +(mandatory)+ | 指定模型存储位置,可以加载模型 |
-h, --help | 显示帮助消息并退出 |
-v, --version | 返回 TorchServe 的版本 |
--start | 启动模型服务器 |
--stop | 停止模型服务器 |
--ts-config +TS_CONFIG+ | 指示 TorchServe 的配置文件 |
--models +MODEL_PATH1 MODEL_NAME=MODEL_PATH2… [MODEL_PATH1 MODEL_NAME=MODEL_PATH2… …]+ | 指示要使用*[model_name=]model_location*格式加载的模型;位置可以是 HTTP URL、模型存档文件或包含模型存档文件的目录在MODEL_STORE中 |
--log-config +LOG_CONFIG+ | 指示 TorchServe 的 log4j 配置文件 |
--ncs, --no-config-snapshots | 禁用快照功能 |
现在 TorchServe Web 服务器正在运行,您可以使用推理 API 发送数据并请求预测。
请求预测
您可以使用推理 API 传递数据并请求预测。推理 API 在端口 8080 上侦听,默认情况下仅从本地主机访问。要更改默认设置,请参阅TorchServe 文档。要从服务器获取预测,我们使用推理 API 的Service.Predictions gRPC API,并通过 REST 调用到*/predictions/<model_name>*,如下面的命令行中使用curl所示:
$c`url` `http://localhost:8080/predictions/vgg16`
`-T` `hot_dog.jpg`
代码假设我们有一个图像文件hot_dog.jpg. JSON 格式的响应看起来像这样:
{
"class": "n02175045 hot dog",
"probability": 0.788482002828
}
您还可以使用推理 API 进行健康检查,使用以下请求:
$ `curl` `http://localhost:8080/ping`
如果服务器正在运行,响应将如下所示:
{
"health": "healthy!"
}
要查看推理 API 的完整列表,请使用以下命令:
$ `curl` `-X` `OPTIONS` `http://localhost:8080`
日志记录和监控
您可以使用 Metrics API 配置指标,并在部署时监视和记录模型的性能。Metrics API 监听端口 8082,默认情况下仅从本地主机访问,但在配置 TorchServe 服务器时可以更改默认设置。以下命令说明如何访问指标:
$ `curl` `http://127.0.0.1:8082/metrics`
# HELP ts_inference_latency_microseconds # Cumulative inference
# TYPE ts_inference_latency_microseconds counter ts_inference_latency_microseconds{
uuid="d5f84dfb-fae8-4f92-b217-2f385ca7470b",...
ts_inference_latency_microseconds{
uuid="d5f84dfb-fae8-4f92-b217-2f385ca7470b",model_name="noop"...
# HELP ts_inference_requests_total Total number of inference ...
# TYPE ts_inference_requests_total counter ts_inference_requests_total{
uuid="d5f84dfb-fae8-4f92-b217-2f385ca7470b",...
ts_inference_requests_total{
uuid="d5f84dfb-fae8-4f92-b217-2f385ca7470b",model_name="noop"...
# HELP ts_queue_latency_microseconds Cumulative queue duration ...
# TYPE ts_queue_latency_microseconds counter ts_queue_latency_microseconds{
uuid="d5f84dfb-fae8-4f92-b217-2f385ca7470b",...
ts_queue_latency_microseconds{
uuid="d5f84dfb-fae8-4f92-b217-2f385ca7470b",model_name="noop"...
默认的指标端点返回 Prometheus 格式的指标。Prometheus 是一个免费软件应用程序,用于事件监控和警报,它使用 HTTP 拉模型记录实时指标到时间序列数据库中。您可以使用curl请求查询指标,或者将 Prometheus 服务器指向端点并使用 Grafana 进行仪表板。有关更多详细信息,请参阅Metrics API 文档。
指标被记录到文件中。TorchServe 还支持其他类型的服务器日志记录,包括访问日志和 TorchServe 日志。访问日志记录推理请求以及完成请求所需的时间。根据properties文件的定义,访问日志被收集在*<log_location>/access_log.log*文件中。TorchServe 日志收集来自 TorchServe 及其后端工作人员的所有日志。
TorchServe 支持超出默认设置的指标和日志记录功能。指标和日志可以以许多不同的方式进行配置。此外,您可以创建自定义日志。有关 TorchServe 的指标和日志自定义以及其他高级功能的更多信息,请参阅TorchServe 文档。
注意
NVIDIA Triton 推理服务器变得越来越受欢迎,也用于在生产环境中规模部署 AI 模型。尽管不是 PyTorch 项目的一部分,但在部署到 NVIDIA GPU 时,您可能希望考虑 Triton 推理服务器作为 TorchServe 的替代方案。
Triton 推理服务器是开源软件,可以从本地存储、GCP 或 AWS S3 加载模型。Triton 支持在单个或多个 GPU 上运行多个模型,低延迟和共享内存,以及模型集成。Triton 相对于 TorchServe 的一些可能优势包括:
-
Triton 已经不再是测试版。
-
这是在 NVIDIA 硬件上进行推理的最快方式(常见)。
-
它可以使用
int4量化。 -
您可以直接从 PyTorch 转换而无需 ONNX。
作为 Docker 容器提供,Triton 推理服务器还与 Kubernetes 集成,用于编排、指标和自动扩展。有关更多信息,请访问NVIDIA Triton 推理服务器文档。
ONNX
如果您的平台不支持 PyTorch,并且无法在部署中使用 TorchScript/C++或 TorchServe,那么您的部署平台可能支持 Open Neural Network Exchange(ONNX)格式。ONNX 格式定义了一组通用操作符和通用文件格式,以便深度学习工程师可以在各种框架、工具、运行时和编译器之间使用模型。
ONNX 是由 Facebook 和 Microsoft 开发的,旨在允许 PyTorch 和其他框架(如 Caffe2 和 Microsoft 认知工具包(CTK))之间的模型互操作性。目前,ONNX 由多家供应商的推理运行时支持,包括 Cadence Systems、Habana、Intel AI、NVIDIA、Qualcomm、腾讯、Windows 和 Xilinx。
一个示例用例是在 Xilinx FPGA 设备上进行边缘部署。FPGA 设备是可以使用特定逻辑编程的定制芯片。它们被边缘设备用于低延迟或高性能应用,如视频。如果您想将您的新创新模型部署到 FPGA 设备上,您首先需要将其转换为 ONNX 格式,然后使用 Xilinx FPGA 开发工具生成带有您模型实现的 FPGA 图像。
让我们看一个如何将模型导出为 ONNX 的示例,再次使用我们的 VGG16 模型。ONNX 导出器可以使用追踪或脚本。我们在 TorchScript 的早期部分学习了关于追踪和脚本的内容。我们可以通过简单地提供模型和一个示例输入来使用追踪。以下代码显示了我们如何使用追踪将我们的 VGG16 模型导出为 ONNX:
model = vgg16(pretrained=True)
example_input = torch.rand(1, 3, 224, 224)
onnx_model = torch.onnx.export(model,
example_input,
"vgg16.onnx")
我们定义一个示例输入并调用torch.onnx.export()。生成的文件vgg16.onnx是一个包含我们导出的 VGG16 模型的网络结构和参数的二进制 protobuf 文件。
如果我们想要验证我们的模型是否正确转换为 ONNX,我们可以使用 ONNX 检查器,如下所示:
import onnx
model = onnx.load("vgg16.onnx")
onnx.checker.check_model(model)
onnx.helper.printable_graph(model.graph)
此代码使用 Python ONNX 库加载模型,运行检查器,并打印出模型的可读版本。在运行代码之前,您可能需要安装 ONNX 库,使用conda或pip。
要了解更多关于转换为 ONNX 或在 ONNX 运行时中运行的信息,请查看 PyTorch 网站上的ONNX 教程。
除了 TorchScript、TorchServe 和 ONNX 之外,还正在开发更多工具来支持 PyTorch 模型部署。让我们考虑一些用于将模型部署到移动平台的工具。
移动库
Android 和 iPhone 设备不断发展,并在其定制芯片组中添加对深度学习加速的本机支持。此外,由于需要减少延迟、保护隐私以及在应用程序中与深度学习模型无缝交互的增长需求,部署到移动设备变得更加复杂。这是因为移动运行时可能与开发人员使用的训练环境有显著不同,导致在移动部署过程中出现错误和挑战。
PyTorch Mobile 解决了这些挑战,并提供了一个从训练到移动部署的端到端工作流程。PyTorch Mobile 可用于 iOS、Android 和 Linux,并提供用于移动应用程序所需的预处理和集成任务的 API。基本工作流程如图 7-2 所示。
图 7-2. PyTorch 移动工作流程
您可以像通常在 PyTorch 中设计模型一样开始。然后,您可以对模型进行量化,以减少其复杂性,同时最小程度地降低性能。随后,您可以使用追踪或脚本转换为 TorchScript,并使用torch.utils优化模型以适用于移动设备。接下来,保存您的模型并使用适当的移动库进行部署。Android 使用 Maven PyTorch 库,iOS 使用 CocoPods 与 LibTorch pod。
警告
PyTorch Mobile 仍在开发中,可能会发生变化。
有关 PyTorch Mobile 的最新详细信息,请参考PyTorch Mobile 文档。
现在我们已经探讨了一些 PyTorch 工具,用于部署我们的模型,让我们看一些参考应用程序和代码,用于部署到云端和边缘设备。首先,我将向您展示如何使用 Flask 构建开发 Web 服务器。
部署到 Flask 应用程序
在部署到全面生产之前,您可能希望将模型部署到开发 Web 服务器。这使您能够将深度学习算法与其他系统集成,并快速构建原型以演示您的新模型。使用 Python 使用 Flask 构建开发服务器的最简单方法之一。
Flask 是一个用 Python 编写的简单微型 Web 框架。它被称为“微”框架,因为它不包括数据库抽象层、表单验证、上传处理、各种身份验证技术或其他可能由其他库提供的内容。我们不会在本书中深入讨论 Flask,但我会向您展示如何使用 Flask 在 Python 中部署您的模型。
我们还将公开一个 REST API,以便其他应用程序可以传入数据并接收预测。在以下示例中,我们将部署我们预训练的 VGG16 模型并对图像进行分类。首先,我们将定义我们的 API 端点、请求类型和响应类型。我们的 API 端点将位于*/predict*,接受 POST 请求(包括图像文件)。响应将以 JSON 格式返回,并包含来自 ImageNet 数据集的class_id和class_name。
让我们创建我们的主要 Flask 文件,称为app.py。首先我们将导入所需的包:
import io
import json
from torchvision import models
import torchvision.transforms as transforms
from PIL import Image
from flask import Flask, jsonify, request
我们将使用io将字节转换为图像,使用json处理 JSON 格式数据。我们将使用torchvision创建我们的 VGG16 模型,并将图像数据转换为适合我们模型的格式。最后,我们导入Flask、jsonnify和request来处理 API 请求和响应。
在创建我们的 Web 服务器之前,让我们定义一个get_prediction()函数,该函数读取图像数据,预处理它,将其传递到我们的模型,并返回图像类别:
import json
imagenet_class_index = json.load(
open("./imagenet_class_index.json"))
model = models.vgg16(pretrained=True)
image_transforms = transforms.Compose(
[transforms.Resize(255),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(
[0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])])
def get_prediction(image_bytes):
image = Image.open(io.BytesIO(image_bytes))
tensor = image_transforms(image)
outputs = model(tensor)
_, y = outputs.max(1)
predicted_idx = str(y.item())
return imagenet_class_index[predicted_idx]
由于我们的模型将返回一个表示类别的数字,我们需要一个查找表将此数字转换为类别名称。我们通过读取 JSON 转换文件创建一个名为imagenet_class_index的字典。然后,我们实例化我们的 VGG16 模型,并定义我们的图像转换,以预处理一个 PIL 图像,将其调整大小、中心裁剪、转换为张量并进行归一化。在将图像发送到我们的模型之前,这些步骤是必需的。
我们的get_prediction()函数基于接收到的字节创建一个 PIL 图像对象,并应用所需的图像转换以创建输入张量。接下来,我们执行前向传递(或模型推断),并找到具有最高概率的类别y。最后,我们使用输出类值查找类名。
现在我们有了预处理图像、通过我们的模型传递图像并返回预测类别的代码,我们可以创建我们的 Flask Web 服务器和端点,并部署我们的模型,如下所示的代码:
app = Flask(__name__)
@app.route('/predict', methods=['POST'])
def predict():
if request.method == 'POST':
file = request.files['file']
img_bytes = file.read()
class_id, class_name = \
get_prediction(image_bytes=img_bytes)
return jsonify({'class_id': class_id,
'class_name': class_name})
我们的 Web 服务器对象称为app。我们已经创建了它,但它还没有运行。我们将我们的端点设置为*/predict*,并配置它以处理 POST 请求。当 Web 服务器接收到 POST 请求时,它将执行predict()函数,读取图像,获取预测,并以 JSON 格式返回图像类别。
就是这样!现在我们只需要添加以下代码,以便在执行app.py时运行 Web 服务器:
if __name__ == '__main__':
app.run()
要测试我们的 Web 服务器,可以按照以下方式运行它:
>>> FLASK_ENV=development FLASK_APP=app.py flask run
我们可以使用一个简单的 Python 文件和requests库发送图像:
import requests
resp = requests.post(
"http://localhost:5000/predict",
files={"file": open('cat.jpg','rb')})
print(resp.json())
>>> {"class_id": "n02124075", "class_name": "Egyptian_cat"}
在这个例子中,我们在本地机器的端口 5000(localhost:5000)上运行一个 Web 服务器。您可能希望在 Google Colab 中运行开发 Web 服务器,以利用云 GPU。接下来我将向您展示如何做到这一点。
Colab Flask 应用程序
也许您一直在 Colab 中开发您的 PyTorch 模型,以利用其快速开发或其 GPU。Colab 提供了一个虚拟机(VM),它将其localhost路由到我们机器的本地主机。要将其暴露到公共 URL,我们可以使用一个名为ngrok的库。
首先在 Colab 中安装ngrok:
!pip install flask-ngrok
要使用ngrok运行我们的 Flask 应用程序,我们只需要添加两行代码,如下注释所示:
from flask_ngrok import run_with_ngrok # ①
@app.route("/")
def home():
return "<h1>Running Flask on Google Colab!</h1>"
app.run()
app = Flask(__name__)
run_with_ngrok(app) # ②
@app.route('/predict', methods=['POST'])
def predict():
if request.method == 'POST':
file = request.files['file']
img_bytes = file.read()
class_id, class_name = \
get_prediction(image_bytes=img_bytes)
return jsonify({'class_id': class_id,
'class_name': class_name})
app.run() # ③
①
导入ngrok库。
②
当应用程序运行时启动ngrok。
③
由于我们在 Colab 中运行,我们不需要检查main。
我已经省略了其他导入和get_prediction()函数,因为它们没有改变。现在您可以在 Colab 中运行开发 Web 服务器,以便更快地进行原型设计。ngrok库为在 Colab 中运行的服务器提供了安全的 URL;当运行 Flask 应用程序时,您将在 Colab 笔记本输出中找到 URL。例如,以下输出显示 URL 为http://c0c97117ba27.ngrok.io:
* Serving Flask app "__main__" (lazy loading)
* Environment: production
WARNING: This is a development server.
Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Running on http://c0c97117ba27.ngrok.io
* Traffic stats available on http://127.0.0.1:4040
127.0.0.1 - - [08/Dec/2020 20:46:05] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [08/Dec/2020 20:46:05]
"GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [08/Dec/2020 20:46:06] "GET / HTTP/1.1" 200 -
再次,您可以发送带有图像的 POST 请求来测试 Web 服务器。您可以在本地或另一个 Colab 笔记本中运行以下代码:
import requests
resp = requests.post(
"http://c0c97117ba27.ngrok.io/predict",
files={"file": open('cat.jpg','rb')})
print(resp.json())
# out :
# {"class_id": "n02124075",
# "class_name": "Egyptian_cat"}
请注意 URL 已更改。在 Flask 应用程序中部署您的模型是快速测试和使用 REST API 的get_prediction()函数的好方法。但是,在这里我们的 Flask 应用程序用作开发 Web 服务器,而不是用于生产部署。在大规模部署模型时,您将需要解决模型管理、A/B 测试、监控、日志记录和其他任务等问题,以确保您的模型服务器正常工作。要在大规模生产环境中部署,我们将使用 TorchServe。
使用 TorchServe 部署到云端
在此示例中,我们将将 VGG16 图像分类器部署到生产环境。假设我们的公司制作了一个软件工具,将根据图像中出现的对象对零售产品图像集进行分类。该公司正在迅速发展,现在支持数百万家每天使用该工具的小型企业。
作为机器学习工程团队的一部分,您需要将模型部署到生产环境,并提供一个简单的 REST API,软件工具将使用该 API 对其图像进行分类。因为我们希望尽快部署某些东西,所以我们将在 AWS EC2 实例中使用 Docker 容器。
使用 Docker 快速入门
TorchServe 提供了脚本,可以基于各种平台和选项创建 Docker 镜像。运行 Docker 容器可以消除重新安装运行 TorchServe 所需的所有依赖项的需要。此外,我们可以通过使用 Kubernetes 旋转多个 Docker 容器来扩展我们的模型推理。首先,我们必须根据我们在 EC2 实例上拥有的资源创建 Docker 镜像。
第一步是克隆 TorchServe 存储库并导航到Docker文件夹,使用以下命令:
$ git clone https://github.com/pytorch/serve.git
cd serve/docker
接下来,我们需要将 VGG16 模型归档添加到 Docker 镜像中。我们通过向下载存档模型文件并将其保存在*/home/model-server/*目录中的 Dockerfile 添加以下行来实现这一点:
$ curl -o /home/model-server/vgg16.pth \
https://download.pytorch.org/models/vgg16.pth
现在我们可以运行build_image.sh脚本,创建一个安装了公共二进制文件的 Docker 镜像。由于我们在带有 GPU 的 EC2 实例上运行,我们将使用-g标志,如下所示:
$ ./build_image.sh -g
您可以运行**./build_image.sh -h**查看其他选项。
一旦我们创建了 Docker 镜像,我们可以使用以下命令运行容器:
$ docker run --rm -it --gpus '"device=1"' \
-p 8080:8080 -p 8081:8081 -p 8082:8082 \
-p 7070:7070 -p 7071:7071 \
pytorch/torchserve:latest-gpu
这个命令将启动容器,将 8080/81/82 和 7070/71 端口暴露给外部世界的本地主机。它使用一个带有最新 CUDA 版本的 GPU。
现在我们的 TorchServe Docker 容器正在运行。我们公司的软件工具可以通过将图像文件发送到ourip.com/predict来发送推理请求,并可以通过 JSON 接收图像分类。
有关在 Docker 中运行 TorchServe 的更多详细信息,请参阅TorchServe Docker 文档。要了解有关 TorchServe 的更多信息,请访问TorchServe 存储库。
现在,您可以使用 Flask 进行开发或使用 TorchServe 进行生产,将模型部署到本地计算机和云服务器。这对于原型设计和通过 REST API 与其他应用程序集成非常有用。接下来,您将扩展部署能力,将模型部署到云之外:在下一节中,我们将探讨如何将模型部署到移动设备和其他边缘设备。
部署到移动和边缘
边缘设备通常是与用户或环境直接交互并在设备上直接运行机器学习计算的(通常是小型)硬件系统,而不是在云中的集中服务器上运行。一些边缘设备的例子包括手机和平板电脑,智能手表和心率监测器等可穿戴设备,以及工业传感器和家用恒温器等其他物联网设备。有一个越来越大的需求在边缘设备上运行深度学习算法,以保护隐私,减少数据传输,最小化延迟,并支持实时的新交互式用例。
首先我们将探讨如何在 iOS 和 Android 移动设备上部署 PyTorch 模型,然后我们将涵盖其他边缘设备。PyTorch 对边缘部署的支持有限但在不断增长。这些部分将提供一些参考代码,帮助您开始使用 PyTorch Mobile。
iOS
根据苹果公司的数据,截至 2021 年 1 月,全球有超过 16.5 亿活跃的 iOS 设备。随着每个新模型和定制处理单元的推出,对机器学习硬件加速的支持不断增长。学习如何将 PyTorch 模型部署到 iOS 为您打开了许多机会,可以基于深度学习创建 iOS 应用程序。
要将模型部署到 iOS 设备,您需要学习如何使用 Xcode 等开发工具创建 iOS 应用程序。我们不会在本书中涵盖 iOS 开发,但您可以在PyTorch iOS 示例应用 GitHub 存储库中找到“Hello, World”程序和示例代码,以帮助您构建您的应用程序。
让我们描述将我们的 VGG16 网络部署到 iOS 应用程序的工作流程。iOS 将使用 PyTorch C++ API 与我们的模型进行接口,因此我们需要首先将我们的模型转换并保存为 TorchScript。然后我们将在 Objective-C 中包装 C++函数,以便 iOS Swift 代码可以访问 API。我们将使用 Swift 加载和预处理图像,然后将图像数据传入我们的模型以预测其类别。
首先我们将使用追踪将我们的 VGG16 模型转换为 TorchScript 并保存为model.pt,如下面的代码所示:
import torch
import torchvision
from torch.utils.mobile_optimizer \ import optimize_for_mobile
model = torchvision.models.vgg16(pretrained=True)
model.eval()
example = torch.rand(1, 3, 224, 224) # ①
traced_script_module = \
torch.jit.trace(model, example) # ②
torchscript_model_optimized = \
optimize_for_mobile(traced_script_module) # ③
torchscript_model_optimized.save("model.pt") # ④
①
使用随机数据定义example。
②
将model转换为 TorchScript。
③
优化代码的新步骤。
④
保存模型。
如前所述,使用追踪需要定义一个示例输入,我们使用随机数据来做到这一点。然后我们使用torch.jit.trace()将模型转换为 TorchScript。然后我们添加一个新步骤,使用torch.utils.mobile_optimizer包为移动平台优化 TorchScript 代码。最后,我们将模型保存到名为model.pt的文件中。
现在我们需要编写我们的 Swift iOS 应用程序。我们的 iOS 应用程序将使用 PyTorch C++库,我们可以通过 CocoaPods 安装如下:
$ pod install
然后我们需要编写一些 Swift 代码来加载一个示例图像。您可以在将来通过访问设备上的相机或照片来改进这一点,但现在我们将保持简单:
let image = UIImage(named: "image.jpg")! \
imageView.image = image
let resizedImage = image.resized(
to: CGSize(width: 224, height: 224))
guard var pixelBuffer = resizedImage.normalized()
else return
在这里,我们将图像调整大小为 224×224 像素,并运行一个函数来规范化图像数据。
接下来,我们将加载并实例化我们的模型到我们的 iOS 应用程序中,如下面的代码所示:
private lazy var module: TorchModule = {
if let filePath = Bundle.main.path(
forResource: "model", ofType: "pt"),
let module = TorchModule(
fileAtPath: filePath) {
return module
} else {
fatalError("Can't find the model file!")
}
}()
iOS 是用 Swift 编写的,Swift 无法与 C++进行接口,因此我们需要使用一个 Objective-C 类TorchModule作为torch::jit::script::Module的包装器。
现在我们的模型已加载,我们可以通过将预处理的图像数据传入我们的模型并运行预测来预测图像的类别,如下面的代码所示:
guard let outputs = module.predict(image:
UnsafeMutableRawPointer(&pixelBuffer))
else {
return
}
在内部,predict() Objective-C 包装器调用 C++ forward()函数如下:
at::Tensor tensor = torch::from_blob(
imageBuffer, {1, 3, 224, 224}, at::kFloat);
torch::autograd::AutoGradMode guard(false);
auto outputTensor = _impl.forward(
{tensor}).toTensor();
float* floatBuffer =
outputTensor.data_ptr<float>();
当您运行示例应用程序时,您应该看到类似于图 7-3 的输出,用于示例图像文件。
这个图像分类示例只是对为 iOS 设备编码能力的一个小表示。对于更高级的用例,您仍然可以遵循相同的流程:转换并保存为 TorchScript,创建一个 Objective-C 包装器,预处理输入,并调用您的predict()函数。接下来,我们将为部署 PyTorch 到 Android 移动设备遵循类似的流程。
图 7-3. iOS 示例
Android
Android 移动设备在全球范围内也被广泛使用,据估计,2021 年初移动设备的市场份额超过 70%。这意味着也有巨大的机会将 PyTorch 模型部署到 Android 设备上。
Android 使用 PyTorch Android API,您需要安装 Android 开发工具来构建示例应用程序。使用 Android Studio,您将能够安装 Android 本机开发工具包(NDK)和软件开发工具包(SDK)。我们不会在本书中涵盖 Android 开发,但您可以在PyTorch Android 示例 GitHub 存储库中找到“Hello, World”程序和示例代码,以帮助您构建您的应用程序。
在 Android 设备上部署 PyTorch 模型的工作流程与我们用于 iOS 的过程非常相似。我们仍然需要将我们的模型转换为 TorchScript 以便与 PyTorch Android API 一起使用。然而,由于 API 本身支持加载和运行我们的 TorchScript 模型,我们无需像在 iOS 中那样将其包装在 C++代码中。相反,我们将使用 Java 编写一个 Android 应用程序,该应用程序加载和预处理图像文件,将其传递给我们的模型进行推理,并返回结果。
让我们将 VGG16 模型部署到 Android。首先,我们将模型转换为 TorchScript,就像我们为 iOS 所做的那样,如下面的代码所示:
import torch
import torchvision
from torch.utils.mobile_optimizer \
import optimize_for_mobile
model = torchvision.models.vgg16(pretrained=True)
model.eval()
example = torch.rand(1, 3, 224, 224)
traced_script_module = \
torch.jit.trace(model, example)
torchscript_model_optimized = \
optimize_for_mobile(traced_script_module)
torchscript_model_optimized.save("model.pt")
我们使用torch.jit.trace()进行跟踪将模型转换为 TorchScript。然后,我们添加一个新步骤,使用torch.utils.mobile_optimizer包为移动平台优化 TorchScript 代码。最后,我们将模型保存到名为model.pt的文件中。
接下来,我们使用 Java 创建我们的 Android 应用程序。我们通过将以下代码添加到build.gradle将 PyTorch Android API 添加到我们的应用程序作为 Gradle 依赖项:
repositories {
jcenter()
}
dependencies {
implementation
'org.pytorch:pytorch_android:1.4.0'
implementation
'org.pytorch:pytorch_android_torchvision:1.4.0'
}
接下来,我们编写我们的 Android 应用程序。我们首先加载图像并使用以下代码对其进行预处理:
Bitmap bitmap = \
BitmapFactory.decodeStream(
getAssets().open("image.jpg"));
Tensor inputTensor = \
TensorImageUtils.bitmapToFloat32Tensor(
bitmap,
TensorImageUtils.TORCHVISION_NORM_MEAN_RGB,
TensorImageUtils.TORCHVISION_NORM_STD_RGB);
现在我们有了我们的图像,我们可以预测它的类别,但首先我们必须加载我们的模型,如下所示:
Module module = Module.load(
assetFilePath(this, "model.pt"));
然后我们可以运行推理来预测图像的类别,并使用以下代码处理结果:
Tensor outputTensor = module.forward(
IValue.from(inputTensor)).toTensor();
float[] scores = \
outputTensor.getDataAsFloatArray();
float maxScore = -Float.MAX_VALUE;
int maxScoreIdx = -1;
for (int i = 0; i < scores.length; i++) {
if (scores[i] > maxScore) {
maxScore = scores[i];
maxScoreIdx = i;
}
}
String className = \
ImageNetClasses.IMAGENET_CLASSES[maxScoreIdx];
这个工作流程可以用于更高级的用例。您可以使用设备上的相机或照片或其他 Android 传感器来创建更复杂的应用程序。有关更多 PyTorch Android 演示应用程序,请访问PyTorch Android 演示应用程序 GitHub 存储库。
其他边缘设备
运行 iOS 或 Android 的移动设备代表一种边缘设备,但还有许多可以执行深度学习算法的设备。边缘设备通常使用定制硬件构建用于特定应用。其他边缘设备的示例包括传感器、视频设备、医疗监视器、软件定义无线电、恒温器、农业机械和制造传感器以检测缺陷。
大多数边缘设备包括计算机处理器、GPU、FPGA 或其他定制 ASIC 计算机芯片,能够运行深度学习模型。那么,如何将 PyTorch 模型部署到这些边缘设备呢?这取决于设备上使用了哪些处理组件。让我们探讨一些常用芯片的想法:
CPU
如果您的边缘设备使用 CPU,如英特尔或 AMD 处理器,PyTorch 可以在 Python 和 C++中使用 TorchScript 和 C++前端 API 部署。移动和边缘 CPU 芯片组通常经过优化以最小化功耗,并且边缘设备上的内存可能更有限。在部署之前通过修剪或量化优化您的模型以最小化运行推理所需的功耗和内存可能是值得的。
ARMs
ARM 处理器是一类具有简化指令集的计算机处理器。它们通常以比英特尔或 AMD CPU 更低的功耗和时钟速度运行,并可以包含在片上系统(SoCs)中。除了处理器,SoCs 芯片通常还包括其他电子设备,如可编程 FPGA 逻辑或 GPU。目前正在开发在 ARM 设备上运行 PyTorch 的 Linux。
微控制器
微控制器是通常用于非常简单控制任务的非常有限的处理器。一些流行的微控制器包括 Arduino 和 Beaglebone 处理器。由于可用资源有限,对微控制器的支持有限。
GPUs
边缘设备可能包括 GPU 芯片。NVIDIA GPU 是最广泛支持的 GPU,但其他公司(如 AMD 和英特尔)也制造 GPU 芯片。NVIDIA 在其 GPU 开发套件中支持 PyTorch,包括其 Jetson Nano、Xavier 和 NX 板。
FPGAs
PyTorch 模型可以部署到许多 FPGA 设备,包括赛灵思(最近被 AMD 收购)和英特尔 FPGA 设备系列。这两个平台都不支持直接的 PyTorch 部署;但是它们支持 ONNX 格式。典型的方法是将 PyTorch 模型转换为 ONNX,并使用 FPGA 开发工具从 ONNX 模型创建 FPGA 逻辑。
TPUs
谷歌的 TPU 芯片也正在部署到边缘设备上。PyTorch 通过 XLA 库支持,如“在 TPU 上的 PyTorch”中所述。将模型部署到使用 TPU 的边缘设备可以使您使用 XLA 库进行推理。
ASICs
许多公司正在开发自己的定制芯片或 ASIC,以高度优化和高效的方式实现模型设计。部署 PyTorch 模型的能力将严重依赖于定制 ASIC 芯片设计和开发工具所支持的功能。在某些情况下,如果 ASIC 支持,您可以使用 PyTorch/XLA 库。
当部署 PyTorch 模型到边缘设备时,请考虑系统上可用的处理组件。根据可用的芯片,研究利用 C++前端 API、利用 TorchScript、将模型转换为 ONNX 格式,或访问 PyTorch XLA 库以部署模型的选项。
在本章中,您学习了如何使用标准的 Python API、TorchScript/C++、TorchServe、ONNX 和 PyTorch 移动库来部署您的模型进行推理。本章还提供了参考代码,以在本地开发服务器或云中的生产环境中使用 Flask 和 TorchServe,以及在 iOS 和 Android 设备上部署 PyTorch 模型。
PyTorch 支持一个庞大、活跃的有用工具生态系统,用于模型开发和部署。我们将在下一章中探讨这个生态系统,该章还提供了一些最受欢迎的 PyTorch 工具的参考代码。
第八章:PyTorch 生态系统和其他资源
在之前的章节中,您已经学会了使用 PyTorch 设计和部署深度学习模型所需的一切。您已经学会了如何在不同平台上构建、训练、测试和加速您的模型,以及如何将这些模型部署到云端和边缘设备。正如您所见,PyTorch 在开发和部署环境中都具有强大的功能,并且高度可扩展,允许您创建符合您需求的定制化。
为了总结这个参考指南,我们将探索 PyTorch 生态系统、其他支持库和额外资源。PyTorch 生态系统是 PyTorch 最强大的优势之一。它提供了丰富的项目、工具、模型、库和平台,用于探索人工智能并加速您的人工智能开发。
PyTorch 生态系统包括由研究人员、第三方供应商和 PyTorch 社区创建的项目和库。这些项目得到了 PyTorch 团队的认可,以确保它们的质量和实用性。
此外,PyTorch 项目还包括支持特定领域的其他库,包括用于计算机视觉的 Torchvision 和用于 NLP 的 Torchtext。PyTorch 还支持其他包,如 TensorBoard 用于可视化,还有大量的学习资源供进一步研究,如 Papers with Code 和 PyTorch Academy。
在本章中,我们将首先概述 PyTorch 生态系统及其支持的项目和工具的高级视图。然后,我们将深入了解一些最强大和流行的资源,提供关于它们的使用和 API 的参考资料。最后,我将向您展示如何通过各种教程、书籍、课程和其他培训资源进一步学习。
让我们开始看看生态系统提供了什么。
PyTorch 生态系统
截至 2021 年初,PyTorch 生态系统拥有超过 50 个库和项目,这个列表还在不断增长。其中一些是特定领域的项目,例如专门用于计算机视觉或 NLP 解决方案的项目。其他项目,如 PyTorch Lightning 和 fastai,提供了编写简洁代码的框架,而像 PySyft 和 Crypten 这样的项目支持安全性和隐私性。还有支持强化学习、游戏模型、模型可解释性和加速的项目。在本节中,我们将探索包含在 PyTorch 生态系统中的项目。
表 8-1 提供了支持计算机视觉应用的生态系统项目列表。
表 8-1. 计算机视觉项目
| 项目 | 描述 |
|---|---|
| Torchvision | PyTorch 的计算机视觉库,提供常见的转换、模型和实用程序,以支持计算机视觉应用(https://pytorch.tips/torchvision) |
| Detectron2 | Facebook 的目标检测和分割平台(https://pytorch.tips/detectron2) |
| Albumentations | 图像增强库(https://pytorch.tips/albumentations) |
| PyTorch3D | 用于 3D 计算机视觉的可重用组件集合(https://pytorch.tips/pytorch3d) |
| Kornia | 用于计算机视觉的可微分模块库(https://pytorch.tips/kornia) |
| MONAI | 用于医疗影像深度学习的框架(https://pytorch.tips/monai) |
| TorchIO | 用于 3D 医学图像的工具包(https://pytorch.tips/torchio) |
Torchvision 是计算机视觉应用中最强大的库之一,包含在 PyTorch 项目中。它也由 PyTorch 开发团队维护。我们将在本章后面更详细地介绍 Torchvision API。
PyTorch3D 和 TorchIO 为 3D 成像提供了额外支持,而 TorchIO 和 MONAI 专注于医学成像应用。Detectron2 是一个强大的物体检测平台。如果您正在进行计算机视觉研究和开发,这些扩展可能有助于加速您的结果。
与计算机视觉一样,过去十年来在 NLP 研究中取得了重大进展,NLP 应用也得到了 PyTorch 的良好支持。
表 8-2 提供了支持NLP 和基于音频应用的生态系统项目列表。
表 8-2. NLP 和音频项目
| 项目 | 描述 |
|---|---|
| Torchtext | PyTorch 的自然语言处理和文本处理库(https://pytorch.tips/torchtext) |
| Flair | NLP 的简单框架(https://pytorch.tips/flair) |
| AllenNLP | 用于设计和评估 NLP 模型的库(https://pytorch.tips/allennlp) |
| ParlAI | 用于共享、训练和测试对话模型的框架(https://pytorch.tips/parlai) |
| NeMo | 用于会话 AI 的工具包(https://pytorch.tips/nemo) |
| PyTorch NLP | NLP 的基本工具(https://pytorch.tips/pytorchnlp) |
| Translate | Facebook 的机器翻译平台(https://pytorch.tips/translate) |
| TorchAudio | PyTorch 的音频预处理库(https://pytorch.tips/torchaudio) |
与 Torchvision 一样,Torchtext 作为 PyTorch 项目的一部分包含在内,并由 PyTorch 开发团队维护。Torchtext 为处理文本数据和开发基于 NLP 的模型提供了强大的功能。
Flair、AllenNLP 和 PyTorch NLP 为基于文本的处理和 NLP 模型开发提供了额外功能。ParlAI 和 NeMo 提供了开发对话和会话 AI 系统的工具,而 Translate 专注于机器翻译。
TorchAudio 提供处理音频文件(如语音和音乐)的功能。
强化学习和游戏也是研究的快速增长领域,有工具支持它们使用 PyTorch。
表 8-3 提供了支持游戏和强化学习应用的生态系统项目列表。
表 8-3. 游戏和强化学习项目
| 项目 | 描述 |
|---|---|
| ELF | 用于在游戏环境中训练和测试算法的项目(https://pytorch.tips/elf) |
| PFRL | 深度强化学习算法库(https://pytorch.tips/pfrl) |
ELF(广泛、轻量级、灵活的游戏研究平台)是 Facebook 开发的开源项目,重新实现了像 AlphaGoZero 和 AlphaZero 这样的游戏算法。PFRL(首选强化学习)是由 Preferred Networks 开发的基于 PyTorch 的开源深度强化学习库,是 Chainer 和 ChainerRL 的创造者。它可以用来创建强化学习的基线算法。PFRL 目前为 11 个基于原始研究论文的关键深度强化学习算法提供了可重现性脚本。
正如您在本书中所看到的,PyTorch 是一个高度可定制的框架。这种特性有时会导致需要为常见任务经常编写相同的样板代码。为了帮助开发人员更快地编写代码并消除样板代码的需要,几个 PyTorch 项目提供了高级编程 API 或与其他高级框架(如 scikit-learn)的兼容性。
表 8-4 提供了支持高级编程的生态系统项目列表。
表 8-4. 高级编程项目
| 项目 | 描述 |
|---|---|
| fastai | 简化使用现代实践进行训练的库(https://pytorch.tips/fastai) |
| PyTorch Lightning | 可定制的类 Keras ML 库,消除样板代码(https://pytorch.tips/lightning) |
| Ignite | 用于编写紧凑、功能齐全的训练循环的库(https://pytorch.tips/ignite) |
| Catalyst | 用于紧凑强化学习流水线的框架(https://pytorch.tips/catalyst) |
| skorch | 提供与 scikit-learn 兼容的 PyTorch(https://pytorch.tips/skorch) |
| Hydra | 用于配置复杂应用程序的框架(https://pytorch.tips/hydra) |
| higher | 促进复杂元学习算法实现的库(https://pytorch.tips/higher) |
| Poutyne | 用于样板代码的类 Keras 框架(https://pytorch.tips/poutyne) |
Fastai 是建立在 PyTorch 上的研究和学习框架。它有全面的文档,并自早期提供了 PyTorch 的高级 API。您可以通过查阅其文档和免费的在线课程或阅读 Jeremy Howard 和 Sylvain Gugger(O'Reilly)合著的书籍使用 fastai 和 PyTorch 进行编码的深度学习来快速掌握该框架。
PyTorch Lightning 也已成为 PyTorch 非常受欢迎的高级编程 API 之一。它为训练、验证和测试循环提供了所有必要的样板代码,同时允许您轻松添加自定义方法。
Ignite 和 Catalyst 也是流行的高级框架,而 skorch 和 Poutyne 分别提供了类似于 scikit-learn 和 Keras 的接口。Hydra 和 higher 用于简化复杂应用程序的配置。
除了高级框架外,生态系统中还有支持硬件加速和优化推理的软件包。
表 8-5 提供了支持推理加速应用程序的生态系统项目列表。
表 8-5。推理项目
| 项目 | 描述 |
|---|---|
| Glow | 用于硬件加速的 ML 编译器(https://pytorch.tips/glow) |
| Hummingbird | 编译经过训练的模型以实现更快推理的库(https://pytorch.tips/hummingbird) |
Glow 是用于硬件加速器的机器学习编译器和执行引擎,可以用作高级深度学习框架的后端。该编译器允许进行最先进的优化和神经网络图的代码生成。Hummingbird 是由微软开发的开源项目,是一个库,用于将经过训练的传统 ML 模型编译为张量计算,并无缝地利用 PyTorch 加速传统 ML 模型。
除了加速推理外,PyTorch 生态系统还包含用于加速训练和使用分布式训练优化模型的项目。
表 8-6 提供了支持分布式训练和模型优化的生态系统项目列表。
表 8-6。分布式训练和模型优化项目
| 项目 | 描述 |
|---|---|
| Ray | 用于构建和运行分布式应用程序的快速、简单框架(https://pytorch.tips/ray) |
| Horovod | 用于 TensorFlow、Keras、PyTorch 和 Apache MXNet 的分布式深度学习训练框架(https://pytorch.tips/horovod) |
| DeepSpeed | 优化库(https://pytorch.tips/deepspeed) |
| Optuna | 自动化超参数搜索和优化(https://pytorch.tips/optuna) |
| Polyaxon | 用于构建、训练和监控大规模深度学习应用程序的平台(https://pytorch.tips/polyaxon) |
| Determined | 使用共享 GPU 和协作训练模型的平台(https://pytorch.tips/determined) |
| Allegro Trains | 包含深度学习实验管理器、版本控制和机器学习操作的库(https://pytorch.tips/allegro) |
Ray 是一个用于构建分布式应用程序的 Python API,并打包了其他库以加速机器学习工作负载。我们在第六章中使用了其中一个软件包 Ray Tune 来在分布式系统上调整超参数。Ray 是一个非常强大的软件包,还可以支持可扩展的强化学习、分布式训练和可扩展的服务。Horovod 是另一个分布式框架。它专注于分布式训练,并可与 Ray 一起使用。
DeepSpeed、Optuna 和 Allegro Trains 还支持超参数调优和模型优化。Polyaxon 可用于规模化训练和监控模型,而 Determined 专注于共享 GPU 以加速训练。
随着 PyTorch 的流行,已经开发了许多专门的软件包来支持特定领域和特定工具。这些工具中的许多旨在改进模型或数据的预处理。
表 8-7 提供了支持建模和数据处理的生态系统项目列表。
表 8-7. 建模和数据处理项目
| 项目 | 描述 |
|---|---|
| TensorBoard | TensorBoard 的数据和模型可视化工具已集成到 PyTorch 中(https://pytorch.tips/pytorch-tensorboard) |
| PyTorch Geometric | 用于 PyTorch 的几何深度学习扩展库(https://pytorch.tips/geometric) |
| Pyro | 灵活且可扩展的深度概率建模(https://pytorch.tips/pyro) |
| Deep Graph Library (DGL) | 用于实现图神经网络的库(https://pytorch.tips/dgl) |
| MMF | Facebook 的多模型深度学习(视觉和语言)模块化框架(https://pytorch.tips/mmf) |
| GPyTorch | 用于创建可扩展高斯过程模型的库(https://pytorch.tips/gpytorch) |
| BoTorch | 用于贝叶斯优化的库(https://pytorch.tips/botorch) |
| Torch Points 3D | 用于非结构化 3D 空间数据的框架(https://pytorch.tips/torchpoints3d) |
| TensorLy | 用于张量方法和深度张量神经网络的高级 API(https://pytorch.tips/tensorly)(https://pytorch.tips/advertorch) |
| BaaL | 从贝叶斯理论中实现主动学习(https://pytorch.tips/baal) |
| PennyLane | 量子机器学习库(https://pytorch.tips/pennylane) |
TensorBoard 是为 TensorFlow 开发的非常流行的可视化工具,也可以用于 PyTorch。我们将在本章后面介绍这个工具及其 PyTorch API。
PyTorch Geometric、Pyro、GPyTorch、BoTorch 和 BaaL 都支持不同类型的建模,如几何建模、概率建模、高斯建模和贝叶斯优化。
Facebook 的 MMF 是一个功能丰富的多模态建模软件包,而 Torch Points 3D 可用于对通用的 3D 空间数据进行建模。
PyTorch 作为一个工具的成熟和稳定性体现在用于支持安全和隐私的软件包的出现。随着法规要求系统在这些领域合规,安全和隐私问题变得更加重要。
表 8-8 提供了支持安全性和隐私性的生态系统项目列表。
表 8-8. 安全和隐私项目
| 项目 | 描述 |
|---|---|
| AdverTorch | 用于对抗性示例和防御攻击的模块 |
| PySyft | 用于模型加密和隐私的库(https://pytorch.tips/pysyft) |
| Opacus | 用于训练具有差分隐私的模型的库(https://pytorch.tips/opacus) |
| CrypTen | 隐私保护 ML 的框架(https://pytorch.tips/crypten) |
PySyft、Opacus 和 CrypTen 是支持安全性和隐私性的 PyTorch 包。它们添加了保护和加密模型以及用于创建模型的数据的功能。
通常,深度学习似乎是一个黑匣子,开发人员不知道模型为什么做出决策。然而,如今,这种缺乏透明度已不再可接受:人们越来越意识到公司及其高管必须对其算法的公平性和运作负责。模型可解释性对于研究人员、开发人员和公司高管来说很重要,以了解模型为何产生其结果。
表 8-9 显示了支持模型 可解释性的生态系统项目。
表 8-9. 模型可解释性项目
| 项目 | 描述 |
|---|---|
| Captum | 用于模型可解释性的库(https://pytorch.tips/captum) |
| 视觉归因 | 用于模型可解释性的最新视觉归因方法的 PyTorch 实现(https://pytorch.tips/visual-attribution) |
目前,Captum 是支持模型可解释性的首要 PyTorch 项目。视觉归因包对解释计算机视觉模型和识别图像显著性很有用。随着领域的扩展,更多的项目肯定会进入这个领域。
正如您所看到的,PyTorch 生态系统包括广泛的开源项目,可以在许多不同的方面帮助您。也许您正在开展一个可以使其他研究人员受益的项目。如果您希望将您的项目纳入官方 PyTorch 生态系统,请访问PyTorch 生态系统申请页面。
在考虑应用程序时,PyTorch 团队寻找符合以下要求的项目:
-
您的项目使用 PyTorch 来改善用户体验、添加新功能或加快训练/推理速度。
-
您的项目稳定、维护良好,并包含足够的基础设施、文档和技术支持。
生态系统不断增长。要获取最新的项目列表,请访问PyTorch 生态系统网站。要向我们更新书中的新项目,请发送电子邮件至作者邮箱 jpapa@joepapa.ai。
接下来,我们将更深入地了解一些 PyTorch 项目的支持工具和库。显然,我们无法在本书中涵盖所有可用的库和工具,但在接下来的章节中,我们将探索一些最受欢迎和有用的库,以帮助您更深入地了解它们的 API 和用法。
Torchvision 用于图像和视频
我们在本书中使用了 Torchvision,它是计算机视觉研究中最强大和有用的 PyTorch 库之一。从技术上讲,Torchvision 包是 PyTorch 项目的一部分。它包括一系列流行的数据集、模型架构和常见的图像转换。
数据集和 I/O
Torchvision 提供了大量的数据集。它们包含在torchvision.datasets库中,可以通过创建数据集对象来访问,如下面的代码所示:
import torchvision
train_data = torchvision.datasets.CIFAR10(
root=".",
train=True,
transform=None,
download=True)
您只需调用构造函数并传入适当的选项。此代码使用训练数据从 CIFAR-10 数据集创建数据集对象,不使用任何转换。它会在当前目录中查找数据集文件,如果文件不存在,它将下载它们。
表 8-10 提供了 Torchvision 提供的数据集的全面列表。
表 8-10。Torchvision 数据集
| 数据集 | 描述 |
|---|---|
| CelebA | 大规模人脸属性数据集,包含超过 200,000 张名人图像,每张图像有 40 个属性注释。 |
| CIFAR-10 | CIFAR-10 数据集包含 60,000 个 32×32 彩色图像,分为 10 个类别,分为 50,000 个训练图像和 10,000 个测试图像。还提供了包含 100 个类别的 CIFAR-100 数据集。 |
| Cityscapes | 包含来自 50 个不同城市街景记录的视频序列的大规模数据集,带有注释。 |
| COCO | 大规模目标检测、分割和字幕数据集。 |
| DatasetFolder | 用于从文件夹结构中创建任何数据集。 |
| EMNIST | MNIST 的手写字母扩展。 |
| FakeData | 一个返回随机生成图像作为 PIL 图像的虚假数据集。 |
| Fashion-MNIST | Zalando 服装图像数据集,符合 MNIST 格式(60,000 个训练示例,10,000 个测试示例,28×28 灰度图像,10 个类别)。 |
| Flickr | Flickr 8,000 张图像数据集。 |
| HMDB51 | 大型人体运动视频序列数据库。 |
| ImageFolder | 用于从文件夹结构中创建图像数据集。 |
| ImageNet | 包含 14,197,122 张图像和 21,841 个单词短语的图像分类数据集。 |
| Kinetics-400 | 大规模动作识别视频数据集,包含 650,000 个持续 10 秒的视频剪辑,涵盖高达 700 个人类动作类别,如演奏乐器、握手和拥抱。 |
| KMNIST | Kuzushiji-MNIST,MNIST 数据集的替代品(70,000 个 28×28 灰度图像),其中每个字符代表平假名的 10 行之一。 |
| LSUN | 每个 10 个场景类别和 20 个对象类别的一百万标记图像。 |
| MNIST | 手写的单个数字,28×28 灰度图像,有 60,000 个训练和 10,000 个测试样本。 |
| Omniglot | 由 50 种不同字母表的 1,623 个不同手写字符生成的数据集。 |
| PhotoTour | 包含 1,024×1,024 位图图像的照片旅游数据集,每个图像包含一个 16×16 的图像块数组。 |
| Places365 | 包含 400 多个独特场景类别的 10,000,000 张图像数据集,每个类别有 5,000 至 30,000 张训练图像。 |
| QMNIST | Facebook 的项目,从 NIST 特殊数据库 19 中找到的原始数据生成 MNIST 数据集。 |
| SBD | 包含 11,355 张图像的语义分割注释的语义边界数据集。 |
| SBU | Stony Brook 大学(SBU)标题照片数据集,包含超过 1,000,000 张带标题的图像。 |
| STL10 | 用于无监督学习的类似于 CIFAR-10 的数据集。96×96 彩色图像的 10 个类别,包括 5,000 个训练图像,8,000 个测试图像和 100,000 个未标记图像。 |
| SVHN | 街景房屋号码数据集,类似于 MNIST,但是在自然场景彩色图像中有 10 倍的数据。 |
| UCF101 | 包含来自 101 个动作类别的 13,320 个视频的动作识别数据集。 |
| USPS | 包含 16×16 手写文本图像的数据集,有 10 个类别,7,291 个训练图像和 2,007 个测试图像。 |
| VOC | 用于目标类别识别的 PASCAL 视觉对象类别图像数据集。2012 年版本有 20 个类别,11,530 个训练/验证图像,27,450 个感兴趣区域(ROI)标注对象和 6,929 个分割。 |
Torchvision 不断添加更多数据集。要获取最新列表,请访问Torchvision 文档。
模型
Torchvision 还提供了一个广泛的模型列表,包括模块架构和预训练权重(如果有的话)。通过调用相应的构造函数,可以轻松创建模型对象,如下所示:
import torchvision
model = torchvision.models.vgg16(pretrained=False)
这段代码创建了一个带有随机权重的 VGG16 模型,因为没有使用预训练权重。通过使用类似的构造函数并设置适当的参数,可以实例化许多不同的计算机视觉模型。Torchvision 使用 PyTorch 的torch.utils.model_zoo提供预训练模型。可以通过传递pretrained=True来构建这些模型。
表 8-11 提供了 Torchvision 中包含的模型的全面列表,按类别分类。这些模型在研究界广为人知,表中包含了与每个模型相关的研究论文的参考文献。
表 8-11. Torchvision 模型
| 模型 | 论文 |
|---|---|
| 分类 | |
| AlexNet | “用于并行化卷积神经网络的一个奇怪技巧,” 作者:Alex Krizhevsky |
| VGG | “用于大规模图像识别的非常深度卷积网络,” 作者:Karen Simonyan 和 Andrew Zisserman |
| ResNet | “用于图像识别的深度残差学习,” 作者:Kaiming He 等 |
| SqueezeNet | “SqueezeNet: AlexNet 级别的准确性,参数减少 50 倍,模型大小<0.5MB,” 作者:Forrest N. Iandola 等 |
| DenseNet | “密集连接的卷积网络,” 作者:Gao Huang 等 |
| Inception v3 | “重新思考计算机视觉中的 Inception 架构,” 作者:Christian Szegedy 等 |
| GoogLeNet | “使用卷积深入研究,” 作者:Christian Szegedy 等 |
| ShuffleNet v2 | “ShuffleNet V2: 高效 CNN 架构设计的实用指南,” 作者:马宁宁等 |
| MobileNet v2 | “MobileNetV2: 反向残差和线性瓶颈,” 作者:Mark Sandler 等 |
| ResNeXt | “用于深度神经网络的聚合残差变换,” 作者:Saining Xie 等 |
| Wide ResNet | “宽残差网络,” 作者:Sergey Zagoruyko 和 Nikos Komodakis |
| MNASNet | “MnasNet: 面向移动设备的神经架构搜索,” 作者:Mingxing Tan 等 |
| 语义分割 | |
| FCN ResNet50 | “用于语义分割的全卷积网络,” 作者:Jonathan Long 等 |
| FCN ResNet101 | 参见上文 |
| DeepLabV3 ResNet50 | “重新思考空洞卷积用于语义图像分割,” 作者:Liang-Chieh Chen 等 |
| DeepLabV3 ResNet101 | 参见上文 |
| 目标检测 | |
| Faster R-CNN ResNet-50 | “FPNFaster R-CNN: 实时目标检测与区域建议网络,” 作者:Shaoqing Ren 等 |
| Mask R-CNN ResNet-50 FPN | “Mask R-CNN,” 作者:Kaiming He 等 |
| 视频分类 | |
| ResNet 3D 18 | “仔细研究时空卷积用于动作识别,” 作者:Du Tran 等 |
| ResNet MC 18 | 参见上文 |
| ResNet (2+1)D | 参见上文 |
Torchvision 还在不断添加新的计算机视觉模型。要获取最新列表,请访问Torchvision 文档。
变换、操作和实用程序
Torchvision 还提供了一套全面的变换、操作和实用程序集合,以帮助图像预处理和数据准备。应用变换的常见方法是形成一组变换的组合,并将这个transforms对象传递给数据集构造函数,如下面的代码所示:
from torchvision import transforms, datasets
train_transforms = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(
(0.4914, 0.4822, 0.4465),
(0.2023, 0.1994, 0.2010)),
])
train_data = datasets.CIFAR10(
root=".",
train=True,
transform=train_transforms)
在这里,我们创建了一个复合变换,使用ToTensor()将数据转换为张量,然后使用预定的均值和标准差对图像数据进行归一化。将transform参数设置为train_transforms对象会配置数据集在访问数据时应用一系列变换。
表 8-12 提供了torchvision.transforms中可用转换的完整列表。在本表和表 8-13 中以*斜体*显示的转换目前不受 TorchScript 支持。
表 8-12. Torchvision 转换
| 转换 | 描述 |
|---|---|
| 操作转换 | |
Compose() | 基于其他转换序列创建一个转换 |
CenterCrop(size) | 以给定大小在中心裁剪图像 |
ColorJitter(brightness=0, contrast=0, saturation=0, hue=0) | 随机改变图像的亮度、对比度、饱和度和色调 |
FiveCrop(size) | 将图像裁剪成四个角和中心裁剪 |
Grayscale(num_output_channels=1) | 将彩色图像转换为灰度图像 |
Pad(padding, fill=0, padding_mode=constant) | 使用给定值填充图像的边缘 |
RandomAffine(degrees, translate=None, scale=None, shear=None, resample=0, fillcolor=0) | 随机应用仿射变换 |
RandomApply(transforms, p=0.5) | 以给定概率随机应用一系列转换 |
RandomCrop(size, padding=None, pad_if_needed=False, fill=0, padding_mode=constant) | 在随机位置裁剪图像 |
RandomGrayscale(p=0.1) | 以给定概率随机将图像转换为灰度图像 |
RandomHorizontalFlip(p=0.5) | 以给定概率随机水平翻转图像 |
RandomPerspective(distortion_scale=0.5, p=0.5, interpolation=2, fill=0) | 应用随机透视变换 |
RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(0.75, 1.3333333333333333), interpolation=2) | 使用随机大小和长宽比调整图像 |
RandomRotation(degrees, resample=False, expand=False, center=None, fill=None) | 随机旋转图像 |
RandomVerticalFlip(p=0.5) | 以给定概率随机垂直翻转图像 |
Resize(size, interpolation=2) | 将图像调整为随机大小 |
TenCrop(size, vertical_flip=False) | 将图像裁剪成四个角和中心裁剪,并额外提供每个的翻转版本 |
GaussianBlur(kernel_size, sigma=(0.1, 2.0)) | 使用随机核应用高斯模糊 |
| 转换转换 | |
ToPILImage(mode=None) | 将张量或numpy.ndarray转换为 PIL 图像 |
ToTensor() | 将 PIL 图像或ndarray转换为张量 |
| 通用转换 | |
Lambda(lambda) | 将用户定义的lambda作为转换应用 |
大多数转换可以在张量或 PIL 格式的图像上进行操作,其形状为[..., C, H, W],其中...表示任意数量的前导维度。然而,一些转换只能在 PIL 图像或张量图像数据上操作。
在表 8-13 中列出的转换仅适用于 PIL 图像。这些转换目前不受 TorchScript 支持。
表 8-13. Torchvision 仅支持 PIL 的转换
| 转换 | 描述 |
|---|---|
RandomChoice(transforms) | 从列表中随机选择一个转换应用 |
RandomOrder(transforms) | 以随机顺序应用一系列转换 |
在表 8-14 中列出的转换仅适用于张量图像。
表 8-14. Torchvision 仅支持张量的转换
| 转换 | 描述 |
|---|---|
LinearTransformation(transformation_matrix, mean_vector) | 根据离线计算的方形变换矩阵和mean_vector对张量图像应用线性变换。 |
Normalize(mean, std, inplace=False) | 使用给定的均值和标准差对张量图像进行归一化。 |
RandomErasing(p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False) | 随机选择一个矩形区域并擦除其像素。 |
ConvertImageDtype(dtype: torch.dtype) | 将张量图像转换为新的数据类型,并自动缩放其值以匹配该类型 |
注意
在为 C++使用脚本转换时,请使用torch.nn.Sequential()而不是torchvision.transforms.Compose()。以下代码显示了一个示例:
>>> transforms = torch.nn.Sequential(
transforms.CenterCrop(10),
transforms.Normalize(
(0.485, 0.456, 0.406), (0.229, 0.224,
0.225)),
)
>>> scripted_transforms = torch.jit.script(transforms)
在前面的表中列出的许多转换包含用于指定参数的随机数生成器。例如,RandomResizedCrop()将图像裁剪为随机大小和长宽比。
Torchvision 还提供了功能性转换作为torchvision.transforms.functional包的一部分。您可以使用这些转换来执行具有您选择的特定参数集的转换。例如,您可以调用torchvision.transforms.functional.adjust_brightness()来调整一个或多个图像的亮度。
表 8-15 提供了支持的功能性转换列表。
表 8-15。Torchvision 功能性转换
| 功能性转换和实用程序 |
|---|
adjust_brightness(img: torch.Tensor, brightness_factor: float) |
adjust_contrast(img: torch.Tensor, contrast_factor: float) |
adjust_gamma(img: torch.Tensor, gamma: float, gain: float = 1) |
adjust_hue(img: torch.Tensor, hue_factor: float) → torch.Tensor |
adjust_saturation(img: torch.Tensor, saturation_factor: float) |
affine(img: torch.Tensor, angle: float, translate: List[int], scale: float, shear: List[float], resample: int = 0, fillcolor: Optional[int] = None) |
center_crop(img: torch.Tensor, output_size: List[int]) |
convert_image_dtype(image: torch.Tensor, dtype: torch.dtype = torch.float32) |
crop(img: torch.Tensor, top: int, left: int, height: int, width: int) |
erase(img: torch.Tensor, i: int, j: int, h: int, w: int, v: torch.Tensor, inplace: bool = False) |
five_crop(img: torch.Tensor, size: List[int]) |
gaussian_blur(img: torch.Tensor, kernel_size: List[int], sigma: Optional[List[float]] = None) |
hflip(img: torch.Tensor) |
normalize(tensor: torch.Tensor, mean: List[float], std: List[float], inplace: bool = False) |
pad(img: torch.Tensor, padding: List[int], fill: int = 0, padding_mode: str = constant) |
perspective(img: torch.Tensor, startpoints: List[List[int]], endpoints: List[List[int]], interpolation: int = 2, fill: Optional[int] = None) |
pil_to_tensor(pic) |
resize(img: torch.Tensor, size: List[int], interpolation: int = 2) |
resized_crop(img: torch.Tensor, top: int, left: int, height: int, width: int, size: List[int], interpolation: int = 2) |
rgb_to_grayscale(img: torch.Tensor, num_output_channels: int = 1) |
rotate(img: torch.Tensor, angle: float, resample: int = 0, expand: bool = False, center: Optional[List[int]] = None, fill: Optional[int] = None) |
ten_crop(img: torch.Tensor, size: List[int], vertical_flip: bool = False) |
to_grayscale(img, num_output_channels=1) |
to_pil_image(pic, mode=None) |
to_tensor(pic) |
vflip(img: torch.Tensor) |
utils.save_image(tensor: Union[torch.Tensor, List[torch.Tensor]], fp: Union[str, pathlib.Path, BinaryIO], nrow: int = 8, padding: int = 2, normalize: bool = False, range: Optional[Tuple[int, int]] = None, scale_each: bool = False, pad_value: int = 0, format: Optional[str] = None) |
utils.make_grid(tensor: Union[torch.Tensor, List[torch.Tensor]], nrow: int = 8, padding: int = 2, normalize: bool = False, range: Optional[Tuple[int, int]] = None, scale_each: bool = False, pad_value: int = 0) |
如上表所示,Torchvision 提供了一组强大的功能操作,可用于处理图像数据。每个操作都有自己的一组参数,用于强大的控制。
此外,Torchvision 提供了用于简化 I/O 和操作的函数。表 8-16 列出了其中一些函数。
表 8-16. Torchvision 的 I/O 和操作函数
| 函数 |
|---|
| 视频 |
io.read_video(filename: str, start_pts: int = 0, end_pts: Optional[float] = None, pts_unit: str = pts) |
io.read_video_timestamps9filename: str, pts_unit: str = pts) |
io.write_video9filename: str, video_array: torch.Tensor, _fps: float, video_codec: str = *libx264*, options: Optional[Dict[str, Any]] = None) |
| 细粒度视频 |
io.VideoReader(path, stream=video) |
| 图像 |
io.decode_image(input: torch.Tensor) |
io.encode_jpeg(input: torch.Tensor, quality: int = 75) |
io.read_image(path: str) |
io.write_jpeg(input: torch.Tensor, filename: str, quality: int = 75) |
io.encode_png(input: torch.Tensor, compression_level: int = 6) |
io.write_png(input: torch.Tensor, filename: str, compression_level: int = 6) |
上述函数是为了让您能够快速读取和写入多种格式的视频和图像文件。它们让您能够加快图像和视频处理的速度,而无需从头开始编写这些函数。
如您所见,Torchvision 是一个功能丰富、得到良好支持且成熟的 PyTorch 包。本节提供了 Torchvision API 的快速参考。在下一节中,我们将探索另一个用于 NLP 和文本应用的流行 PyTorch 包 Torchtext。
Torchtext 用于 NLP
Torchtext 包含一系列用于数据处理的实用工具和流行的 NLP 数据集。Torchtext API 与 Torchvision API 略有不同,但整体方法是相同的。
创建数据集对象
首先创建一个数据集,并描述一个预处理流水线,就像我们在 Torchvision 转换中所做的那样。Torchtext 提供了一组知名数据集。例如,我们可以加载 IMDb 数据集,如下面的代码所示:
from torchtext.datasets import IMDB
train_iter, test_iter = \
IMDB(split=('train', 'test'))
next(train_iter)
# out:
# ('neg',
# 'I rented I AM CURIOUS-YELLOW ...)
我们自动创建一个迭代器,并可以使用next()访问数据。
警告
Torchtext 在 PyTorch 1.8 中显著改变了其 API。如果本节中的代码返回错误,您可能需要升级 PyTorch 的版本。
预处理数据
Torchtext 还提供了预处理文本和创建数据管道的功能。预处理任务可能包括定义分词器、词汇表和数值嵌入。
在新的 Torchtext API 中,您可以使用data.get_tokenizer()函数访问不同的分词器,如下面的代码所示:
from torchtext.data.utils \
import get_tokenizer
tokenizer = get_tokenizer('basic_english')
在新 API 中创建词汇表也是灵活的。您可以直接使用Vocab类构建词汇表,如下面的代码所示:
from collections import Counter
from torchtext.vocab import Vocab
train_iter = IMDB(split='train')
counter = Counter()
for (label, line) in train_iter:
counter.update(tokenizer(line))
vocab = Vocab(counter,
min_freq=10,
specials=('<unk>',
'<BOS>',
'<EOS>',
'<PAD>'))
如您所见,我们可以设置min_freq来指定词汇表中的截止频率。我们还可以将特殊符号分配给特殊符号,比如<BOS>和<EOS>,如Vocab类的构造函数所示。
另一个有用的功能是为文本和标签定义转换,如下面的代码所示:
text_transform = lambda x: [vocab['<BOS>']] \
+ [vocab[token] \
for token in tokenizer(x)] + [vocab['<EOS>']]
label_transform = lambda x: 1 \
if x == 'pos' else 0
print(text_transform("programming is awesome"))
# out: [1, 8320, 12, 1156, 2]
我们将文本字符串传递给我们的转换,然后使用词汇表和分词器对数据进行预处理。
创建用于批处理的数据加载器
现在我们已经加载并预处理了数据,最后一步是创建一个数据加载器,以从数据集中对数据进行采样和批处理。我们可以使用以下代码创建一个数据加载器:
from torch.utils.data import DataLoader
train_iter = IMDB(split='train')
train_dataloader = DataLoader(
list(train_iter),
batch_size=8,
shuffle=True)
# for text, label in train_dataloader
您可能会注意到,这段代码与我们在 Torchvision 中创建数据加载器的代码相似。我们不是传入数据集对象,而是将train_iter转换为list()传入。DataLoader()构造函数还接受batch_sampler和collate_fcn参数(在上述代码中未显示;请参阅文档),因此您可以自定义数据集的采样和整理方式。创建数据加载器后,使用它来训练您的模型,如上述代码注释所示。
Torchtext 具有许多有用的功能。让我们探索 API 中提供的内容。
数据(torchtext.data)
torchtext.data API 提供了在 PyTorch 中创建基于文本的数据集对象的函数。表 8-17 列出了torchtext.data中可用的函数。
表 8-17. Torchtext 数据
| 函数 | 描述 |
|---|---|
torchtext.data.utils | |
get_tokenizer(tokenizer, language=en) | 为字符串句子生成一个分词器函数 |
ngrams_iterator(token_list, ngrams) | 返回一个迭代器,产生给定标记及其 ngrams |
torchtext.data.functional | |
generate_sp_model(filename, vocab_size=20000, model_type=unigram, model_prefix=m_user) | 训练一个SentencePiece分词器 |
load_sp_model(spm) | 从文件加载一个SentencePiece模型 |
sentencepiece_numericalizer(sp_model) | 创建一个生成器,接受文本句子并根据SentencePiece模型输出相应的标识符 |
sentencepiece_tokenizer(sp_model) | 创建一个生成器,接受文本句子并根据SentencePiece模型输出相应的标记 |
custom_replace(replace_pattern) | 作为一个转换器,将文本字符串转换 |
simple_space_split(iterator) | 作为一个转换器,通过空格分割文本字符串 |
numericalize_tokens_from_iterator(vocab, iterator, removed_tokens=None) | 从一个标记迭代器中产生一个标识符列表,使用vocab |
torchtext.data.metrics | |
bleu_score(candidate_corpus, references_corpus, max_n=4, weights=[0.25, 0.25, 0.25, 0.25]) | 计算候选翻译语料库和参考翻译语料库之间的 BLEU 分数 |
正如您所看到的,torchtext.data子模块支持根据字段创建数据集对象的函数,以及加载、预处理和迭代批次。接下来让我们看看 Torchtext 库中提供的 NLP 数据集有哪些。
数据集(torchtext.datasets)
Torchtext 支持从流行论文和研究中加载数据集。您可以找到用于语言建模、情感分析、文本分类、问题分类、蕴涵、机器翻译、序列标记、问题回答和无监督学习的数据集。
表 8-18 提供了 Torchtext 中包含的数据集的全面列表。
表 8-18. Torchtext 数据集
| 函数 | 描述 |
|---|---|
| 文本分类 | |
TextClassificationDataset(vocab, data, labels) | 通用文本分类数据集 |
IMDB(root=*.data*, split=(*train*, *test*)) | 包含来自 IMDb 的 50,000 条评论,标记为正面或负面的二元情感分析数据集 |
AG_NEWS(root=*.data*, split=(*train*, *test*)) | 包含四个主题标记的新闻文章数据集 |
SogouNews(root=*.data*, split=(*train*, *test*)) | 包含五个主题标记的新闻文章数据集 |
DBpedia(root=*.data*, split=(*train*, *test*)) | 包含 14 个类别标记的新闻文章数据集 |
YelpReviewPolarity(root=*.data*, split=(*train*, *test*)) | 包含 50 万条 Yelp 评论的二元分类数据集 |
YelpReviewFull(root=*.data*, split=(*train*, *test*)) | 包含 50 万条 Yelp 评论的数据集,具有细粒度(五类)分类 |
YahooAnswers(root=*.data*, split=(*train*, *test*)) | 包含 10 个不同类别的 Yahoo 答案的数据集 |
AmazonReviewPolarity(root=*.data*, split=(*train*, *test*)) | 包含亚马逊评论的数据集,具有二元分类 |
AmazonReviewFull(root=*.data*, split=(*train*, *test*)) | 包含亚马逊评论的数据集,具有细粒度(五类)分类 |
| 语言建模 | |
LanguageModelingDataset(path, text_field, newline_eos=True, encoding=*utf-8*, **kwargs) | 通用语言建模数据集类 |
WikiText2(root=*.data*, split=(*train*, *valid*, *test*)) | WikiText 长期依赖语言建模数据集,从维基百科上经过验证的“优秀”和“精选”文章中提取的超过 1 亿个标记的集合 |
WikiText103(root=*.data*, split=(*train*, *valid*, *test*)) | 更大的 WikiText 数据集 |
PennTreebank(root=*.data*, split=(*train*, *valid*, *test*)) | 最初为词性(POS)标记创建的相对较小的数据集 |
| 机器翻译 | |
TranslationDataset(path, exts, fields, **kwargs) | 通用翻译数据集类 |
IWSLT2016(root=*.data*, split=(*train*, *valid*, *test*), language_pair=(**de*, *en*)*,* *valid_set=tst2013, test_set=tst2014*)` | 国际口语翻译会议(IWSLT)2016 TED 演讲翻译任务 |
IWSLT2017(root=*.data*, split=(*train*, *valid*, *test*), language_pair=(*de*, *en*)) | 国际口语翻译会议(IWSLT)2017 TED 演讲翻译任务 |
| 序列标记 | |
SequenceTaggingDataset(path, fields, encoding=*utf-8*, separator=*t*, **kwargs) | 通用序列标记数据集类 |
UDPOS(root=*.data*, split=(*train*, *valid*, *test*)) | 通用依存关系版本 2 词性标记数据 |
CoNLL2000Chunking(root=*.data*, split=(*train*, *test*)) | 下载和加载 Conference on Computational Natural Language Learning (CoNLL) 2000 分块数据集的命令 |
| 问答 | |
SQuAD1(root=*.data*, split=(*train*, *dev*)) | 创建斯坦福问答数据集(SQuAD)1.0 数据集,这是一个由众包工作者在一组维基百科文章上提出的问题的阅读理解数据集 |
SQuAD2(root=.data, split=(train, dev)) | 创建斯坦福问答数据集(SQuAD)2.0 数据集,该数据集通过添加超过 5 万个无法回答的问题扩展了 1.0 数据集 |
Torchtext 开发人员始终在添加新的数据集。要获取最新列表,请访问Torchtext 数据集文档。
加载数据后,无论是来自现有数据集还是您创建的数据集,您都需要在训练模型和运行推理之前将文本数据转换为数值数据。为此,我们使用提供映射以执行这些转换的词汇表和词嵌入。接下来,我们将检查用于支持词汇表的 Torchtext 函数。
词汇表(torchtext.vocab)
Torchtext 提供了通用类和特定类来支持流行的词汇表。表 8-19 提供了torchtext.vocab中的类列表,以支持词汇表的创建和使用。
表 8-19. Torchtext 词汇表
| 功能 | 描述 |
|---|---|
| 词汇表类 | |
Vocab(counter, max_size=None, min_freq=1, specials=(<unk>, <pad>), vectors=None, unk_init=None, vectors_cache=None, specials_first=True) | 定义将用于数值化字段的词汇表对象 |
SubwordVocab(counter, max_size=None, specials=<pad>, vectors=None, unk_init=<method zero_of torch._C._TensorBase objects>) | 从collections.Counter创建一个revtok子词汇表 |
Vectors(name, cache=None, url=None, unk_init=None, max_vectors=None) | 用于词向量嵌入的通用类 |
| 预训练词嵌入 | |
GloVe(name=*840B*, dim=300, **kwargs) | 全局向量(GloVe)模型,用于分布式词表示,由斯坦福大学开发 |
FastText(language=en, **kwargs) | 294 种语言的预训练词嵌入,由 Facebook 的 AI 研究实验室创建 |
CharNGram(**kwargs) | CharNGram 嵌入,一种学习基于字符的组合模型以嵌入文本序列的简单方法 |
| 杂项 | |
build_vocab_from_iterator(iterator, num_lines=None) | 通过循环遍历迭代器构建词汇表 |
正如您所看到的,Torchtext 提供了一套强大的功能,支持基于文本的建模和 NLP 研究。欲了解更多信息,请访问Torchtext 文档。
无论您是为 NLP、计算机视觉或其他领域开发深度学习模型,能够在开发过程中可视化模型、数据和性能指标是很有帮助的。在下一节中,我们将探索另一个强大的用于可视化的包,称为 TensorBoard。
用于可视化的 TensorBoard
TensorBoard 是一个可视化工具包,包含在 PyTorch 的主要竞争深度学习框架 TensorFlow 中。PyTorch 没有开发自己的可视化工具包,而是与 TensorBoard 集成,并原生地利用其可视化能力。
使用 TensorBoard,您可以可视化学习曲线、标量数据、模型架构、权重分布和 3D 数据嵌入,以及跟踪超参数实验结果。本节将向您展示如何在 PyTorch 中使用 TensorBoard,并提供 TensorBoard API 的参考。
TensorBoard 应用程序在本地或远程服务器上运行,显示和用户界面在浏览器中运行。我们还可以在 Jupyter Notebook 或 Google Colab 中运行 TensorBoard。
我将在本书中使用 Colab 来演示 TensorBoard 的功能,但在本地或远程云中运行它的过程非常类似。Colab 预装了 TensorBoard,您可以直接在单元格中使用魔术命令运行它,如下所示的代码:
%load_ext tensorboard
%tensorboard --logdir ./runs/
首先我们加载tensorboard扩展,然后运行tensorboard并指定保存事件文件的日志目录。事件文件保存了来自 PyTorch 的数据,将在 TensorBoard 应用程序中显示。
由于我们尚未创建任何事件文件,您将看到一个空的显示,如图 8-1 所示。
图 8-1. TensorBoard 应用程序
通过单击右上角菜单中 INACTIVE 旁边的箭头,您将看到可能的显示选项卡。一个常用的显示选项卡是 SCALARS 选项卡。此选项卡可以显示随时间变化的任何标量值。我们经常使用 SCALARS 显示来查看损失和准确率训练曲线。让我们看看如何在您的 PyTorch 代码中保存标量值以供 TensorBoard 使用。
注意
PyTorch 与 TensorBoard 的集成最初是由一个名为 TensorBoardX 的开源项目实现的。自那时起,TensorBoard 支持已集成到 PyTorch 项目中,作为torch.utils.tensorboard包,并由 PyTorch 开发团队积极维护。
首先让我们导入 PyTorch 的 TensorBoard 接口,并设置 PyTorch 以便与 TensorBoard 一起使用,如下所示的代码:
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter() # ①
①
默认情况下,写入器将输出到*./runs/*目录。
我们只需从 PyTorch 的tensorboard包中导入SummaryWriter类,并实例化一个SummaryWriter对象。要将数据写入 TensorBoard,我们只需要调用SummaryWriter对象的方法。在模型训练时保存我们的损失数值,我们使用add_scalar()方法,如下面的代码所示:
N_EPOCHS = 10
for epoch in range(N_EPOCHS):
epoch_loss = 0.0
for inputs, labels in trainloader:
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
epoch_loss += loss.item()
print("Epoch: {} Loss: {}".format(epoch,
epoch_loss/len(trainloader)))
writer.add_scalar('Loss/train',
epoch_loss/len(trainloader), epoch) # ①
①
将loss.item()作为事件记录到tensorboard。
这只是一个示例训练循环。您可以假设model已经被定义,trainloader已经被创建。代码不仅在每个 epoch 打印损失,还将其记录到tensorboard事件中。我们可以刷新之前单元格中的 TensorBoard 应用程序,或者使用%tensorboard命令创建另一个单元格。
使用 SCALARS 查看学习曲线
TensorBoard 提供了绘制一个或多个标量值随时间变化的能力。在深度学习开发中,这对于显示模型训练时的指标非常有用。通过查看损失或准确率等指标,您可以轻松地看到您的模型训练是否稳定并持续改进。
图 8-2 展示了使用 TensorBoard 显示学习曲线的示例。
您可以通过滑动平滑因子与显示进行交互,也可以通过将鼠标悬停在绘图上查看每个 epoch 的曲线。TensorBoard 允许您应用平滑处理以消除不稳定性并显示整体进展。
图 8-2. TensorBoard 学习曲线
使用 GRAPHS 查看模型架构
TensorBoard 的另一个有用功能是使用图形可视化您的深度学习模型。要将图形保存到事件文件中,我们将使用add_graph()方法,如下面的代码所示:
model = vgg16(preTrained=True)
writer.add_graph(model)
在这段代码中,我们实例化了一个 VGG16 模型,并将模型写入事件文件。我们可以通过刷新现有的 TensorBoard 单元格或创建一个新的单元格来显示模型图。图 8-3 展示了 TensorBoard 中的图形可视化工具。
图 8-3. TensorBoard 模型图
该图是交互式的。您可以单击每个模块并展开以查看底层模块。这个工具对于理解现有模型并验证您的模型图是否符合其预期设计非常有用。
使用图像、文本和投影仪的数据
您还可以使用 TensorBoard 查看不同类型的数据,例如图像、文本和 3D 嵌入。在这些情况下,您将分别使用add_image()、add_text()和add_projection()方法将数据写入事件文件。
图 8-4 显示了来自 Fashion-MNIST 数据集的一批图像数据。
通过检查图像数据的批次,您可以验证数据是否符合预期,或者识别数据或结果中的错误。TensorBoard 还提供了监听音频数据、显示文本数据以及查看多维数据或数据嵌入的 3D 投影的能力。
图 8-4. TensorBoard 图像显示
使用 DISTRIBUTIONS 和 HISTOGRAMS 查看权重分布
TensorBoard 的另一个有用功能是显示分布和直方图。这使您可以查看大量数据以验证预期行为或识别问题。
模型开发中的一个常见任务是确保避免梯度消失问题。当模型权重变为零或接近零时,梯度消失就会发生。当这种情况发生时,神经元基本上会死亡,无法再更新。
如果我们可视化我们的权重分布,很容易看到大部分权重值已经达到零。
图 8-5 展示了 TensorBoard 中的 DISTRIBUTIONS 选项卡。在这里,我们可以检查我们的权重值的分布。
如您在图 8-5 中所见,TensorBoard 可以以 3D 显示分布,因此很容易看到分布随时间或每个时期如何变化。
图 8-5. TensorBoard 权重分布
具有 HPARAMS 的超参数
在运行深度学习实验时,很容易迷失不同超参数集的跟踪,以尝试假设。TensorBoard 提供了一种在每次实验期间跟踪超参数值并将值及其结果制表的方法。
图 8-6 显示了我们如何跟踪实验及其相应的超参数和结果的示例。
在 HPARAMS 选项卡中,您可以以表格视图、平行坐标视图或散点图矩阵视图查看结果。每个实验由其会话组名称、超参数(如丢失百分比和优化器算法)以及结果指标(如准确性)标识。HPARAMS 表格可帮助您跟踪实验和结果。
当您完成向 TensorBoard 事件文件写入数据时,应使用close()方法,如下所示:
writer.close()
这将调用析构函数并释放用于摘要写入器的任何内存。
图 8-6. TensorBoard 超参数跟踪
TensorBoard API
PyTorch TensorBoard API 非常简单。它作为torch.utils.tensorboard的一部分包含在torch.utils包中。表 8-20 显示了用于将 PyTorch 与 TensorBoard 接口的函数的全面列表。
表 8-20. PyTorch TensorBoard API
| 方法 | 描述 |
|---|---|
SummaryWriter(log_dir=None, comment='', purge_step=None, max_queue=10, flush_secs=120, filename_suffix='') | 创建SummaryWriter对象 |
flush() | 将事件文件刷新到磁盘;确保所有待处理事件都已写入磁盘 |
close() | 释放SummaryWriter对象并关闭事件文件 |
add_scalar(tag, scalar_value, global_step=None, walltime=None) | 将标量写入事件文件 |
add_scalars(main_tag, tag_scalar_dict, global_step=None, walltime=None) | 将多个标量写入事件文件以在同一图中显示多个标量 |
add_custom_scalars(layout) | 通过收集标量中的图表标签创建特殊图表 |
add_histogram(tag, values, global_step=None, bins=tensorflow, walltime=None, max_bins=None) | 为直方图显示写入数据 |
add_image(tag, img_tensor, global_step=None, walltime=None, dataformats=CHW) | 写入图像数据 |
add_images(tag, img_tensor, global_step=None, walltime=None, dataformats=NCHW) | 将多个图像写入同一显示 |
add_figure(tag, figure, global_step=None, close=True, walltime=None) | 将matplotlib类型的图绘制为图像 |
add_video(tag, vid_tensor, global_step=None, fps=4, walltime=None``) | 写入视频 |
add_audio(tag, snd_tensor, global_step=None, sample_rate=44100, walltime=None) | 将音频文件写入事件摘要 |
add_text(tag, text_string, global_step=None, walltime=None) | 将文本数据写入摘要 |
add_graph(model, input_to_model=None, verbose=False) | 将模型图或计算图写入摘要 |
add_embedding(mat, metadata=None, label_img=None, global_step=None, tag=default, metadata_header=None) | 将嵌入投影仪数据写入摘要 |
add_pr_curve(tag, labels, predictions, global_step=None, num_thresholds=127, weights=None, walltime=None) | 在不同阈值下写入精度/召回率曲线 |
add_mesh(tag, vertices, colors=None, faces=None, config_dict=None, global_step=None, walltime=None) | 将网格或 3D 点云添加到 TensorBoard |
add_hparams(hparam_dict, metric_dict, hparam_domain_discrete=None, run_name=None):向 TensorBoard 中添加一组超参数以进行比较。 |
如表 8-20 所示,API 很简单。您可以使用SummaryWriter()、flush()和close()方法来管理写入对象,并使用其他函数向 TensorBoard 事件文件添加数据。
有关 TensorBoard PyTorch API 的更多详细信息,请访问 TensorBoard API 文档。有关如何使用 TensorBoard 应用程序本身的更多详细信息,请访问 TensorBoard 文档。
TensorBoard 通过提供可视化工具解决了在 PyTorch 中开发深度学习模型时的一个主要挑战。另一个主要挑战是跟上最新研究和最先进的解决方案。研究人员经常需要重现结果并利用代码来对比自己的设计。在接下来的部分中,我们将探讨 Papers with Code,这是一个您可以使用的资源来解决这个问题。
Papers with Code
Papers with Code(PwC)是一个网站,它整理了机器学习研究论文及其相应的代码,这些代码通常是用 PyTorch 编写的。PwC 允许您轻松重现实验并扩展当前研究,该网站还允许您找到给定机器学习主题的表现最佳的研究论文。例如,想要找到最佳的图像分类模型及其代码吗?只需点击图像分类瓷砖,您将看到研究领域的摘要以及 GitHub 上相应论文和代码的基准和链接。图 8-7 展示了图像分类的示例列表。
“Papers With Code Image Classification Listing”图片
图 8-7. Papers with Code
PwC 并不是一个专门的 PyTorch 项目;然而,PwC 提供的大多数代码都使用 PyTorch。它可能有助于您了解当前最先进的研究并解决您在深度学习和人工智能方面的问题。在 PwC 网站上探索更多。
额外的 PyTorch 资源
阅读完这本书后,您应该对 PyTorch 及其功能有很好的理解。然而,总是有新的方面可以探索和实践。在本节中,我将提供一些额外资源的列表,您可以查看以了解更多信息,并提升您在 PyTorch 中的技能。
教程
PyTorch 网站提供了大量的文档和教程。如果您正在寻找更多的代码示例,这个资源是一个很好的起点。图 8-8 展示了 PyTorch 教程网站,您可以选择标签来帮助您找到感兴趣的教程。
“PyTorch 教程网站”图片
图 8-8. PyTorch 教程
该网站包括一个 60 分钟的闪电战、PyTorch 食谱、教程和 PyTorch 备忘单。大多数代码和教程都可以在 GitHub 上找到,并且可以在 VS Code、Jupyter Notebook 和 Colab 中运行。
60 分钟闪电战是一个很好的起点,可以帮助您恢复技能或复习 PyTorch 的基础知识。PyTorch 食谱是关于如何使用特定 PyTorch 功能的简短、可操作的示例。PyTorch 教程比食谱稍长,由多个步骤组成,以实现或演示一个结果。
目前,您可以找到与以下主题相关的教程:
-
音频
-
最佳实践
-
C++
-
CUDA
-
扩展 PyTorch
-
FX
-
前端 API
-
入门
-
图像/视频
-
可解释性
-
内存格式
-
移动
-
模型优化
-
并行和分布式训练
-
生产
-
性能分析
-
量化
-
强化学习
-
TensorBoard
-
文本
-
TorchScript
PyTorch 团队不断添加新资源,这个列表肯定会发生变化。有关更多信息和最新教程,请访问 PyTorch 教程网站。
书籍
教程是学习的好方法,但也许您更喜欢阅读有关 PyTorch 的更多信息,并从多位作者的不同视角获得不同观点。表 8-21 提供了与 PyTorch 相关的其他书籍列表。
表 8-21. PyTorch 书籍
| 书籍 | 出版商,年份 | 摘要 |
|---|---|---|
| 云原生机器学习 by Carl Osipov | Manning, 2021 | 学习如何在 AWS 上部署 PyTorch 模型 |
| 使用 fastai 和 PyTorch 进行编码人员的深度学习 by Jeremy Howard 和 Sylvain Gugger | O’Reilly, 2020 | 学习如何在没有博士学位的情况下构建人工智能应用程序 |
| 使用 PyTorch 进行深度学习 by Eli Stevens 等 | Manning, 2019 | 学习如何使用 Python 工具构建、训练和调整神经网络 |
| 使用 PyTorch 进行深度学习 by Vishnu Subramanian | Packt, 2018 | 学习如何使用 PyTorch 构建神经网络模型 |
| 使用 PyTorch 1.x 进行实用生成对抗网络 by John Hany 和 Greg Walters | Packt, 2019 | 学习如何使用 Python 实现下一代神经网络,构建强大的 GAN 模型 |
| Hands-On Natural Language Processing with PyTorch 1.x by Thomas Dop | Packt, 2020 | 学习如何利用深度学习和自然语言处理技术构建智能的人工智能驱动的语言应用程序 |
| 使用 PyTorch 1.0 进行实用神经网络 by Vihar Kurama | Packt, 2019 | 学习如何在 PyTorch 中实现深度学习架构 |
| 使用 PyTorch 进行自然语言处理 by Delip Rao 和 Brian McMahan | O’Reilly, 2019 | 学习如何利用深度学习构建智能语言应用程序 |
| 使用 PyTorch 进行实用深度学习 by Nihkil Ketkar | Apress, 2020 | 学习如何使用 Python 优化 GAN |
| 为深度学习编程 PyTorch by Ian Pointer | O’Reilly, 2019 | 学习如何创建和部署深度学习应用程序 |
| PyTorch 人工智能基础 by Jibin Mathew | Packt, 2020 | 学习如何设计、构建和部署自己的 PyTorch 1.x AI 模型 |
| PyTorch 食谱 by Pradeepta Mishra | Apress, 2019 | 学习如何在 PyTorch 中解决问题 |
在线课程和现场培训
如果您更喜欢在线视频课程和现场培训研讨会,您可以选择扩展您的 PyTorch 知识和技能的选项。您可以继续从 PyTorch Academy、Udemy、Coursera、Udacity、Skillshare、DataCamp、Pluralsight、edX、O’Reilly Learning 和 LinkedIn Learning 等在线讲师那里学习。一些课程是免费的,而其他课程需要付费或订阅。
表 8-22 列出了撰写时可用的 PyTorch 在线课程的选择。
表 8-22. PyTorch 课程
| 课程 | 讲师 | 平台 |
|---|---|---|
| 开始使用 PyTorch 开发 | Joe Papa | PyTorch Academy |
| PyTorch 基础 | Joe Papa | PyTorch Academy |
| 高级 PyTorch | Joe Papa | PyTorch Academy |
| 使用 PyTorch 进行深度学习入门 | Ismail Elezi | DataCamp |
| PyTorch 基础 | Janani Ravi | Pluralsight |
| 使用 PyTorch 的深度神经网络 | IBM | Coursera |
| 用于机器学习的 PyTorch 基础 | IBM | edX |
| 使用 PyTorch 进行深度学习入门 | Facebook AI | Udacity |
| PyTorch:深度学习和人工智能 | 懒惰的程序员 | Udemy |
| 用于深度学习和计算机视觉的 PyTorch | Rayan Slim 等 | Udemy |
| PyTorch 入门 | Dan We | Skillshare |
| PyTorch 基础培训:深度学习 | Jonathan Fernandes | LinkedIn Learning |
| 使用 PyTorch 介绍深度学习 | Goku Mohandas 和 Alfredo Canziani | O’Reilly Learning |
本章提供了扩展您学习、研究和开发 PyTorch 的资源。您可以将这些材料作为 PyTorch 项目和 PyTorch 生态系统中众多软件包的快速参考。当您希望扩展您的技能和知识时,可以返回本章,获取其他培训材料的想法。
恭喜您完成了这本书!您已经走了很长一段路,掌握了张量,理解了模型开发过程,并探索了使用 PyTorch 的参考设计。此外,您还学会了如何定制 PyTorch,创建自己的特性,加速训练,优化模型,并将您的神经网络部署到云端和边缘设备。最后,我们探索了 PyTorch 生态系统,调查了关键软件包如 Torchvision、Torchtext 和 TensorBoard,并了解了通过教程、书籍和在线课程扩展知识的其他方法。
无论您将来要处理什么项目,我希望您能一次又一次地返回这本书。我也希望您继续扩展您的技能,并掌握 PyTorch 的能力,开发创新的新深度学习工具和系统。不要让您的新知识和技能消失。去构建一些有趣的东西,在世界上产生影响!
让我知道您创造了什么!我希望在PyTorch Academy的课程中见到您,并随时通过电子邮件(jpapa@joepapa.ai)、Twitter(@JoePapaAI)或 LinkedIn(@MrJoePapa)联系我。