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

60 Minutes Blitz 中,我们展示了如何加载数据,并把数据送到我们继承 nn.Module 类的模型,在训练数据上训练模型,并在测试集上测试模型。为了看到发生了什么,当模型训练的时候我们打印输出一些统计值获得对模型是否有进展的感觉。我们可以做的比这更好:PyTorch 整合了 TensorBoard,为可视化训练中的神经网络结果的工具。这篇博文说明了它的一些功能,使用可以被 torchvision.datasets 读入 PyTorch 中的 Fashion-MNIST 数据集。

在本文中,我们将学会如何:

  1. 以合适的转换(transforms)读入数据(几乎等同于之前的博文)。
  2. 设置 TensorBoard
  3. 写入 TensorBoard
  4. 使用 TensorBoard 检查模型结构
  5. 以少量的代码 TensorBoard 创建之前的可视化的交互式版本

尤其在第 5 点,我们将看到:

  • 几个检查我们训练数据的方法
  • 当训练时如何跟踪我们模型的性能(performance
  • 一旦训练之后我们如何评估我们的模型性能(performance

我们将开始于相似于 训练分类器 的模板代码。

  1. # 导包
  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. )
  15. # 数据集(datasets)
  16. trainset = torchvision.datasets.FashionMNIST(
  17. './data', download=True,
  18. train=True, transform=transform
  19. )
  20. testset = torchvision.datasets.FashionMNIST(
  21. './data', download=True,
  22. train=False, transform=transform
  23. )
  24. # 数据加载器(dataloaders)
  25. trainloader = torch.utils.data.DataLoader(
  26. trainset, batch_size=4,
  27. shuffle=True, num_workers=2
  28. )
  29. testloader = torch.utils.data.DataLoader(
  30. testset, batch_size=4,
  31. shuffle=False, num_workers=2
  32. )
  33. # 类别常量(constant for classes)
  34. classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
  35. 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot')
  36. # 显示一张图像的帮助函数
  37. # (用于下面的 `plot_classes_preds` 函数)
  38. def matplotlib_imshow(img, one_channel=False):
  39. if one_channel:
  40. img = img.mean(dim=0)
  41. img = img / 2 + 0.5 # 反规范化(unormalize)
  42. npimg = img.numpy()
  43. if one_channel:
  44. plt.imshow(npimg, cmap='Greys')
  45. else:
  46. 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,从 torch.utils 导入 tensorboard 并定义一个 SummaryWriter,我们向 TensorBoard 写入信息的关键对象。

  1. import tensorflow as tf
  2. import tensorboard as tb
  3. tf.io.gfile = tb.compat.tensorflow_stub.io.gfile
  4. from torch.utils.tensorboard import SummaryWriter
  5. # 默认 `log_dir` 是 "runs" —— 在这里我们更具体一些
  6. writer = SummaryWriter("runs/fashion_mnist_experiment_1")

注意上面这一行创建一个 runs/fashion_mnist_experiment_1 文件夹。

2. 写入 TensorBoard

现在,让我们写入一张图片到 TensorBoard —— 确切的来说,一个网格(grid)—— 使用 make_grid

  1. # 获得一些随机训练图像
  2. dataiter = iter(trainloader)
  3. images, labels = dataiter.next()
  4. # 创建图像网格(grid of images)
  5. img_grid = torchvision.utils.make_grid(images)
  6. # 显示图像
  7. matplotlib_imshow(img_grid, one_channel=True)
  8. # 写入到 TensorBoard
  9. writer.add_image('four_fashion_mnist_images', img_grid)

现在运行。

  1. tensorboard --logdir=runs

从命令行然后导航到 http://localhost:6006/ 应该会看到如下。

现在你知道如何使用 TensorBoard 了!然而,这个例子可被完成在 Jupyter Notebook 中 —— TensorBoard 真正擅长的是创建交互式可视化。我们下一步将介绍这些中的一个,在本博文的最后你会看到几个更多的例子。

3. 使用 TensorBoard 检查模型

TensorBoard 的一个强大的能力就是它可以可视化复杂的模型结构。让我们可视化我们构建的模型。

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

现在刷新 TensorBoard 你应该能从上面看到一个“Graphs”就像这样。

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

TensorBoard 对于可视化高维数据有着非常方便的特征,比如低维空间中图像数据;我们将在下一步讨论它。

4. 向 TensorBoard 添加“Projector”

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

  1. # 辅助函数
  2. def select_n_random(data, labels, n=100):
  3. '''
  4. 从一个数据集选择 n 个随机数据点和它们对应的标签
  5. '''
  6. assert len(data) == len(labels)
  7. perm = torch.randperm(len(data))
  8. return data[perm][:n], labels[perm][:n]
  9. # 选择随即图像和它们的目标索引
  10. images, labels = select_n_random(trainset.data, trainset.targets)
  11. # 对每一张图像获得类标签
  12. class_labels = [classes[lab] for lab in labels]
  13. # 载入 embeddings
  14. features = images.view(-1, 28 * 28)
  15. writer.add_embedding(
  16. features, metadata=class_labels,
  17. label_img=images.unsqueeze(1)
  18. )
  19. writer.close()

现在,在 TensorBoard 的“Projector”标签里,你可以看到这 100 张图像(每个都是 784 维)投影到三维空间中。除此之外,这还是交互式的:你可以点击并且拖拽旋转三维的投影。最终,几个小提示让可视化更轻松地看到:选择左上方的“color: label”,并且也启用“night mode”,因为它们的背景是白色,这将让图像更轻松地显示出来。

现在我们彻底地检查了我们的数据,现在让我们的展示 TensorBoard 如何更清楚的从训练开始跟踪模型训练和评估。

5. 使用 TensorBoard 跟踪模型训练

在之前的例子中,我们只是每 2000 次迭代就简单地打印输出模型的损失值(loss)。现在,我们将把运行中的损失值(loss)记录到 TensorBoard,以及通过 plot_classes_pred 函数查看模型所做的预测。

  1. # 辅助函数
  2. def images_to_probs(net, images):
  3. '''
  4. 从一个训练好的网络和一系列图像中生成预测和对应的概率
  5. '''
  6. output = net(images)
  7. # 转换输出概率到预测的类别
  8. _, preds_tensor = torch.max(output, 1)
  9. preds = np.squeeze(preds_tensor.numpy())
  10. return preds, [F.softmax(el, dim=0)[i].item() for i, el in zip(preds, output)]
  11. def plot_classes_preds(net, images, labels):
  12. '''
  13. 使用一个训练的网络生成 matplotlib 图像,以及从一个数据批量的图片和标签,
  14. 显示出网络的最高的预测和概率以及真实的标签,并且根据预测是否正确信息上色。
  15. 使用 images_to_prbs 函数。
  16. '''
  17. preds, probs = images_to_probs(net, images)
  18. # 画出批量中的图像以及预测的和真实的标签。
  19. fig = plt.figure(figsize=(12, 6))
  20. for idx in np.arange(4):
  21. ax = fig.add_subplot(1, 4, idx + 1, xticks=[], yticks=[])
  22. matplotlib_imshow(images[idx], one_channel=True)
  23. ax.set_title("{0}, {1:.1f}%\n(label: {2})".format(
  24. classes[preds[idx]],
  25. probs[idx] * 100.0,
  26. classes[labels[idx]]),
  27. color=("green" if preds[idx] == labels[idx].item() else "red")
  28. )
  29. return fig

最后,让我们使用与之前的演示相同的代码训练模型,但是将每 1000 批量的结果写入 TensorBoard 而不是打印输出到控制台(console),这一工作使用 add_scalar 函数。

另外,当我们训练时,我们将生成一张图像,显示了包含在数据批量里的四张图像的模型预测和真实结果的对比。

  1. running_loss = 0.0
  2. for epoch in range(1): # 遍历数据集多次
  3. for i, data in enumerate(trainloader, 0):
  4. # 获取输入;data 是一个列表:[inputs, labels]
  5. inputs, labels = data
  6. # 置零参数的梯度
  7. optimizer.zero_grad()
  8. # 前向传播 + 反向传播 + 优化
  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: # 每 1000 的数据批量
  15. # 记录运行的损失值(loss)
  16. writer.add_scalar('training loss', running_loss / 1000, epoch * len(trainloader) + i)
  17. # 在随机的数据批量记录一个 Matplotlib 图像,展示模型的预测
  18. writer.add_figure('predictions vs. actuals',
  19. plot_classes_preds(net, inputs, labels),
  20. global_step=epoch * len(trainloader) + i)
  21. running_loss = 0.0
  22. print('Finished Training')
  1. Finished Training

你现在可以在“SCALARS”标签下看到训练的 15,000 次的迭代运行中的 loss

此外,我们可以看到学习过程中任意的数据批量模型做的预测。在 Images 标签里,滚到 predictions vs. actuals 可视化下方查看;这向我们展示,举个例子,刚过 3000 训练迭代后,即使它还没有训练之后那样自信,模型就有能力区分视觉上有明显区分的类别,比如 shirtssneakerscoats

在之前的教程里,模型一旦训练完成,我们就看每个类别的准确率;这里,我们将使用 TensorBoard 对每一个类别画出精度—召回率曲线(precision_recall curves),这里 有一个很好的解释。

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

  1. # 1. 获得预测概率 test_size * num_classes 张量(Tensor)
  2. # 2. 获取 preds 尺寸为 test_size 张量(Tensor)
  3. # 运行时间大约为 10 秒
  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. # 辅助函数
  17. def add_pr_curve_tensorboard(class_index, test_probs, test_preds, global_step=0):
  18. '''
  19. 接收从 0 到 9 的 class_index 并且画出对应的 precision-recall curve
  20. '''
  21. tensorboard_preds = test_preds == class_index
  22. tensorboard_probs = test_probs[:, class_index]
  23. writer.add_pr_curve(classes[class_index], tensorboard_preds, tensorboard_probs, global_step=global_step)
  24. writer.close()
  25. # 画出所有的 precision-recall curve
  26. for i in range(len(classes)):
  27. add_pr_curve_tensorboard(i, test_probs, test_preds)

你现在将看到 PR CURVES 菜单标签,其中包含了每一个类别的 precision-recall curves。去四处看看,你将看到一些类别模型有接近 100% 的曲线下的面积(area under the curve),然而其它类别中,这个标记会低一点。

这是一篇关于 TensorBoard 与 PyTorch 的整合的介绍。当然,你可以在 Jupyter Notebook 做 TensorBoard 能做到的事情,但是在 TensorBoard,默认情况下可以得到交互式的视觉效果。

使用 TensorBoard 可视化模型、数据和训练的更多相关文章

  1. 利用Tensorboard可视化模型、数据和训练过程

    在60分钟闪电战中,我们像你展示了如何加载数据,通过为我们定义的nn.Module的子类的model提供数据,在训练集上训练模型,在测试集上测试模型.为了了解发生了什么,我们在模型训练时打印了一些统计 ...

  2. 利用tensorboard可视化checkpoint模型文件参数分布

    写在前面: 上周微调一个文本检测模型seglink,将特征提取层进行冻结,只训练分类回归层,然而查看tensorboard发现里面有histogram显示模型各个参数分布,看了目前这个训练模型参数分布 ...

  3. LDA模型数据的可视化

    """ 执行lda2vec.ipnb中的代码 模型LDA 功能:训练好后模型数据的可视化 """ from lda2vec import p ...

  4. 【猫狗数据集】利用tensorboard可视化训练和测试过程

    数据集下载地址: 链接:https://pan.baidu.com/s/1l1AnBgkAAEhh0vI5_loWKw提取码:2xq4 创建数据集:https://www.cnblogs.com/xi ...

  5. LUSE: 无监督数据预训练短文本编码模型

    LUSE: 无监督数据预训练短文本编码模型 1 前言 本博文本应写之前立的Flag:基于加密技术编译一个自己的Python解释器,经过半个多月尝试已经成功,但考虑到安全性问题就不公开了,有兴趣的朋友私 ...

  6. TensorFlow2.0(9):TensorBoard可视化

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...

  7. TensorFlow——TensorBoard可视化

    TensorFlow提供了一个可视化工具TensorBoard,它能够将训练过程中的各种绘制数据进行展示出来,包括标量,图片,音频,计算图,数据分布,直方图等,通过网页来观察模型的结构和训练过程中各个 ...

  8. 学习TensorFlow,TensorBoard可视化网络结构和参数

    在学习深度网络框架的过程中,我们发现一个问题,就是如何输出各层网络参数,用于更好地理解,调试和优化网络?针对这个问题,TensorFlow开发了一个特别有用的可视化工具包:TensorBoard,既可 ...

  9. 超简单tensorflow入门优化程序&&tensorboard可视化

    程序1 任务描述: x = 3.0, y = 100.0, 运算公式 x×W+b = y,求 W和b的最优解. 使用tensorflow编程实现: #-*- coding: utf-8 -*-) im ...

随机推荐

  1. OS第六章

    OS第七次实验 多进程 添加一个进程体 添加进程B,首先设置i的初值为0x1000,这样来方便程序运行时的时候能区分.其余地方与A一致. 相关变量和宏 Minix中定义了一个数组,叫做tasktab的 ...

  2. github无法访问解决方法

    windows 系统下找到目录 C:\Windows\System32\drivers\etc 打开 hosts 文件 添加以下配置 #github140.82.114.3 github.com 保存 ...

  3. linux里用户权限:~$,/$,~#,/#的区别与含义

    $表明是非root用户登录,#表示是root用户登录,它们是终端shell的命令提示符几种常用终端的命令提示符 BASH:  root账户: # ,非root账户: $KSH:  root账户: # ...

  4. Ecshop V2.7代码执行漏洞分析

    0x01 此漏洞形成是由于未对Referer的值进行过滤,首先导致SQL注入,其次导致任意代码执行. 0x02 payload: 554fcae493e564ee0dc75bdf2ebf94caads ...

  5. Python利用openpyxl带格式统计数据(2)- 处理mysql数据

    上一篇些了openpyxl处理excel数据,再写一篇处理mysql数据的,还是老规矩,贴图,要处理的数据截图: 再贴最终要求的统计格式截图: 第三贴代码: 1 ''' 2 #利用openpyxl向e ...

  6. python初学者-使用for循环做一个九九乘法表

    for i in range(1, 10): for j in range(1, i + 1): print(j, '*', i, '=', i * j, end=" ") #en ...

  7. vue watch监听不到对象,探究 watch 原理

    最近使用vue watch时,在某些模块监听不到对象的改变,无法触发回调函数. 解决: 使用watch监听对象时,只能监听到该对象初始化时已存在的key值. 如下例监听user对象,在初始化时没有ag ...

  8. ava基础MySQL存储过程 Java基础 JDBC连接MySQL数据库

    1.MySQL存储过程   1.1.什么是存储过程 带有逻辑的sql语句:带有流程控制语句(if  while)等等 的sql语句   1.2.存储过程的特点 1)执行效率非常快,存储过程是数据库的服 ...

  9. [LeetCode]319. Bulb Switcher灯泡开关

    智商压制的一道题 这个题有个数学定理: 一般数(非完全平方数)的因子有偶数个 完全平凡数的因子有奇数个 开开关的时候,第i个灯每到它的因子一轮的时候就会拨动一下,也就是每个灯拨动的次数是它的因子数 而 ...

  10. Linux嵌入式学习-烟雾传感器驱动-字符设备驱动-按键驱动

    MQ-2烟雾气敏传感器模块在X210v3开发板上的驱动. 现在需要一个MQ-2烟雾气敏传感器模块的驱动.其检测烟雾超过一定的标准后,会返回一个不同的电平,和按键驱动差不多. 但是在编写驱动的时候,需要 ...