• 使用Tensorboard在 PyTorch 中进行可视化


    1. import torch
    2. import numpy as np
    3. import torch.nn as nn
    4. import torch.nn.functional as F
    5. from PIL import Image
    6. from torchvision import transforms
    7. from torchvision import models,datasets
    8. torch.__version__

    Tensorboard 简介

    Tensorboard是tensorflow内置的一个可视化工具,它通过将tensorflow程序输出的日志文件的信息可视化使得tensorflow程序的理解、调试和优化更加简单高效。 Tensorboard的可视化依赖于tensorflow程序运行输出的日志文件,因而tensorboard和tensorflow程序在不同的进程中运行。 TensorBoard给我们提供了极其方便而强大的可视化环境。它可以帮助我们理解整个神经网络的学习过程、数据的分布、性能瓶颈等等。

    tensorboard虽然是tensorflow内置的可视化工具,但是他们跑在不同的进程中,所以Github上已经有大神将tensorboard应用到Pytorch中 链接在这里

    Tensorboard 安装

    首先需要安装tensorboard

    pip install tensorboard

    ~~ 然后再安装tensorboardx ~~

    ~~ pip install tensorboardx ~~ pytorch 1.1以后的版本内置了SummaryWriter 函数,所以不需要再安装tensorboardx了

    安装完成后与 visdom一样执行独立的命令 tensorboard --logdir logs 即可启动,默认的端口是 6006,在浏览器中打开 http://localhost:6006/ 即可看到web页面。

    这里要说明的是 微软的Edge浏览器css会无法加载,使用chrome正常显示

    页面

    与visdom不同,tensorboard针对不同的类型人为的区分多个标签,每一个标签页面代表不同的类型。 下面我们根据不同的页面功能做个简单的介绍,更多详细内容请参考官网

    SCALAR

    对标量数据进行汇总和记录,通常用来可视化训练过程中随着迭代次数准确率(val acc)、损失值(train/test loss)、学习率(learning rate)、每一层的权重和偏置的统计量(mean、std、max/min)等的变化曲线

    IMAGES

    可视化当前轮训练使用的训练/测试图片或者 feature maps

    GRAPHS

    可视化计算图的结构及计算图上的信息,通常用来展示网络的结构

    HISTOGRAMS

    可视化张量的取值分布,记录变量的直方图(统计张量随着迭代轮数的变化情况)

    PROJECTOR

    全称Embedding Projector 高维向量进行可视化

    使用

    在使用前请先去确认执行tensorboard --logdir logs 并保证 http://localhost:6006/ 页面能够正常打开

    图像展示

    首先介绍比较简单的功能,查看我们训练集和数据集中的图像,这里我们使用现成的图像作为展示。这里使用wikipedia上的一张猫的图片这里

    引入 tensorboardX 包

    1. # 这里的引用也要修改成torch的引用
    2. #from tensorboardX import SummaryWriter
    3. from torch.utils.tensorboard import SummaryWriter
    1. cat_img = Image.open('./1280px-Felis_silvestris_catus_lying_on_rice_straw.jpg')
    2. cat_img.size

    (1280, 853)
    
    

    这是一张1280x853的图,我们先把她变成224x224的图片,因为后面要使用的是vgg16

    1. transform_224 = transforms.Compose([
    2. transforms.Resize(224), # 这里要说明下 Scale 已经过期了,使用Resize
    3. transforms.CenterCrop(224),
    4. transforms.ToTensor(),
    5. ])
    6. cat_img_224=transform_224(cat_img)

    将图片展示在tebsorboard中:

    1. writer = SummaryWriter(log_dir='./logs', comment='cat image') # 这里的logs要与--logdir的参数一样
    2. writer.add_image("cat",cat_img_224)
    3. writer.close()# 执行close立即刷新,否则将每120秒自动刷新

    浏览器访问 http://localhost:6006/#images 即可看到猫的图片

    更新损失函数

    更新损失函数和训练批次我们与visdom一样使用模拟展示,这里用到的是tensorboard的SCALAR页面

    1. x = torch.FloatTensor([100])
    2. y = torch.FloatTensor([500])
    3. for epoch in range(30):
    4. x = x * 1.2
    5. y = y / 1.1
    6. loss = np.random.random()
    7. with SummaryWriter(log_dir='./logs', comment='train') as writer: #可以直接使用python的with语法,自动调用close方法
    8. writer.add_histogram('his/x', x, epoch)
    9. writer.add_histogram('his/y', y, epoch)
    10. writer.add_scalar('data/x', x, epoch)
    11. writer.add_scalar('data/y', y, epoch)
    12. writer.add_scalar('data/loss', loss, epoch)
    13. writer.add_scalars('data/data_group', {'x': x,
    14. 'y': y}, epoch)

    浏览器访问 http://localhost:6006/#scalars 即可看到图形

    使用PROJECTOR对高维向量可视化

    PROJECTOR的的原理是通过PCA,T-SNE等方法将高维向量投影到三维坐标系(降维度)。Embedding Projector从模型运行过程中保存的checkpoint文件中读取数据,默认使用主成分分析法(PCA)将高维数据投影到3D空间中,也可以通过设置设置选择T-SNE投影方法,这里做一个简单的展示。

    我们还是用第三章的mnist代码

    1. BATCH_SIZE=512
    2. EPOCHS=20
    3. train_loader = torch.utils.data.DataLoader(
    4. datasets.MNIST('data', train=True, download=True,
    5. transform=transforms.Compose([
    6. transforms.ToTensor(),
    7. transforms.Normalize((0.1307,), (0.3081,))
    8. ])),
    9. batch_size=BATCH_SIZE, shuffle=True)
    1. class ConvNet(nn.Module):
    2. def __init__(self):
    3. super().__init__()
    4. # 1,28x28
    5. self.conv1=nn.Conv2d(1,10,5) # 10, 24x24
    6. self.conv2=nn.Conv2d(10,20,3) # 128, 10x10
    7. self.fc1 = nn.Linear(20*10*10,500)
    8. self.fc2 = nn.Linear(500,10)
    9. def forward(self,x):
    10. in_size = x.size(0)
    11. out = self.conv1(x) #24
    12. out = F.relu(out)
    13. out = F.max_pool2d(out, 2, 2) #12
    14. out = self.conv2(out) #10
    15. out = F.relu(out)
    16. out = out.view(in_size,-1)
    17. out = self.fc1(out)
    18. out = F.relu(out)
    19. out = self.fc2(out)
    20. out = F.log_softmax(out,dim=1)
    21. return out
    22. model = ConvNet()
    23. optimizer = torch.optim.Adam(model.parameters())
    1. def train(model, train_loader, optimizer, epoch):
    2. n_iter=0
    3. model.train()
    4. for batch_idx, (data, target) in enumerate(train_loader):
    5. optimizer.zero_grad()
    6. output = model(data)
    7. loss = F.nll_loss(output, target)
    8. loss.backward()
    9. optimizer.step()
    10. if(batch_idx+1)%30 == 0:
    11. n_iter=n_iter+1
    12. print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
    13. epoch, batch_idx * len(data), len(train_loader.dataset),
    14. 100. * batch_idx / len(train_loader), loss.item()))
    15. #相对于以前的训练方法 主要增加了以下内容
    16. out = torch.cat((output.data, torch.ones(len(output), 1)), 1) # 因为是投影到3D的空间,所以我们只需要3个维度
    17. with SummaryWriter(log_dir='./logs', comment='mnist') as writer:
    18. #使用add_embedding方法进行可视化展示
    19. writer.add_embedding(
    20. out,
    21. metadata=target.data,
    22. label_img=data.data,
    23. global_step=n_iter)

    这里节省时间,只训练一次

    train(model, train_loader, optimizer, 0)
    Train Epoch: 0 [14848/60000 (25%)]	Loss: 0.352312
    Train Epoch: 0 [30208/60000 (50%)]	Loss: 0.202950
    Train Epoch: 0 [45568/60000 (75%)]	Loss: 0.156494
    

    打开 http://localhost:6006/#projector 即可看到效果。

    目前测试投影这部分也是有问题的,根据官网文档的代码进行测试,也显示不出来,正在找原因

    绘制网络结构

    在pytorch中我们可以使用print直接打印出网络的结构,但是这种方法可视化效果不好,这里使用tensorboard的GRAPHS来实现网络结构的可视化。 由于pytorch使用的是动态图计算,所以我们这里要手动进行一次前向的传播.

    使用Pytorch已经构建好的模型进行展示

    1. vgg16 = models.vgg16(pretrained=True) # 这里下载预训练好的模型
    2. print(vgg16) # 打印一下这个模型
    VGG(
      (features): Sequential(
        (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (1): ReLU(inplace=True)
        (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (3): ReLU(inplace=True)
        (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (6): ReLU(inplace=True)
        (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (8): ReLU(inplace=True)
        (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (11): ReLU(inplace=True)
        (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (13): ReLU(inplace=True)
        (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (15): ReLU(inplace=True)
        (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (18): ReLU(inplace=True)
        (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (20): ReLU(inplace=True)
        (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (22): ReLU(inplace=True)
        (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (25): ReLU(inplace=True)
        (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (27): ReLU(inplace=True)
        (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        (29): ReLU(inplace=True)
        (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
      )
      (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
      (classifier): Sequential(
        (0): Linear(in_features=25088, out_features=4096, bias=True)
        (1): ReLU(inplace=True)
        (2): Dropout(p=0.5, inplace=False)
        (3): Linear(in_features=4096, out_features=4096, bias=True)
        (4): ReLU(inplace=True)
        (5): Dropout(p=0.5, inplace=False)
        (6): Linear(in_features=4096, out_features=1000, bias=True)
      )
    )
    

    在前向传播前,先要把图片做一些调整

    1. transform_2 = transforms.Compose([
    2. transforms.Resize(224),
    3. transforms.CenterCrop((224,224)),
    4. transforms.ToTensor(),
    5. transforms.Normalize(mean=[0.485, 0.456, 0.406],
    6. std=[0.229, 0.224, 0.225])
    7. ])

    使用上一张猫的图片进行前向传播

    1. vgg16_input=transform_2(cat_img)[np.newaxis]# 因为pytorch的是分批次进行的,所以我们这里建立一个批次为1的数据集
    2. vgg16_input.shape
    torch.Size([1, 3, 224, 224])

    开始前向传播,打印输出值

    1. out = vgg16(vgg16_input)
    2. _, preds = torch.max(out.data, 1)
    3. label=preds.numpy()[0]
    4. label
    287

    将结构图在tensorboard进行展示

    1. with SummaryWriter(log_dir='./logs', comment='vgg161') as writer:
    2. writer.add_graph(vgg16, vgg16_input)

    对于Pytorch的版本来说,实测 SummaryWriter在处理结构图的时候是有问题的(或者是需要加什么参数,目前我还没找到),所以建议大家继续使用tensorboardx。

  • 相关阅读:
    c语言 编程及答案
    可重构柔性装配产线:为工业制造领域注入了新的活力
    ELK 日志分析系统(二)
    Jetpack 到底香不香?看完这篇就知道了
    linux安装mysql
    RK3399-PWM
    elasticsearch 之时间类型
    python可视化分析(五)-绘制边缘箱线图
    2022百度之星初赛第三场-三个因子
    内存取证之NSSCTF-OtterCTF 2018(复现赛)
  • 原文地址:https://blog.csdn.net/sikh_0529/article/details/126913954