PyTorch-Ignite的介绍与快速上手

news2024/11/19 3:39:21

PyTorch-Ignite 是一个用于 PyTorch 的高级库,旨在帮助开发者更快、更简洁地编写可复用的代码来进行深度学习实验。它由 PyTorch 社区开发,提供了一套灵活的抽象,用于构建和管理训练和验证循环,而无需牺牲 PyTorch 的灵活性和强大功能。

主要特点包括:

  1. 简洁的训练和验证循环:Ignite 提供了一个 Engine 类,用于封装训练和验证循环的逻辑,使代码更加简洁和易于理解。

  2. 易于扩展:通过 Events 和 Handlers,用户可以轻松地自定义训练过程,比如在训练的不同阶段添加日志记录、模型保存等。

  3. 指标和日志:Ignite 内置了许多常用的指标,方便评估模型性能。它也可以与流行的日志库(如 TensorBoard)集成,以便于跟踪实验。

  4. 复用和共享:它鼓励代码复用,并使得分享最佳实践变得更加容易。

  5. 社区支持:作为 PyTorch 生态系统的一部分,Ignite 享有活跃的社区支持和持续的发展。

Ignite 对于想要减少样板代码、更专注于模型开发的 PyTorch 用户来说是一个很好的选择。它不仅简化了开发过程,还保留了 PyTorch 的灵活性和强大功能。

一、介绍

这篇文章是对 PyTorch-Ignite 的全面介绍,旨在向深度学习爱好者、专业人士和研究人员展示 PyTorch-Ignite 的核心优势和功能。PyTorch-Ignite 与 PyTorch 保持一致的设计理念,致力于保持简单性、灵活性和可扩展性,同时确保高效性和可伸缩性。

在本教程中,我们将通过构建和评估一个简单的 MNIST 分类器来阐述 PyTorch-Ignite 的基本概念,这是一个理想的入门案例。我们假设读者已经具备 PyTorch 的基础知识。

PyTorch-Ignite:是什么以及为什么选择它?

PyTorch-Ignite 是一个高级库,专为在 PyTorch 中灵活且透明地训练和评估神经网络而设计。它旨在成为易用的高级功能和深度定制可能性的交汇点。通过推广最佳实践,PyTorch-Ignite 助力深度学习社区技术能力的提升。它的设计理念是让一切功能都易于用户理解和使用,而不是隐藏在一个全能的工具背后。

PyTorch-Ignite 采用了“自己动手”的方法,这一点对于研究领域尤为重要,因为研究本质上是充满不确定性的,重要的是在不阻碍流程的同时捕捉到研究的需求。

PyTorch + Ignite

PyTorch-Ignite 将 PyTorch 的原生抽象概念(如模块、优化器和数据加载器)以极简的方式封装,通过 Engine 这一控制反转的抽象概念实现了模型与训练框架的完全分离。Engine 负责运行任意函数,通常是训练或评估函数,并在整个过程中发出事件。

Engine 的灵活性得益于其内置的事件系统(由 Events 类实现),这大大促进了运行过程中每一步的互动。用户可以完全自定义运行期间的事件流程,从而实现高度定制化的训练体验。

总结来说,PyTorch-Ignite 提供了:
• 极其简单的引擎和事件系统,实现了训练循环的高度抽象。
• 开箱即用的度量指标,便于轻松评估模型性能。
• 内置的处理程序,用于构建训练管道、保存工件以及记录参数和指标。
选择 PyTorch-Ignite 的额外好处包括:
• 相较于纯 PyTorch,代码更少,同时保持了最大程度的控制性和简洁性。
• 更加模块化、结构化的代码设计。

关于 PyTorch-Ignite 的设计

PyTorch-Ignite 允许您构建应用程序,而不是专注于一个多功能的超级对象,而是侧重于弱耦合的组件,从而实现高级定制。
该库的设计指导原则包括:
• 预见未来可能出现的新软件或用例,而不是把一切都集中在一个单一的类中。
• 避免使用难以管理和维护的大量参数配置。
• 提供旨在最大化内聚性和最小化耦合性的工具。
• 保持简单。

二、快速入门示例

在这一部分,我们将使用 PyTorch-Ignite 构建和训练一个著名的 MNIST 数据集分类器。这个简单的例子将介绍 PyTorch-Ignite 背后的主要概念。
如需获取更多信息和关于 API 的详细信息,请参阅项目文档点击跳转。

安装pytorch-ignite模块

pip install pytorch-ignite

首先,我们定义了我们的模型、训练和验证数据集、优化器和损失函数:

import os
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import SGD
from torch.utils.data import DataLoader

from torchvision.transforms import Compose, ToTensor, Normalize
from torchvision.datasets import MNIST

# transform to normalize the data
transform = Compose([ToTensor(), Normalize((0.1307,), (0.3081,))])

# Download and load the training data
trainset = MNIST("data", download=True, train=True, transform=transform)
train_loader = DataLoader(trainset, batch_size=128, shuffle=True)

# Download and load the test data
validationset = MNIST("data", train=False, transform=transform)
val_loader = DataLoader(validationset, batch_size=256, shuffle=False)

# Define a class of CNN model (as you want)
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=-1)

device = "cuda"

# Define a model on move it on CUDA device
model = Net().to(device)

# Define a NLL loss
criterion = nn.NLLLoss()

# Define a SGD optimizer
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.8)

上面的代码是纯粹的 PyTorch,并且通常由用户定义,对于任何流程来说都是必需的。

训练器和评估器的设置

模型的训练器是一个引擎,它多次循环遍历训练数据集并更新模型参数。让我们看看如何使用 PyTorch-Ignite 定义这样的训练器。为此,PyTorch-Ignite 引入了通用类 Engine,它是一个抽象概念,可以遍历提供的数据,执行处理函数并返回结果。构建训练器所需的唯一参数是 train_step 函数。

from ignite.engine import Engine

def train_step(engine, batch):
    x, y = batch
    x = x.to(device)
    y = y.to(device)

    model.train()
    y_pred = model(x)
    loss = criterion(y_pred, y)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    return loss

# Define a trainer engine
trainer = Engine(train_step)

请注意,train_step 函数必须接受 engine 和 batch 参数。在上面的例子中,尽管 train_step 内部没有使用 engine,但我们可以轻松想象一个使用场景,在该场景中我们可能希望从 engine 中获取当前迭代、epoch 或自定义变量等信息。

同样地,模型评估可以通过一个引擎来完成,该引擎对验证数据集运行一次,并计算指标。

def validation_step(engine, batch):
    model.eval()
    with torch.no_grad():
        x, y = batch[0], batch[1]
        x = x.to("cuda")
        y = y.to("cuda")

        y_pred = model(x)

        return y_pred, y

evaluator = Engine(validation_step)

这允许从最简单到最复杂的场景构建训练逻辑。
处理函数的输出类型(例如上面示例中的 loss 或 y_pred, y)并不受限制。这些函数可以返回用户想要的任何内容。输出被设置为引擎的内部对象 engine.state.output,并可以进一步用于任何类型的处理。

事件和处理器

为了提高引擎的灵活性,引入了一个可配置的事件系统,以便在运行的每一步上促进互动。具体来说,Engine 允许在运行期间触发的各种事件上添加处理器。当事件被触发时,附加的处理器(命名函数、lambda 表达式、类函数)将被执行。以下是默认触发内置事件的流程图:

fire_event(Events.STARTED)
while epoch < max_epochs:
    fire_event(Events.EPOCH_STARTED)
    # run once on data
    for batch in data:
        fire_event(Events.ITERATION_STARTED)

        output = process_function(batch)

        fire_event(Events.ITERATION_COMPLETED)
    fire_event(Events.EPOCH_COMPLETED)
fire_event(Events.COMPLETED)

请注意,每个引擎(即训练器和评估器)都有自己的事件系统,这允许定义其自己的引擎处理逻辑。

使用事件和处理器,可以以非常直观的方式完全自定义引擎的运行:

from ignite.engine import Events

# Show a message when the training begins
@trainer.on(Events.STARTED)
def start_message():
    print("Start training!")

# Handler can be want you want, here a lambda !
trainer.add_event_handler(
    Events.COMPLETED,
    lambda _: print("Training completed!")
)

# Run evaluator on val_loader every trainer's epoch completed
@trainer.on(Events.EPOCH_COMPLETED)
def run_validation():
    evaluator.run(val_loader)

在上述代码中,run_validation 函数被附加到训练器上,并将在每个完成的 epoch 时触发,以启动使用评估器的模型验证。这表明可以嵌入引擎来创建复杂的流水线。

与回调相比,处理器提供了无与伦比的灵活性,因为它们可以是任何函数:例如,一个 lambda 表达式、一个简单的函数、一个类方法等。因此,我们不需要继承一个接口并重写其抽象方法,这可能会不必要地增加代码的体积和复杂性。

定制的可能性是无穷的,因为 PyTorch-Ignite 允许您掌握应用程序的工作流程。正如之前提到的,PyTorch-Ignite 中没有魔法或完全自动化的东西。

模型评估指标

指标是展示 PyTorch-Ignite 处理器是什么以及如何使用它们的另一个很好的例子。在我们的例子中,我们使用内置的 Accuracy 和 Loss 指标。

from ignite.metrics import Accuracy, Loss

# Accuracy and loss metrics are defined
val_metrics = {
  "accuracy": Accuracy(),
  "loss": Loss(criterion)
}

# Attach metrics to the evaluator
for name, metric in val_metrics.items():
    metric.attach(evaluator, name)

PyTorch-Ignite 的指标可以优雅地相互结合使用。

from ignite.metrics import Precision, Recall

# Build F1 score
precision = Precision(average=False)
recall = Recall(average=False)
F1 = (precision * recall * 2 / (precision + recall)).mean()

# and attach it to evaluator
F1.attach(evaluator, "f1")

为了进一步简化操作,我们提供了辅助方法来创建类似上面所示的监督型引擎。因此,我们接下来将以这种方式定义一个新的评估器,它将应用于训练数据集。

from ignite.engine import create_supervised_evaluator

# Define another evaluator with default validation function and attach metrics
train_evaluator = create_supervised_evaluator(model, metrics=val_metrics, device="cuda")

# Run train_evaluator on train_loader every trainer's epoch completed
@trainer.on(Events.EPOCH_COMPLETED)
def run_train_validation():
    train_evaluator.run(train_loader)

我们之所以需要两个不同的评估器(即评估器和训练评估器),是因为它们可以执行不同的处理器和逻辑。例如,如果我们想根据验证数据集的指标值来保存最佳模型,这个任务就由计算验证数据集指标的评估器来承担。

常用的训练处理器
从现在开始,我们设置了一个训练器,它会在每个 epoch 完成时调用评估器和训练评估器。因此,每个评估器都会运行并计算相应的指标。另外,能够显示这些指标的结果非常有助于我们了解训练过程。

借助引擎系统的定制能力,我们可以添加一些简单的处理器来实现这种日志记录:

@evaluator.on(Events.COMPLETED)
def log_validation_results():
    metrics = evaluator.state.metrics
    print("Validation Results - Epoch: {}  Avg accuracy: {:.2f} Avg loss: {:.2f} Avg F1: {:.2f}"
          .format(trainer.state.epoch, metrics["accuracy"], metrics["loss"], metrics["f1"]))

@train_evaluator.on(Events.COMPLETED)
def log_train_results():
    metrics = train_evaluator.state.metrics
    print("  Training Results - Epoch: {}  Avg accuracy: {:.2f} Avg loss: {:.2f}"
          .format(trainer.state.epoch, metrics["accuracy"], metrics["loss"]))

在这里,我们在 Events.COMPLETED 事件上附加了 log_validation_results 和 log_train_results 处理器,因为评估器和训练评估器将在验证数据集上运行一个 epoch。

让我们来看看如何为我们的应用程序添加一些其他有用的功能。
*PyTorch-Ignite 提供了一个 ProgressBar 处理器,用以显示引擎的进度。

from ignite.contrib.handlers import ProgressBar

ProgressBar().attach(trainer, output_transform=lambda x: {'batch loss': x})
* [ModelCheckpoint](https://pytorch.org/ignite/handlers.html#ignite.handlers.ModelCheckpoint)处理程序可用于定期保存具有属性state_dict的对象。
from ignite.handlers import ModelCheckpoint, global_step_from_engine

# Score function to select relevant metric, here f1
def score_function(engine):
    return engine.state.metrics["f1"]

# Checkpoint to store n_saved best models wrt score function
model_checkpoint = ModelCheckpoint(
    "quick-start-mnist-output",
    n_saved=2,
    filename_prefix="best",
    score_function=score_function,
    score_name="f1",
    global_step_transform=global_step_from_engine(trainer),
)

# Save the model (if relevant) every epoch completed of evaluator
evaluator.add_event_handler(Events.COMPLETED, model_checkpoint, {"model": model})
*PyTorch-Ignite 为现代实验跟踪工具提供了包装器。例如,TensorBoardLogger 处理器可以在训练和验证过程中记录指标结果、模型参数、优化器参数、梯度等信息,以便于在 TensorBoard 中进行查看。
from ignite.contrib.handlers import TensorboardLogger

# Define a Tensorboard logger
tb_logger = TensorboardLogger(log_dir="quick-start-mnist-output")

# Attach handler to plot trainer's loss every 100 iterations
tb_logger.attach_output_handler(
    trainer,
    event_name=Events.ITERATION_COMPLETED(every=100),
    tag="training",
    output_transform=lambda loss: {"batchloss": loss},
)

# Attach handler to dump evaluator's metrics every epoch completed
for tag, evaluator in [("training", train_evaluator), ("validation", evaluator)]:
    tb_logger.attach_output_handler(
        evaluator,
        event_name=Events.EPOCH_COMPLETED,
        tag=tag,
        metric_names="all",
        global_step_transform=global_step_from_engine(trainer),
    )

通过集成用户定义的函数,可以非常简单地扩展 TensorBoard 记录器的使用。例如,以下是在训练过程中展示图像和预测的方法:

import matplotlib.pyplot as plt

# Store predictions and scores using matplotlib
def predictions_gt_images_handler(engine, logger, *args, **kwargs):
    x, _ = engine.state.batch
    y_pred, y = engine.state.output
    # y_pred is log softmax value
    num_x = num_y = 8
    le = num_x * num_y
    probs, preds = torch.max(torch.exp(y_pred[:le]), dim=1)
    fig = plt.figure(figsize=(20, 20))
    for idx in range(le):
        ax = fig.add_subplot(num_x, num_y, idx + 1, xticks=[], yticks=[])
        ax.imshow(x[idx].squeeze(), cmap="Greys")
        ax.set_title("{0} {1:.1f}% (label: {2})".format(
            preds[idx],
            probs[idx] * 100.0,
            y[idx]),
            color=("green" if preds[idx] == y[idx] else "red")
        )
    logger.writer.add_figure('predictions vs actuals', figure=fig, global_step=trainer.state.epoch)

# Attach custom function to evaluator at first iteration
tb_logger.attach(
    evaluator,
    log_handler=predictions_gt_images_handler,
    event_name=Events.ITERATION_COMPLETED(once=1),
)

现在我们需要做的就是在 train_loader 提供的数据上运行训练器,并进行若干个 epoch 的训练。

trainer.run(train_loader, max_epochs=5)

# Once everything is done, let's close the logger
tb_logger.close()

Start training!

Validation Results - Epoch: 1  Avg accuracy: 0.94 Avg loss: 0.20 Avg F1: 0.94
  Training Results - Epoch: 1  Avg accuracy: 0.94 Avg loss: 0.21

Validation Results - Epoch: 2  Avg accuracy: 0.96 Avg loss: 0.12 Avg F1: 0.96
  Training Results - Epoch: 2  Avg accuracy: 0.96 Avg loss: 0.13

Validation Results - Epoch: 3  Avg accuracy: 0.97 Avg loss: 0.10 Avg F1: 0.97
  Training Results - Epoch: 3  Avg accuracy: 0.97 Avg loss: 0.10

Validation Results - Epoch: 4  Avg accuracy: 0.98 Avg loss: 0.07 Avg F1: 0.98
  Training Results - Epoch: 4  Avg accuracy: 0.97 Avg loss: 0.09

Validation Results - Epoch: 5  Avg accuracy: 0.98 Avg loss: 0.07 Avg F1: 0.98
  Training Results - Epoch: 5  Avg accuracy: 0.98 Avg loss: 0.08
Training completed!

我们可以使用 TensorBoard 来检查结果。在 TensorBoard 中,我们可以看到两个标签页:“Scalars”和“Images”。

%load_ext tensorboard

%tensorboard --logdir=.
在这里插入图片描述在这里插入图片描述

五个关键点

• 几乎所有的训练逻辑都可以通过编写 train_step 方法并基于此方法构建训练器来实现。
• 这个库的核心是 Engine 类,它能够在数据集上重复执行给定次数的循环,并执行处理函数。
• 一个高度可定制的事件系统使得在运行的每一步都能轻松与引擎互动。
• PyTorch-Ignite 提供了一系列内置的处理器和常用任务的指标。
• PyTorch-Ignite 容易扩展。

高级特性
在这一节中,我们将为经验丰富的用户介绍 PyTorch-Ignite 的一些高级特性。我们将更深入地讨论事件、处理器和指标,以及在 GPU 和 TPU 上的分布式计算。如果您是初学者,现在可以先跳过这部分,日后再回来阅读。

事件与处理器的强大功能
通过快速入门示例,我们已经见识到了事件和处理器在需要时执行任意数量函数的完美适用性。除此之外,我们还提供了几种方法来进一步扩展这些功能,包括:
• 内置事件的过滤功能
• 堆叠事件以共享操作
• 添加自定义事件,以超越内置标准事件
让我们更详细地探讨这些特性。

内置事件过滤器

用户可以简单地过滤掉事件,以跳过触发处理器。让我们创建一个虚拟的训练器:

from ignite.engine import Engine, Events

trainer = Engine(lambda e, batch: None)

让我们考虑一个用例,我们希望训练一个模型,并定期在几个开发数据集上运行其验证,例如 devset1 和 devset2:

# We run the validation on devset1 every 5 epochs
@trainer.on(Events.EPOCH_COMPLETED(every=5))
def run_validation1():
    print("Epoch {}: Validation on devset 1".format(trainer.state.epoch))
    # evaluator.run(devset1)  # commented out for demo purposes

# We run another validation on devset2 every 10 epochs
@trainer.on(Events.EPOCH_COMPLETED(every=10))
def run_validation2():
    print("Epoch {}: Validation on devset 2".format(trainer.state.epoch))
    # evaluator.run(devset2)  # commented out for demo purposes

train_data = [0, 1, 2, 3, 4]
trainer.run(train_data, max_epochs=50)
Epoch 5: Validation on devset 1
Epoch 10: Validation on devset 1
Epoch 10: Validation on devset 2
Epoch 15: Validation on devset 1
Epoch 20: Validation on devset 1
Epoch 20: Validation on devset 2
Epoch 25: Validation on devset 1
Epoch 30: Validation on devset 1
Epoch 30: Validation on devset 2
Epoch 35: Validation on devset 1
Epoch 40: Validation on devset 1
Epoch 40: Validation on devset 2
Epoch 45: Validation on devset 1
Epoch 50: Validation on devset 1
Epoch 50: Validation on devset 2

现在让我们考虑另一种情况,当我们达到特定的 epoch 或迭代时,我们想要进行一次性的变更。例如,让我们在第 5 个 epoch 将训练数据集从低分辨率图像更改为高分辨率图像:

def train_step(e, batch):
    print("Epoch {} - {} : batch={}".format(e.state.epoch, e.state.iteration, batch))

trainer = Engine(train_step)

small_res_data = [0, 1, 2, ]
high_res_data = [10, 11, 12]

# We run the following handler once on 5-th epoch started
@trainer.on(Events.EPOCH_STARTED(once=5))
def change_train_dataset():
    print("Epoch {}: Change training dataset".format(trainer.state.epoch))
    trainer.set_data(high_res_data)

trainer.run(small_res_data, max_epochs=10)

Epoch 1 - 1 : batch=0
Epoch 1 - 2 : batch=1
Epoch 1 - 3 : batch=2
Epoch 2 - 4 : batch=0
Epoch 2 - 5 : batch=1
Epoch 2 - 6 : batch=2
Epoch 3 - 7 : batch=0
Epoch 3 - 8 : batch=1
Epoch 3 - 9 : batch=2
Epoch 4 - 10 : batch=0
Epoch 4 - 11 : batch=1
Epoch 4 - 12 : batch=2
Epoch 5: Change training dataset
Epoch 5 - 13 : batch=10
Epoch 5 - 14 : batch=11
Epoch 5 - 15 : batch=12
Epoch 6 - 16 : batch=10
Epoch 6 - 17 : batch=11
Epoch 6 - 18 : batch=12
Epoch 7 - 19 : batch=10
Epoch 7 - 20 : batch=11
Epoch 7 - 21 : batch=12
Epoch 8 - 22 : batch=10
Epoch 8 - 23 : batch=11
Epoch 8 - 24 : batch=12
Epoch 9 - 25 : batch=10
Epoch 9 - 26 : batch=11
Epoch 9 - 27 : batch=12
Epoch 10 - 28 : batch=10
Epoch 10 - 29 : batch=11
Epoch 10 - 30 : batch=12

现在,让我们来考虑另一种情景,我们希望能够触发一个具有完全定制化逻辑的处理器。例如,我们想在训练损失达到某个特定条件时,导出模型的梯度:

# Let's predefine for simplicity training losses
train_losses = [2.0, 1.9, 1.7, 1.5, 1.6, 1.2, 0.9, 0.8, 1.0, 0.8, 0.7, 0.4, 0.2, 0.1, 0.1, 0.01]

trainer = Engine(lambda e, batch: train_losses[e.state.iteration - 1])

# We define our custom logic when to execute a handler
def custom_event_filter(trainer, event):
    if 0.1 < trainer.state.output < 1.0:
        return True
    return False

# We run the following handler every iteration completed under our custom_event_filter condition:
@trainer.on(Events.ITERATION_COMPLETED(event_filter=custom_event_filter))
def dump_model_grads():
    print("{} - loss={}: dump model grads".format(trainer.state.iteration, trainer.state.output))

train_data = [0, ]
trainer.run(train_data, max_epochs=len(train_losses))
7 - loss=0.9: dump model grads
8 - loss=0.8: dump model grads
10 - loss=0.8: dump model grads
11 - loss=0.7: dump model grads
12 - loss=0.4: dump model grads
13 - loss=0.2: dump model grads

堆叠事件以实现共享操作

用户可以在不同类型的事件上触发相同的处理器。例如,我们可以设置每隔 3 个 epoch 对模型进行一次验证,并在训练结束时再进行一次验证:

trainer = Engine(lambda e, batch: None)

@trainer.on(Events.EPOCH_COMPLETED(every=3) | Events.COMPLETED)
def run_validation():
    print("Epoch {} - event={}: Validation".format(trainer.state.epoch, trainer.last_event_name))
    # evaluator.run(devset)

train_data = [0, 1, 2, 3, 4]
trainer.run(train_data, max_epochs=20)
Epoch 3 - event=epoch_completed: Validation
Epoch 6 - event=epoch_completed: Validation
Epoch 9 - event=epoch_completed: Validation
Epoch 12 - event=epoch_completed: Validation
Epoch 15 - event=epoch_completed: Validation
Epoch 18 - event=epoch_completed: Validation
Epoch 20 - event=completed: Validation

添加自定义事件

用户可以添加自己的事件,以超越内置的标准事件。例如,我们可以定义与反向传播和优化器步骤调用相关的新事件。这可以帮助我们以可配置的方式在这些事件上附加特定的处理器。

from ignite.engine import EventEnum


class BackpropEvents(EventEnum):
    BACKWARD_STARTED = 'backward_started'
    BACKWARD_COMPLETED = 'backward_completed'
    OPTIM_STEP_COMPLETED = 'optim_step_completed'


def update(engine, batch):
    # ...
    # loss = criterion(y_pred, y)
    engine.fire_event(BackpropEvents.BACKWARD_STARTED)
    # loss.backward()
    engine.fire_event(BackpropEvents.BACKWARD_COMPLETED)
    # optimizer.step()
    engine.fire_event(BackpropEvents.OPTIM_STEP_COMPLETED)
    # ...

trainer = Engine(update)
trainer.register_events(*BackpropEvents)

def function_before_backprop():
    print("{} - before backprop".format(trainer.state.iteration))

trainer.add_event_handler(BackpropEvents.BACKWARD_STARTED, function_before_backprop)

def function_after_backprop():
    print("{} - after backprop".format(trainer.state.iteration))

trainer.add_event_handler(BackpropEvents.BACKWARD_COMPLETED, function_after_backprop)

train_data = [0, 1, 2, 3, 4]
trainer.run(train_data, max_epochs=2)
1 - before backprop
1 - after backprop
2 - before backprop
2 - after backprop
3 - before backprop
3 - after backprop
4 - before backprop
4 - after backprop
5 - before backprop
5 - after backprop
6 - before backprop
6 - after backprop
7 - before backprop
7 - after backprop
8 - before backprop
8 - after backprop
9 - before backprop
9 - after backprop
10 - before backprop
10 - after backprop

即用型指标

PyTorch-Ignite 提供了一整套专为多种深度学习任务(如分类、回归、分割等)设计的指标。这些指标中的大多数能够在线计算感兴趣的数据,无需存储模型的整个输出历史。
* 分类任务:精确度、召回率、准确率、混淆矩阵等。
* 分割任务:Dice 系数、IoU、mIOU 等。
* 约 20 种回归指标,例如均方误差(MSE)、平均绝对误差(MAE)、中位绝对误差等。
* 能够存储每个 epoch 的整个输出历史的指标
* 可以与 scikit-learn 的指标结合使用,如 EpochMetric、AveragePrecision、ROC_AUC 等。
* 易于组合,可用于构建自定义指标。
* 易于扩展,用于创建自定义指标。
PyTorch-Ignite 提供的完整指标列表可以在 ignite.metrics 和 ignite.contrib.metrics 这两个部分找到。

提供了两种类型的公共 API:
* 将指标附加到 Engine 上。
* 指标的 reset、update、compute 方法。

关于 reset、update、compute 公共 API 的详细信息

我们将使用 Accuracy 指标的一个简单示例来演示这个 API。这个 API 的核心思想是,在每次 update 调用时,我们会在内部累积一些计数器。指标的值在每次 compute 调用时被计算,并且在每次 reset 调用时重置计数器。

import torch
from ignite.metrics import Accuracy

acc = Accuracy()

# Start accumulation
acc.reset()

y_target = torch.tensor([0, 1, 2, 1,])
# y_pred is logits computed by the model
y_pred = torch.tensor([
    [10.0, 0.1, -1.0],  # correct
    [2.0, -1.0, -2.0],  # incorrect
    [1.0, -1.0, 4.0],   # correct
    [0.0, 5.0, -1.0],   # correct
])
acc.update((y_pred, y_target))

# Compute accuracy on 4 samples
print("After 1st update, accuracy=", acc.compute())

y_target = torch.tensor([1, 2, 0, 2])
# y_pred is logits computed by the model
y_pred = torch.tensor([
    [2.0, 1.0, -1.0],   # incorrect
    [0.0, 1.0, -2.0],   # incorrect
    [2.6, 1.0, -4.0],   # correct
    [1.0, -3.0, 2.0],   # correct
])
acc.update((y_pred, y_target))

# Compute accuracy on 8 samples
print("After 2nd update, accuracy=", acc.compute())
After 1st update, accuracy= 0.75
After 2nd update, accuracy= 0.625

可组合指标
用户可以轻松地使用现有指标通过算术运算或 PyTorch 方法来组合自己的指标。例如,可以直接编码定义为100 * (1.0 - 准确率)的误差指标:

import torch
from ignite.metrics import Accuracy

acc = Accuracy()
error = 100.0 * (1.0 - acc)

# Start accumulation
acc.reset()

y_target = torch.tensor([0, 1, 2, 1,])
# y_pred is logits computed by the model
y_pred = torch.tensor([
    [10.0, 0.1, -1.0],  # correct
    [2.0, -1.0, -2.0],  # incorrect
    [1.0, -1.0, 4.0],   # correct
    [0.0, 5.0, -1.0],   # correct
])
acc.update((y_pred, y_target))

# Compute error on 4 samples
print("After 1st update, error=", error.compute())

y_target = torch.tensor([1, 2, 0, 2])
# y_pred is logits computed by the model
y_pred = torch.tensor([
    [2.0, 1.0, -1.0],   # incorrect
    [0.0, 1.0, -2.0],   # incorrect
    [2.6, 1.0, -4.0],   # correct
    [1.0, -3.0, 2.0],   # correct
])
acc.update((y_pred, y_target))

# Compute err on 8 samples
print("After 2nd update, error=", error.compute())
After 1st update, error= 25.0
After 2nd update, error= 37.5

如果无法通过基础指标的算术运算来表达自定义指标,请遵循此指南来实现自定义指标。

开箱即用的处理器

PyTorch-Ignite 提供了各种常见的处理器,以简化应用程序代码的编写:
* 常用训练处理器:Checkpoint(检查点)、EarlyStopping(提前终止)、Timer(计时器)、TerminateOnNan(遇到 NaN 时终止)
* 优化器参数调度(如学习率、动量等)
* 结合多种调度器、添加热身阶段、循环调度、分段线性调度等!详见示例。
* 时间性能分析
* 日志记录到实验跟踪系统:
* Tensorboard、Visdom、MLflow、Polyaxon、Neptune、Trains 等。
PyTorch-Ignite 提供的处理器的完整列表可以在 ignite.handlers 和 ignite.contrib.handlers 这两部分找到。

常见训练处理器

利用开箱即用的 Checkpoint(检查点)处理器,用户可以轻松地将训练状态或最佳模型保存到文件系统或云存储中。
EarlyStopping(提前终止)和 TerminateOnNan(遇到 NaN 时终止)有助于在训练过程中发生过拟合或发散时及时停止训练。
所有这些功能都可以轻松地一个接一个地添加到训练器中,或者通过辅助方法进行添加。
下面我们来看一个使用辅助方法的示例。

import torch
import torch.nn as nn
import torch.optim as optim

from ignite.engine import create_supervised_trainer, create_supervised_evaluator, Events
from ignite.metrics import Accuracy
import ignite.contrib.engines.common as common

train_data = [[torch.rand(2, 4), torch.randint(0, 5, size=(2, ))] for _ in range(10)]
val_data = [[torch.rand(2, 4), torch.randint(0, 5, size=(2, ))] for _ in range(10)]
epoch_length = len(train_data)

model = nn.Linear(4, 5)
optimizer = optim.SGD(model.parameters(), lr=0.01)
# step_size is expressed in iterations
lr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=epoch_length, gamma=0.88)

# Let's define some dummy trainer and evaluator
trainer = create_supervised_trainer(model, optimizer, nn.CrossEntropyLoss())
evaluator = create_supervised_evaluator(model, metrics={"accuracy": Accuracy()})


@trainer.on(Events.EPOCH_COMPLETED)
def run_validation():
    evaluator.run(val_data)

# training state to save
to_save = {
    "trainer": trainer, "model": model,
    "optimizer": optimizer, "lr_scheduler": lr_scheduler
}
metric_names = ["batch loss", ]

common.setup_common_training_handlers(
    trainer=trainer,
    to_save=to_save,
    output_path="checkpoints",
    save_every_iters=epoch_length,
    lr_scheduler=lr_scheduler,
    output_names=metric_names,
    with_pbars=True,
)

tb_logger = common.setup_tb_logging("tb_logs", trainer, optimizer, evaluators=evaluator)

common.save_best_model_by_val_score(
    "best_models",
    evaluator=evaluator,
    model=model,
    metric_name="accuracy",
    n_saved=2,
    trainer=trainer,
    tag="val",
)

trainer.run(train_data, max_epochs=5)

tb_logger.close()
HBox(children=(FloatProgress(value=0.0, max=5.0), HTML(value='')))
ls -all "checkpoints"
ls -all "best_models"
ls -all "tb_logs"
total 12
drwxr-xr-x 2 root root 4096 Aug 31 11:27 .
drwxr-xr-x 1 root root 4096 Aug 31 11:27 ..
-rw------- 1 root root 1657 Aug 31 11:27 training_checkpoint_50.pt
total 16
drwxr-xr-x 2 root root 4096 Aug 31 11:27  .
drwxr-xr-x 1 root root 4096 Aug 31 11:27  ..
-rw------- 1 root root 1145 Aug 31 11:27 'best_model_2_val_accuracy=0.3000.pt'
-rw------- 1 root root 1145 Aug 31 11:27 'best_model_3_val_accuracy=0.3000.pt'
total 12
drwxr-xr-x 2 root root 4096 Aug 31 11:27 .
drwxr-xr-x 1 root root 4096 Aug 31 11:27 ..
-rw-r--r-- 1 root root  325 Aug 31 11:27 events.out.tfevents.1598873224.3aa7adc24d3d.115.1

在上述代码中,common.setup_common_training_handlers 方法添加了 TerminateOnNan 处理器,添加了一个处理器来使用以迭代表示的 lr_scheduler(学习率调度器),添加了训练状态的检查点,将批量损失输出作为用于日志记录的指数移动平均指标,还为训练器添加了一个进度条。

接下来,common.setup_tb_logging 方法返回一个 TensorBoard 日志记录器,它被自动配置为记录训练器的指标(即批量损失)、优化器的学习率以及评估器的指标。

最后,common.save_best_model_by_val_score 设置了一个处理器,用于根据验证精度指标保存最佳的两个模型。

分布式和 XLA 设备支持

PyTorch 提供了一个分布式通信包,用于编写和运行多个设备和机器上的并行应用程序。
原生接口提供了常用的集体操作,并允许使用 torch DistributedDataParallel 模块和众所周知的 mpi、gloo 和 nccl 后端,无缝地处理多 CPU 和多 GPU 计算。
最近,用户还可以在 XLA 设备(如 TPU)上运行 PyTorch,使用 torch_xla 包。

然而,编写在 GPU 和 TPU 上工作的分布式训练代码并非易事,因为一些 API 的特殊性。
PyTorch-Ignite 在 0.4 版本中引入的 ignite.distributed 包的目的是统一原生 torch.distributed API、XLA 设备上的 torch_xla API 的代码,同时还支持其他分布式框架(如 Horovod)。
为了使分布式配置设置更加简单,引入了 Parallel 上下文管理器:

import ignite.distributed as idist

def training(local_rank, config, **kwargs):
    print(idist.get_rank(), ': run with config:', config, '- backend=', idist.backend())
    # do the training ...

backend = 'gloo' # or "nccl" or "xla-tpu"
dist_configs = {'nproc_per_node': 2}
# dist_configs["start_method"] = "fork"  # If using Jupyter Notebook
config = {'c': 12345}

with idist.Parallel(backend=backend, **dist_configs) as parallel:
    parallel.run(training, config, a=1, b=2)
2020-08-31 11:27:07,128 ignite.distributed.launcher.Parallel INFO: Initialized distributed launcher with backend: 'gloo'
2020-08-31 11:27:07,128 ignite.distributed.launcher.Parallel INFO: - Parameters to spawn processes: 
    nproc_per_node: 2
    nnodes: 1
    node_rank: 0
2020-08-31 11:27:07,128 ignite.distributed.launcher.Parallel INFO: Spawn function '<function training at 0x7f32b8ac9d08>' in 2 processes
0 : run with config: {'c': 12345} - backend= gloo
1 : run with config: {'c': 12345} - backend= gloo
2020-08-31 11:27:09,959 ignite.distributed.launcher.Parallel INFO: End of run

上述代码只需稍作修改,就可以在 GPU、单节点多 GPU、单个或多个 TPU 等上运行。它可以通过 torch.distributed.launch 工具执行,或者通过 Python 来生成所需数量的进程。更多详细信息,请参阅文档。

此外,像 auto_model()、auto_optim() 和 auto_dataloader() 这样的方法有助于以透明的方式将提供的模型、优化器和数据加载器适配到现有配置中:

# main.py

import ignite.distributed as idist

def training(local_rank, config, **kwargs):

    print(idist.get_rank(), ": run with config:", config, "- backend=", idist.backend())

    train_loader = idist.auto_dataloader(dataset, batch_size=32, num_workers=12, shuffle=True, **kwargs)
    # batch size, num_workers and sampler are automatically adapted to existing configuration
    # ...
    model = resnet50()
    optimizer = optim.SGD(model.parameters(), lr=0.01)

    # if training with Nvidia/Apex for Automatic Mixed Precision (AMP)
    # model, optimizer = amp.initialize(model, optimizer, opt_level=opt_level)

    model = idist.auto_model(model)
    # model is DDP or DP or just itself according to existing configuration
    # ...
    optimizer = idist.auto_optim(optimizer)
    # optimizer is itself, except XLA configuration and overrides `step()` method.
    # User can safely call `optimizer.step()` (behind `xm.optimizer_step(optimizier)` is performed)

backend = "nccl"  # torch native distributed configuration on multiple GPUs
# backend = "xla-tpu"  # XLA TPUs distributed configuration
# backend = None  # no distributed configuration
with idist.Parallel(backend=backend, **dist_configs) as parallel:
    parallel.run(training, config, a=1, b=2)

请注意,这些 auto_* 方法是可选的;用户可以自由地使用其中一些方法,并在需要时手动设置代码的某些部分。这种方法的优势在于没有必然的对象补丁和覆盖。

关于 PyTorch-Ignite 提供的分布式助手的更多细节可以在文档中找到。关于在 CIFAR10 上训练的完整示例可以在这里找到。

一个详细的带有分布式助手的教程已经发布在这里。

三、More

要了解更多关于 PyTorch-Ignite 的信息,请查看官方网站:https://pytorch-ignite.ai,以及官方的教程和操作指南。
官方还提供了 PyTorch-Ignite 代码生成器应用程序:https://code-generator.pytorch-ignite.ai/,以便在不需要从头开始编写一切的情况下开始处理任务。
PyTorch-Ignite 的代码可在 GitHub 上获得:https://github.com/pytorch/ignite。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1478845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四、《任务列表案例》后端程序实现和测试

本章概要 准备工作功能实现前后联调 4.1 准备工作 数据库脚本 CREATE TABLE schedule (id INT NOT NULL AUTO_INCREMENT,title VARCHAR(255) NOT NULL,completed BOOLEAN NOT NULL,PRIMARY KEY (id) );INSERT INTO schedule (title, completed) VALUES(学习java, true),(学…

电力运维是做什么的?电力行业智能运维工作内容?

电力行业智能运维工作内容具体涉及哪些关键任务&#xff1f;实施智能运维过程中&#xff0c;如何利用现代信息技术、人工智能和大数据分析来提升电力系统的运行效率与维护响应速度?在电力行业中引入智能运维后&#xff0c;对于预防性维护、故障诊断、设备寿命预测以及成本控制…

react native中如何实现tab切换页面以及页面可以左右滑动效果

react native中如何实现tab切换页面以及页面可以左右滑动效果 效果示例图主体代码 效果示例图 主体代码 import React, {useRef, useState} from react; import {View,ScrollView,Text,StyleSheet,Dimensions,Animated, } from react-native; import {pxToPd} from ../../comm…

Linux系统——LAMP架构

目录 一、LAMP架构组成 1.LAMP定义 2.各组件的主要作用 3.CGI和FastCGI 3.1CGI 3.3CGI和FastCGI比较 4.PHP 4.1PHP简介 4.2PHP的Opcode语言 4.3PHP设置 二、LAMP架构实现 1.编译安装Apache httpd服务 2.编译安装Mysql 3.编译安装PHP 4.安装论坛 5.搭建博客 W…

力扣区间题:合并区间、插入区间

我们可以将区间按照左端点升序排列&#xff0c;然后遍历区间进行合并操作。 我们先将第一个区间加入答案&#xff0c;然后依次考虑之后的每个区间&#xff1a; 如果答案数组中最后一个区间的右端点小于当前考虑区间的左端点&#xff0c;说明两个区间不会重合&#xff0c;因此…

当大语言模型遇到AI绘画-google gemma与stable diffusion webui融合方法-矿卡40hx的AI一体机

你有想过建一台主机&#xff0c;又能AI聊天又能AI绘画&#xff0c;还可以直接把聊天内容直接画出来的机器吗&#xff1f; 当Google最新的大语言模型Gemma碰到stable diffusion webui会怎么样&#xff1f; 首先我们安装stable diffusion webui(automatic1111开源项目&#xff…

【基于ChatGPT大模型】GIS应用、数据清洗、统计分析、论文助手、项目基金助手、科研绘图、AI绘图

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

Google Genie:创意互动环境

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

渗透测试靶场环境搭建

1.DVWA靶场 DVWA&#xff08;Damn Vulnerable Web Application&#xff09;是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用&#xff0c;包含了OWASP TOP10的所有攻击漏洞的练习环境&#xff0c;旨在为安全专业人员测试自己的专业技能和工具提供合法的环境&#xff0c;同时…

完美解决git 执行git push origin master指令 报错command not found

问题描述 报错信息为&#xff1a;在提交项目时的操作&#xff1a;找不到命令行 解决方案 &#xff08;1&#xff09;可以通过如下命令进行代码合并【注&#xff1a;pullfetchmerge】 git pull --rebase origin master&#xff08;2&#xff09;再执行语句&#xff1a; git p…

Linux(CentOS)学习

一、认识Linux 1、如何修改Linux时区 2、配置固定IP 3、重启网络服务 3、小技巧快捷键 4、环境变量设置 5、Linux文件的上传和下载 6、压缩和解压 二、基础命令 1、目录命令 (1、)查看目录内容&#xff08;ls&#xff09; 1、ls //查看当前目录内容 2、- a //显示隐藏内容 3…

Spatom——利用图神经网络进行蛋白质-蛋白质结合位点预测的新工具

介绍一个蛋白质-蛋白质结合位点预测的新工具——Spatom&#xff0c;这是一个图神经网络框架。其发布在brief in bioinformatics上面。 Paper and tool links 文章&#xff0c;网页工具和github链接如下 paper link: Spatom: a graph neural network for structure-based prot…

lv20 QT事件

1 事件模型 2 事件处理 virtual void keyPressEvent(QKeyEvent *event) virtual void keyReleaseEvent(QKeyEvent *event) virtual void mouseDoubleClickEvent(QMouseEvent *event) virtual void mouseMoveEvent(QMouseEvent *event) virtual void mousePressEvent(QMou…

【Android12】Monkey压力测试源码执行流程分析

Monkey压力测试源码执行流程分析 Monkey是Android提供的用于应用程序自动化测试、压力测试的测试工具。 其源码路径(Android12)位于 /development/cmds/monkey/部署形式为Java Binary # development/cmds/monkey/Android.bp // Copyright 2008 The Android Open Source Proj…

《PyTorch深度学习实践》第九讲多分类问题

一、 1、softmax的输入不需要再做非线性变换&#xff0c;也就是说softmax之前不再需要激活函数。softmax两个作用&#xff0c;如果在进行softmax前的input有负数&#xff0c;通过指数变换&#xff0c;得到正数。所有类的概率求和为1。 2、y的标签编码方式是one-hot。one-hot是…

java爬取深圳新房备案价

Java爬取深圳新房备案价 这是我做好效果,一共分3个页面 1、列表;2、统计;3、房源表 列表 价格分析页面 房源页面 一、如何爬取 第一步:获取深圳新房备案价 链接是:http://zjj.sz.gov.cn/ris/bol/szfdc/index.aspx 第二步:通过楼盘名查询获取明细 链接:http://z…

就业班 2401--2.27 Linux Day6--管道和重定向

管道与重定向 只有在开水里&#xff0c;茶叶才能展开生命浓郁的香气. 一、重定向 标准输入、标准正确输出、标准错误输出 进程在运行的过程中根据需要会打开多个文件&#xff0c;每打开一个文件会有一个数字标识。这个标识叫文件描述符。 进程使用文件描述符来管理打开的文件…

Android PDFView 提示401 pom

背景 在开发安卓app&#xff0c;使用PDF组件来解析URL地址 &#xff0c;从github找到一个开源组件 AndroidPdfViewer 遇到一个大坑&#xff0c;一直提示下载依赖401 pom 打开控制台链接弹出需要登录jitpack 原因分析&#xff1a; 这个组件项目依赖库链接到了需要鉴权的…

【airtest】自动化入门教程(一)AirtestIDE

目录 一、下载与安装 1、下载 2、安装 3、打开软件 二、web自动化配置 1、配置chrome浏览器 2、窗口勾选selenium window 三、新建项目&#xff08;web&#xff09; 1、新建一个Airtest项目 2、初始化代码 3、打开一个网页 四、恢复默认布局 五、新建项目&#xf…

服务器数据恢复-服务器RAID5上层XFS文件系统分区数据恢复案例

服务器数据恢复环境&#xff1a; MD1200磁盘柜中的磁盘通过RAID卡创建了一组RAID5阵列&#xff0c;分配了一个LUN。在Linux操作系统层面对该LUN进行了分区&#xff0c;划分sdc1和sdc2两个分区&#xff0c;通过LVM扩容的方式将sdc1分区加入到了root_lv中&#xff1b;sdc2分区格式…