使用 TensorBoard 可视化模型,数据和训练

译者:片刻

校验:片刻

60分钟闪电战中,我们向您展示了如何加载数据,如何通过定义为的子类的nn.Module模型提供数据,如何在训练数据上训练该模型以及如何在测试数据上对其进行测试。为了了解发生了什么,我们在模型训练期间打印一些统计数据,以了解训练是否在进行。但是,我们可以做得更好:PyTorch与TensorBoard集成在一起,TensorBoard是一种工具,用于可视化神经网络训练运行的结果。本教程使用Fashion-MNIST数据集说明了其某些功能,该 数据集 可以使用torchvision.datasets读取到PyTorch中。

在本教程中,我们将学习如何:

  • 读入数据并进行适当的转换(与先前的教程几乎相同)。
  • 设置TensorBoard。
  • 写入TensorBoard。
  • 使用TensorBoard检查模型架构。
  • 使用TensorBoard以更少的代码创建我们在上一个教程中创建的可视化的交互式版本

具体来说,在第5点,我们将看到:

  • 检查我们训练数据的几种方法
  • 在训练过程中如何跟踪模型的性能
  • 训练后如何评估模型的性能。
  • 我们将从与CIFAR-10教程类似的样板代码开始:
  1. # imports
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. import torch
  5. import torchvision
  6. import torchvision.transforms as transforms
  7. import torch.nn as nn
  8. import torch.nn.functional as F
  9. import torch.optim as optim
  10. # transforms
  11. transform = transforms.Compose(
  12. [transforms.ToTensor(),
  13. transforms.Normalize((0.5,), (0.5,))])
  14. # datasets
  15. trainset = torchvision.datasets.FashionMNIST('./data',
  16. download=True,
  17. train=True,
  18. transform=transform)
  19. testset = torchvision.datasets.FashionMNIST('./data',
  20. download=True,
  21. train=False,
  22. transform=transform)
  23. # dataloaders
  24. trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
  25. shuffle=True, num_workers=2)
  26. testloader = torch.utils.data.DataLoader(testset, batch_size=4,
  27. shuffle=False, num_workers=2)
  28. # constant for classes
  29. classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
  30. 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot')
  31. # helper function to show an image
  32. # (used in the `plot_classes_preds` function below)
  33. def matplotlib_imshow(img, one_channel=False):
  34. if one_channel:
  35. img = img.mean(dim=0)
  36. img = img / 2 + 0.5 # unnormalize
  37. npimg = img.numpy()
  38. if one_channel:
  39. plt.imshow(npimg, cmap="Greys")
  40. else:
  41. plt.imshow(np.transpose(npimg, (1, 2, 0)))

我们将在该教程中定义一个类似的模型体系结构,仅需进行少量修改即可解决以下事实:图像现在是一个通道而不是三个通道,而图像是28x28而不是32x32:

  1. class Net(nn.Module):
  2. def __init__(self):
  3. super(Net, self).__init__()
  4. self.conv1 = nn.Conv2d(1, 6, 5)
  5. self.pool = nn.MaxPool2d(2, 2)
  6. self.conv2 = nn.Conv2d(6, 16, 5)
  7. self.fc1 = nn.Linear(16 * 4 * 4, 120)
  8. self.fc2 = nn.Linear(120, 84)
  9. self.fc3 = nn.Linear(84, 10)
  10. def forward(self, x):
  11. x = self.pool(F.relu(self.conv1(x)))
  12. x = self.pool(F.relu(self.conv2(x)))
  13. x = x.view(-1, 16 * 4 * 4)
  14. x = F.relu(self.fc1(x))
  15. x = F.relu(self.fc2(x))
  16. x = self.fc3(x)
  17. return x
  18. net = Net()

我们将optimizercriterion之前定义相同:

  1. criterion = nn.CrossEntropyLoss()
  2. optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

1. TensorBoard设置

现在我们将设置TensorBoard,tensorboard从我们的关键对象导入torch.utils并定义它SummaryWriter,该关键对象用于将信息写入TensorBoard。

  1. from torch.utils.tensorboard import SummaryWriter
  2. # default `log_dir`is "runs" - we'll be more specific here
  3. writer = SummaryWriter('runs/fashion_mnist_experiment_1')

请注意,这条线单独创建一个runs/fashion_mnist_experiment_1文件夹中。

2.写入TensorBoard

现在,让我们写我们的TensorBoard形象-具体而言,一个网格-使用make_grid

  1. # get some random training images
  2. dataiter = iter(trainloader)
  3. images, labels = dataiter.next()
  4. # create grid of images
  5. img_grid = torchvision.utils.make_grid(images)
  6. # show images
  7. matplotlib_imshow(img_grid, one_channel=True)
  8. # write to tensorboard
  9. writer.add_image('four_fashion_mnist_images', img_grid)

现在运行

  1. tensorboard --logdir=runs

在命令行,然后导航到https://localhost:6006/应该显示如下。

https://pytorch.org/tutorials/_static/img/tensorboard_first_view.png

现在您知道如何使用TensorBoard了!但是,此示例可以在Jupyter Notebook中完成-TensorBoard真正擅长的地方是创建交互式可视化。我们将在接下来的内容中介绍其中之一,并在本教程结束时介绍更多内容。

3. 使用TensorBoard检查模型

TensorBoard的优势之一是其可视化复杂模型结构的能力。让我们可视化我们构建的模型。

  1. writer.add_graph(net, images)
  2. writer.close()

现在刷新TensorBoard后,您应该会看到一个“ Graphs”标签,如下所示:

https://pytorch.org/tutorials/_static/img/tensorboard_model_viz.png

继续并双击 “Net” 以展开它,查看组成模型的各个操作的详细视图。

TensorBoard具有非常方便的功能,用于可视化高维数据,例如在低维空间中的图像数据;接下来我们将介绍。

4. 在TensorBoard中添加一个“投影仪”

我们可以通过 add_embedding 方法可视化高维数据的低维表示

  1. # helper function
  2. def select_n_random(data, labels, n=100):
  3. '''
  4. Selects n random datapoints and their corresponding labels from a dataset
  5. '''
  6. assert len(data) == len(labels)
  7. perm = torch.randperm(len(data))
  8. return data[perm][:n], labels[perm][:n]
  9. # select random images and their target indices
  10. images, labels = select_n_random(trainset.data, trainset.targets)
  11. # get the class labels for each image
  12. class_labels = [classes[lab] for lab in labels]
  13. # log embeddings
  14. features = images.view(-1, 28 * 28)
  15. writer.add_embedding(features,
  16. metadata=class_labels,
  17. label_img=images.unsqueeze(1))
  18. writer.close()

现在,在TensorBoard的“投影仪”选项卡中,您可以看到这100张图像-每个图像784维-向下投影到三维空间中。此外,这是交互式的:您可以单击并拖动以旋转三维投影。最后,一些技巧可以使可视化效果更容易看到:在左上方选择“颜色:标签”,并启用“夜间模式”,这将使图像更容易看到,因为它们的背景是白色的:

https://pytorch.org/tutorials/_static/img/tensorboard_projector.png

现在我们已经彻底检查了我们的数据,让我们展示了TensorBoard如何从训练开始就可以使跟踪模型训练和评估更加清晰。

5. 使用TensorBoard跟踪模型训练

在前面的示例中,我们仅每2000次迭代打印一次模型的运行损失。现在,我们将运行损失记录到TensorBoard中,并通过模型查看模型所做的预测plot_classes_preds

  1. # helper functions
  2. def images_to_probs(net, images):
  3. '''
  4. Generates predictions and corresponding probabilities from a trained
  5. network and a list of images
  6. '''
  7. output = net(images)
  8. # convert output probabilities to predicted class
  9. _, preds_tensor = torch.max(output, 1)
  10. preds = np.squeeze(preds_tensor.numpy())
  11. return preds, [F.softmax(el, dim=0)[i].item() for i, el in zip(preds, output)]
  12. def plot_classes_preds(net, images, labels):
  13. '''
  14. Generates matplotlib Figure using a trained network, along with images
  15. and labels from a batch, that shows the network's top prediction along
  16. with its probability, alongside the actual label, coloring this
  17. information based on whether the prediction was correct or not.
  18. Uses the "images_to_probs" function.
  19. '''
  20. preds, probs = images_to_probs(net, images)
  21. # plot the images in the batch, along with predicted and true labels
  22. fig = plt.figure(figsize=(12, 48))
  23. for idx in np.arange(4):
  24. ax = fig.add_subplot(1, 4, idx+1, xticks=[], yticks=[])
  25. matplotlib_imshow(images[idx], one_channel=True)
  26. ax.set_title("{0}, {1:.1f}%\n(label: {2})".format(
  27. classes[preds[idx]],
  28. probs[idx] * 100.0,
  29. classes[labels[idx]]),
  30. color=("green" if preds[idx]==labels[idx].item() else "red"))
  31. return fig

最后,让我们使用与之前教程中相同的模型训练代码来训练模型,但是每1000批将结果写入TensorBoard,而不是打印到控制台。这是使用 add_scalar 函数完成的 。

另外,在训练过程中,我们将生成一幅图像,显示该批次中包含的四幅图像的模型预测与实际结果。

  1. running_loss = 0.0
  2. for epoch in range(1): # loop over the dataset multiple times
  3. for i, data in enumerate(trainloader, 0):
  4. # get the inputs; data is a list of [inputs, labels]
  5. inputs, labels = data
  6. # zero the parameter gradients
  7. optimizer.zero_grad()
  8. # forward + backward + optimize
  9. outputs = net(inputs)
  10. loss = criterion(outputs, labels)
  11. loss.backward()
  12. optimizer.step()
  13. running_loss += loss.item()
  14. if i % 1000 == 999: # every 1000 mini-batches...
  15. # ...log the running loss
  16. writer.add_scalar('training loss',
  17. running_loss / 1000,
  18. epoch * len(trainloader) + i)
  19. # ...log a Matplotlib Figure showing the model's predictions on a
  20. # random mini-batch
  21. writer.add_figure('predictions vs. actuals',
  22. plot_classes_preds(net, inputs, labels),
  23. global_step=epoch * len(trainloader) + i)
  24. running_loss = 0.0
  25. print('Finished Training')

现在,您可以查看“标量”选项卡,以查看在15,000次训练迭代中绘制的运行损失:

https://pytorch.org/tutorials/_static/img/tensorboard_scalar_runs.png

此外,我们可以看看预测在整个学习任意批量制造的模型。查看“图像”选项卡,然后在“预测与实际”可视化条件下向下滚动以查看此内容;这向我们表明,例如,仅经过3000次训练迭代,该模型就已经能够区分出视觉上截然不同的类,例如衬衫,运动鞋和外套,尽管它并没有像后来的训练那样充满信心:

https://pytorch.org/tutorials/_static/img/tensorboard_images.png

在之前的教程中,我们研究了模型训练后的每班准确性;在这里,我们将使用TensorBoard绘制每个类的精确调用曲线(此处有很好的解释 )。

6. 使用TensorBoard评估经过训练的模型

  1. # 1. gets the probability predictions in a test_size x num_classes Tensor
  2. # 2. gets the preds in a test_size Tensor
  3. # takes ~10 seconds to run
  4. class_probs = []
  5. class_preds = []
  6. with torch.no_grad():
  7. for data in testloader:
  8. images, labels = data
  9. output = net(images)
  10. class_probs_batch = [F.softmax(el, dim=0) for el in output]
  11. _, class_preds_batch = torch.max(output, 1)
  12. class_probs.append(class_probs_batch)
  13. class_preds.append(class_preds_batch)
  14. test_probs = torch.cat([torch.stack(batch) for batch in class_probs])
  15. test_preds = torch.cat(class_preds)
  16. # helper function
  17. def add_pr_curve_tensorboard(class_index, test_probs, test_preds, global_step=0):
  18. '''
  19. Takes in a "class_index" from 0 to 9 and plots the corresponding
  20. precision-recall curve
  21. '''
  22. tensorboard_preds = test_preds == class_index
  23. tensorboard_probs = test_probs[:, class_index]
  24. writer.add_pr_curve(classes[class_index],
  25. tensorboard_preds,
  26. tensorboard_probs,
  27. global_step=global_step)
  28. writer.close()
  29. # plot all the pr curves
  30. for i in range(len(classes)):
  31. add_pr_curve_tensorboard(i, test_probs, test_preds)

现在,您将看到一个“ PR Curves”选项卡,其中包含每个类别的精确调用曲线。继续戳一下;您会看到,在某些类别上,模型的“曲线下面积”接近100%,而在另一些类别上,该面积更低:

https://pytorch.org/tutorials/_static/img/tensorboard_pr_curves.png

这是TensorBoard和PyTorch与之集成的介绍。当然,你可以做一切TensorBoard确实在Jupyter笔记本电脑,但TensorBoard,你得到了默认情况下交互的视觉效果。