[pytorch] 使用tensorboardX可视化训练过程

在训练神经网络时,我们希望能更直观地了解训练情况,包括损失曲线、输入图片、输出图片、卷积核的参数分布等信息。这些信息能帮助我们更好地监督网络的训练过程,并为参数优化提供方向和依据。最简单的办法就是打印输出,但其只能打印数值信息,不够直观,同时无法查看分布、图片、声音等。接下来,将介绍两个深度学习中常用的可视化工具之一:Tensorboard

安装tensorboardX

安装非常简单,主要分为以下三步:

  1. 安装tensorflow

pip3 install tensorflow

  1. 安装tensorboard

pip3 install tensorboard

  1. 安装tensorboardX

pip3 install tensorboardX

我在安装的过程中,尝试了跳过了第二步(原因是很多网上的教程没有第二步),结果会报错,所以最好按照这三步进行安装。

使用tensorboardX

安装好以后在使用时,需要导入这个包:

from tensorboardX import SummaryWriter

创建writer实例

# Creates writer1 object.
# The log will be saved in 'runs/exp'
writer1 = SummaryWriter('runs/exp')

# Creates writer2 object with auto generated file name
# The log directory will be something like 'runs/Aug20-17-20-33'
writer2 = SummaryWriter()

# Creates writer3 object with auto generated file name, the comment will be appended to the filename.
# The log directory will be something like 'runs/Aug20-17-20-33-resnet'
writer3 = SummaryWriter(comment='resnet')

以上展示了三种不同的初始化方法,会使得生成的日志保存在不同的文件下面。

接下来,我们就可以调用 SummaryWriter 实例的各种 add_something 方法向日志中写入不同类型的数据了。想要在浏览器中查看可视化这些数据,只要在命令行中开启 tensorboard 即可:

tensorboard --logdir=<your_log_dir>

其中的 <your_log_dir> 既可以是单个 run 的路径,如上面 writer1 生成的 runs/exp;也可以是多个 run 的父目录,如 runs/ 下面可能会有很多的子文件夹,每个文件夹都代表了一次实验,我们令 --logdir=runs/ 就可以在 tensorboard 可视化界面中方便地横向比较 runs/ 下不同次实验所得数据的差异。

使用add方法添加记录

添加数字

使用add_scalar添加数字型记录:

add_scalar(tag, scalar_value, global_step=None, walltime=None)

参数

  • tag (string): 数据名称,不同名称的数据使用不同曲线展示
  • scalar_value (float): 数字常量值
  • global_step (int, optional): 训练的 step
  • walltime (float, optional): 记录发生的时间,默认为 time.time()

需要注意,这里的 scalar_value 一定是 float 类型,如果是 PyTorch scalar tensor,则需要调用 .item() 方法获取其数值。我们一般会使用 add_scalar 方法来记录训练过程的 loss、accuracy、learning rate 等数值的变化,直观地监控训练过程。

示例

writer = SummaryWriter(log_dir='./accuracy')

for epoch in range(EPOCH):
    train(epoch)
    
    if (epoch+1) % 5 ==0:
        accuracy = test(epoch)
        writer.add_scalar('Test',accuracy, epoch)

writer.close()

添加图片

使用 add_image 方法来记录单个图像数据。注意,该方法需要 pillow 库的支持。

add_image(tag, img_tensor, global_step=None, walltime=None, dataformats='CHW')

参数

  • tag (string): 数据名称
  • img_tensor (torch.Tensor / numpy.array): 图像数据
  • global_step (int, optional): 训练的 step
  • walltime (float, optional): 记录发生的时间,默认为 time.time()
  • dataformats (string, optional): 图像数据的格式,默认为 ‘CHW’,即 Channel x Height x Width,还可以是 ‘CHW’、‘HWC’ 或 ‘HW’ 等

示例

from tensorboardX import SummaryWriter
import cv2 as cv

writer = SummaryWriter('runs/image_example')
for i in range(1, 6):
    writer.add_image('countdown',
                     cv.cvtColor(cv.imread('{}.jpg'.format(i)), cv.COLOR_BGR2RGB),
                     global_step=i,
                     dataformats='HWC')

add_image 方法只能一次插入一张图片。如果要一次性插入多张图片,有两种方法:

  1. 使用 torchvision 中的 make_grid 方法 官方文档将多张图片拼合成一张图片后,再调用 add_image 方法。
  2. 使用 SummaryWriter 的 add_images 方法 官方文档,参数和 add_image 类似,在此不再另行介绍。

添加运行图

使用 add_graph 方法来可视化一个神经网络。

add_graph(model, input_to_model=None, verbose=False, **kwargs)

参数

  • model (torch.nn.Module): 待可视化的网络模型
  • input_to_model (torch.Tensor or list of torch.Tensor, optional): 待输入神经网络的变量或一组变量

示例

Tensorboard有一个官方样例

添加高维嵌入向量

使用 add_embedding 方法可以在二维或三维空间可视化 embedding 向量。

add_embedding(mat, metadata=None, label_img=None, global_step=None, tag='default', metadata_header=None)

参数

  • mat (torch.Tensor or numpy.array): 一个矩阵,每行代表特征空间的一个数据点
  • metadata (list or torch.Tensor or numpy.array, optional): 一个一维列表,mat 中每行数据的 label,大小应和 mat 行数相同
  • label_img (torch.Tensor, optional): 一个形如 NxCxHxW 的张量,对应 mat 每一行数据显示出的图像,N 应和 mat 行数相同
  • global_step (int, optional): 训练的 step
  • tag (string, optional): 数据名称,不同名称的数据将分别展示

示例

add_embedding 是一个很实用的方法,不仅可以将高维特征使用PCA、t-SNE等方法降维至二维平面或三维空间显示,还可观察每一个数据点在降维前的特征空间的K近邻情况。下面例子中我们取 MNIST 训练集中的 100 个数据,将图像展成一维向量直接作为 embedding,使用 TensorboardX 可视化出来。

from tensorboardX import SummaryWriter
import torchvision

writer = SummaryWriter('runs/embedding_example')
mnist = torchvision.datasets.MNIST('mnist', download=True)
writer.add_embedding(
    mnist.train_data.reshape((-1, 28 * 28))[:100,:],
    metadata=mnist.train_labels[:100],
    label_img = mnist.train_data[:100,:,:].reshape((-1, 1, 28, 28)).float() / 255,
    global_step=0

可以发现,虽然还没有做任何特征提取的工作,但 MNIST 的数据已经呈现出聚类的效果,相同数字之间距离更近一些(有没有想到 KNN 分类器)。我们还可以点击左下方的 T-SNE,用 t-SNE 的方法进行可视化。add_embedding 方法需要注意的几点:

  1. mat 是二维 MxN,metadata 是一维 N,label_img 是四维 NxCxHxW!
  2. label_img 记得归一化为 0-1 之间的 float 值

其他

TensorboardX 除了上述的常用方法之外,还有许多其他方法如 add_audioadd_figure 等,感兴趣的朋友可以参考[官方文档]。相信读了这篇文章过后,你已经能够类比熟练调用其他的方法了。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页