TensorBoard 是 TensorFlow 团队开发的一款可视化工具,方便观察和调整机器学习的数据集、模型、超参数和训练结果等等。但是不知道为什么,PyTorch 调用 TensorBoard,要比 TensorFlow 方便简单得多,这何尝不是一种 NTR……


用法和效果

一个使用了 TensorBoard 的 torch 项目的主文件一般是这样的(把和 TensorBoard 无关的部分都注释掉了):

# imports
# import matplotlib.pyplot as plt
# import numpy as np

# import torch
# import torchvision
# import torchvision.transforms as transforms

# import torch.nn as nn
# import torch.nn.functional as F
# import torch.optim as optim

from torch.utils.tensorboard import SummaryWriter

# # transforms
# transform = transforms.Compose(
#     [transforms.ToTensor(),
#     transforms.Normalize((0.5,), (0.5,))])

# # datasets
# trainset = torchvision.datasets.FashionMNIST('./data',
#     download=True,
#     train=True,
#     transform=transform)
# testset = torchvision.datasets.FashionMNIST('./data',
#     download=True,
#     train=False,
#     transform=transform)

# # dataloaders
# trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
#                                         shuffle=True, num_workers=2)
# testloader = torch.utils.data.DataLoader(testset, batch_size=4,
#                                         shuffle=False, num_workers=2)

# # constant for classes
# classes = ('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
#         'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle Boot')

# class Net(nn.Module):
#     def __init__(self):
#         super(Net, self).__init__()
#         self.conv1 = nn.Conv2d(1, 6, 5)
#         self.pool = nn.MaxPool2d(2, 2)
#         self.conv2 = nn.Conv2d(6, 16, 5)
#         self.fc1 = nn.Linear(16 * 4 * 4, 120)
#         self.fc2 = nn.Linear(120, 84)
#         self.fc3 = nn.Linear(84, 10)
#     def forward(self, x):
#         x = self.pool(F.relu(self.conv1(x)))
#         x = self.pool(F.relu(self.conv2(x)))
#         x = x.view(-1, 16 * 4 * 4)
#         x = F.relu(self.fc1(x))
#         x = F.relu(self.fc2(x))
#         x = self.fc3(x)
#         return x
# net = Net()

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

# default `log_dir` is "runs" - we'll be more specific here
writer = SummaryWriter('runs/fashion_mnist_experiment_1')

running_loss = 0.0
for epoch in range(1):  # loop over the dataset multiple times
    for i, data in enumerate(trainloader, 0):
        # # get the inputs; data is a list of [inputs, labels]
        # inputs, labels = data

        # # zero the parameter gradients
        # optimizer.zero_grad()

        # # forward + backward + optimize
        # outputs = net(inputs)
        # loss = criterion(outputs, labels)
        # loss.backward()
        # optimizer.step()

        # running_loss += loss.item()
        if i % 1000 == 999:    # every 1000 mini-batches...
            # ...log the running loss
            writer.add_scalar('training loss',
                            running_loss / 1000,
                            epoch * len(trainloader) + i) # 注意这一行!
# print('Finished Training')

正常情况下,使用了tensorboard 的项目在训练的过程中,可以用网页浏览器打开网址 localhost:6006,应该可以看到和下图类似但不同的画面:

tensorboard
tensorboard

下面来仔细分解。

代码分解

引入 TensorBoard 需要下面一行代码:

from torch.utils.tensorboard import SummaryWriter

从名字就能看出来,SummaryWriter 是一个 class。粗略用了一下文档页面的业内搜索,好像整个 torch.utils.tensorboard 就只有这一个 class。

新建一个这个类的实例:

writer = SummaryWriter('runs/fashion_mnist_experiment_1')

这一步会在当前工作环境下新建一个 /runs 文件夹,

要想显示导航栏上的“SCALARS”、“IMAGES”等等选项卡,并且让自己想观察的数据显示在各自类别的选项卡里,需要调用 SummaryWriter 下面的各种方法,比如 add_scalar(), add_image().

各种方法

用法和效果举例如下:

  • add_scalar(): 在一张图中画出一个标量指标随学习迭代的变化曲线
    • tag: 图片的标题。
    • scalar_value: 指标的值,也就是纵坐标。
    • global_step: 全局迭代次数,也就是横坐标。
  • add_scalars(): 在一张图中同时画出多个指标随学习迭代的变化曲线
    • main_tag: 图片的标题
    • tag_scalar_dict: 一个字典,字典的键是变量的名字,值是各个变量的纵坐标。
    • global_step: 全局迭代次数,也就是横坐标。
  • add_custome_scalars(): 没有用过,也没见到例子,不太明白。根据描述像是把之前 add_scalar()add_scalars() 的结果重新组合,对 SCALARS 选项卡重新排版。每个 SummaryWriter 只能运行一次,可以在训练开始前运行,也可以在之后。
    • layout: 只有一个这参数,是一个字典,字典的键像是新图片/章节的名字,值是下一级字典或者是 add_scalar() 出现过/将要出现的 tag 参数。
  • add_figure(): 显示 matplotlib 画出的图表
    • tag: 标题
    • figure: 图表,要求类型为 matplotlib.pyplot.figure
    • global_step:迭代次数,效果如何 没试过。
  • add_histogram(): 在一张图中画出一个样本的直方图,以及这个直方图随迭代变化的规律。这是个三维图片,x 轴是直方图的取值范围,y 轴是迭代次数,z 轴是直方图的频率值。
    • tag: 图片标题。
    • values: 一个 torch.Tensor 或者 numpy.array ,用于绘制直方图的样本.
    • global_step: 迭代次数,y 轴分量。
    • bins: 取样间隔参数,numpy.histogram() 中用到的。 ****
  • add_graph(): 一般用于在训练前画出神经网络的图状结构
    • model: 要画的模型,类型是 torch.nn.Module
    • input_to_model=None: (可选)输入模型的变量。
  • add_mesh(): 三维点云
    • tag: 表格标题。
    • vertices: 顶点三维坐标的列表。
    • colors: 顶点的颜色。
    • faces: (可选)没看懂 (Indices of vertices within each triangle.)
    • config_dict: 用于画图的 ThreeJS 的参数。
    • global_step: 迭代次数。
  • add_embeddding(): 神经网络的输入一般是高维向量,此工具将高维数据投影到三维空间,然后画出图像,方便我们感知训练集内样本之间的关系。
    • mat: 一个矩阵,每一行都是一个要处理的向量。
    • metadata: 标记文字,一般是列表。
    • label_img: 标记图片,显示在每个数据点旁边的
    • global_step: 迭代次数,一般没人用。
    • tag: 图片标题。
  • add_pr_curve(): 准确率 (precision) -召回率 (call back) 曲线。准确率=真阳性/(真阳性+假阳性),召回率=真阳性/(真阳性+假阴性)
    • tag: 图片标题。
    • labels: Ground truth 数据,每个数据点对应一个布尔值。
    • predictions: 模型的输出,每个数据点对应一个 [0,1] 之间的实数。
    • global_step: 迭代次数。
    • num_thresholds:用于画出 PR 曲线的阈值的数目。
  • add_hparams(): 比较不同次运行之间的超参数。没太看懂。
    • hparam_dict: 超参数的名称和取值
    • metric_dict: metric (不知道怎么翻译)的名称和取值
    • hparam_domain_discrete: (可选)字典,超参数的名称和有限个可能的取值。
    • run_name: 运行的名称,将会成为 logdir 的一部分。
  • add_image(): 在 IMAGES 选项卡中显示一张图片
    • tag: 图片名称。
    • img_tensor: 一个 torch.Tensor 或者 numpy.array,被显示的图片。对应于下面的 dataformats 参数。
    • global_step: 迭代次数,没见有人在显示图片的时候用过。
    • dataformats=’CHW’: 图片各维度的顺序。默认是“颜色-高度-宽度”。
  • add_images(): 并列显示多张图片
    • tag: 图片组的标题。
    • img_tensor: 一个 torch.Tensor 或者 numpy.array,被显示的图片。图片个维度的含义由 datadormats 给出。
    • global_step: 迭代次数,没见有人在显示图片的时候用过。
    • datadormats=’NCHW’: 图片各维度的顺序。默认为“图片序号-颜色-高度-宽度”。
  • add_video(): 略
  • add_audio(): 略
  • add_text(): 略
本文收录于以下合集: