PyTorch 使用 TensorBoard 可視化模型,數(shù)據(jù)和訓(xùn)練

2020-09-16 11:45 更新

原文: PyTorch 使用 TensorBoard 可視化模型,數(shù)據(jù)和訓(xùn)練

校驗(yàn)者:yearing1017

60 分鐘閃電戰(zhàn)中,我們向您展示了如何加載數(shù)據(jù),如何向定義為nn.Module子類的模型提供數(shù)據(jù),如何在訓(xùn)練數(shù)據(jù)上訓(xùn)練該模型,以及在測(cè)試數(shù)據(jù)上對(duì)其進(jìn)行測(cè)試。 為了了解發(fā)生的情況,我們?cè)谀P陀?xùn)練期間打印一些統(tǒng)計(jì)信息,以了解訓(xùn)練是否在進(jìn)行中。 但是,我們可以做得更好:PyTorch 與 TensorBoard 集成,該工具旨在可視化神經(jīng)網(wǎng)絡(luò)訓(xùn)練運(yùn)行的結(jié)果。 本教程使用 Fashion-MNIST 數(shù)據(jù)集說明了其某些功能,可以使用 torchvision.datasets 將其讀取到 PyTorch 中。

在本教程中,我們將學(xué)習(xí)如何:

  1. 讀取數(shù)據(jù)并進(jìn)行適當(dāng)?shù)霓D(zhuǎn)換(與先前的教程幾乎相同)。
    2. 設(shè)置 TensorBoard。
    3. 寫入 TensorBoard。
    4. 使用 TensorBoard 檢查模型架構(gòu)。
    5. 使用 TensorBoard 來創(chuàng)建我們?cè)谏弦粋€(gè)教程中創(chuàng)建的可視化的替代版本,代碼量更少。

具體來說,在第 5 點(diǎn),我們將看到:

  • 有兩種檢查訓(xùn)練數(shù)據(jù)的方法
    - 在訓(xùn)練模型時(shí)如何追蹤其性能
    - 在訓(xùn)練完成后如何評(píng)估模型的性能。

我們將從 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)))

我們將在該教程中定義一個(gè)類似的模型架構(gòu),僅需進(jìn)行少量修改即可說明以下事實(shí):圖像現(xiàn)在是一個(gè)通道而不是三個(gè)通道,是 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 設(shè)置

現(xiàn)在,我們將設(shè)置 TensorBoard,從torch.utils導(dǎo)入tensorboard并定義SummaryWriter,這是將信息寫入 TensorBoard 的關(guān)鍵對(duì)象。

  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')

請(qǐng)注意,僅此行會(huì)創(chuàng)建一個(gè)runs/fashion_mnist_experiment_1文件夾。

2.寫入 TensorBoard

現(xiàn)在,使用 make_grid 將圖像寫入到 TensorBoard 中,具體來說就是網(wǎng)格。

  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)

現(xiàn)在運(yùn)行

  1. tensorboard --logdir=runs

應(yīng)該顯示以下內(nèi)容。

intermediate/../../_static/img/tensorboard_first_view.png

現(xiàn)在您知道如何使用 TensorBoard 了! 但是,此示例可以在 Jupyter Notebook 中完成-TensorBoard 真正擅長(zhǎng)的地方是創(chuàng)建交互式可視化。 接下來,我們將介紹其中之一,并在本教程結(jié)束時(shí)介紹更多內(nèi)容。

3.使用 TensorBoard 檢查模型

TensorBoard 的優(yōu)勢(shì)之一是其可視化復(fù)雜模型結(jié)構(gòu)的能力。 讓我們可視化我們構(gòu)建的模型。

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

現(xiàn)在刷新 TensorBoard 后,您應(yīng)該會(huì)看到一個(gè)“ Graphs”標(biāo)簽,如下所示:

intermediate/../../_static/img/tensorboard_model_viz.png

繼續(xù)并雙擊“ Net”以展開它,查看組成模型的各個(gè)操作的詳細(xì)視圖。

TensorBoard 具有非常方便的功能,可在低維空間中可視化高維數(shù)據(jù),例如圖像數(shù)據(jù); 接下來我們將介紹。

4.在 TensorBoard 中添加一個(gè)“投影儀”

我們可以通過 add_embedding 方法可視化高維數(shù)據(jù)的低維表示

  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()

現(xiàn)在,在 TensorBoard 的“投影儀”選項(xiàng)卡中,您可以看到這 100 張圖像-每個(gè)圖像 784 維-向下投影到三維空間中。 此外,這是交互式的:您可以單擊并拖動(dòng)以旋轉(zhuǎn)三維投影。 最后,有兩個(gè)技巧可以使可視化效果更容易看到:在左上方選擇“顏色:標(biāo)簽”,并啟用“夜間模式”,這將使圖像更容易看到,因?yàn)樗鼈兊谋尘笆前咨模?/p>

intermediate/../../_static/img/tensorboard_projector.png

現(xiàn)在我們已經(jīng)徹底檢查了我們的數(shù)據(jù),接下來讓我們展示TensorBoard 如何從訓(xùn)練開始就可以使跟蹤模型的訓(xùn)練和評(píng)估更加清晰。

5.使用 TensorBoard 跟蹤模型訓(xùn)練

在前面的示例中,我們僅每 2000 次迭代打印該模型的運(yùn)行損失。 現(xiàn)在,我們將運(yùn)行損失記錄到 TensorBoard 中,并通過plot_classes_preds函數(shù)查看模型所做的預(yù)測(cè)。

  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

最后,讓我們使用與之前教程相同的模型訓(xùn)練代碼來訓(xùn)練模型,但是每 1000 批將結(jié)果寫入 TensorBoard,而不是打印到控制臺(tái)。 這是通過 add_scalar 函數(shù)完成的。

此外,在訓(xùn)練過程中,我們將生成一幅圖像,顯示該批次中包含的四幅圖像的模型預(yù)測(cè)與實(shí)際結(jié)果。

  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')

現(xiàn)在,您可以查看“標(biāo)量”選項(xiàng)卡,以查看在 15,000 次訓(xùn)練迭代中繪制的運(yùn)行損失:

intermediate/../../_static/img/tensorboard_scalar_runs.png

此外,我們可以查看整個(gè)學(xué)習(xí)過程中模型在任意批次上所做的預(yù)測(cè)。 查看“圖像”選項(xiàng)卡,然后在“預(yù)測(cè)與實(shí)際”可視化條件下向下滾動(dòng)以查看此內(nèi)容; 這向我們表明,例如,僅經(jīng)過 3000 次訓(xùn)練迭代,該模型就能夠區(qū)分出視覺上截然不同的類,例如襯衫,運(yùn)動(dòng)鞋和外套,盡管它并沒有像后來的訓(xùn)練那樣有信心:

intermediate/../../_static/img/tensorboard_images.png

在之前的教程中,我們研究了模型訓(xùn)練后的每類準(zhǔn)確性; 在這里,我們將使用 TensorBoard 繪制每個(gè)類的精度回召曲線。

6.使用 TensorBoard 評(píng)估經(jīng)過訓(xùn)練的模型

  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)

現(xiàn)在,您將看到一個(gè)“ PR Curves”選項(xiàng)卡,其中包含每個(gè)類別的精度回召曲線。 繼續(xù)戳一下; 您會(huì)發(fā)現(xiàn)在某些類別中,模型的“曲線下面積”接近 100%,而在另一些類別中,該面積更低:

intermediate/../../_static/img/tensorboard_pr_curves.png

這是 TensorBoard 和 PyTorch 與之集成的介紹。 當(dāng)然,您可以在 Jupyter Notebook 中完成 TensorBoard 所做的所有操作,但是使用 TensorBoard,默認(rèn)情況下,您還可以獲得交互式視覺效果。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)