Pytorch使用TensorboardX可视化

1.前言
tensorflow框架可以使用tensorboard这一高级的可视化的工具,而Pytorch可以使用tensorboardX可视化

2.环境依赖

python3.6+
pytorch0.4.0+
tensorboardX : pip install tensorboardX
注意:Pytorch下使用tensorboardX不需要安装tensorflow

3.教程
本文主要介绍scalar 、 graph和feature maps

3.1 scale教程

import numpy as np
from tensorboardX import SummaryWriter

writer = SummaryWriter()
for epoch in range(100):
    # 参数依次为生成的文件所放的目录、要保存的值、步数;第二个参数是可以理解为Y轴数据,第三个参数可以理解为X轴数据;当Y轴数据不止一个时,可以使用writer.add_scalars()
    writer.add_scalar('scalar/test', np.random.rand(), epoch)
    # writer.add_scalars添加许多的scalars,参数为生成文件所放的目录、要保存的键值对
    writer.add_scalars('scalar/scalars_test', {'xsinx': epoch * np.sin(epoch), 'xcosx': epoch * np.cos(epoch)}, epoch)

writer.close()

运行上述代码,会生成runs文件夹,里面就保存了我们要可视化的东西

可视化

打开cmd或者终端,输入tensorboard --logdir=filename
这里的filename必须是你的文件的上一级目录,不然会报错No dashboards are active for the current data set
以下图为例
在这里插入图片描述
我这里的runs文件夹下的Nov7_16-08-14文件夹下有我需要可视化的内容,那么在命令行中输入的内容是
在这里插入图片描述
这时会在终端里面显示网址,复制到浏览器里面就可以看到结果
在这里插入图片描述

3.2 graph教程

主要是可视化网络结构

import torch
import torch.nn as nn
from tensorboardX import SummaryWriter
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Sequential(     #input_size=(1*28*28)
            nn.Conv2d(1, 6, 5, 1, 2),
            nn.ReLU(),      #(6*28*28)
            nn.MaxPool2d(kernel_size=2, stride=2),  #output_size=(6*14*14)
        )
        self.conv2 = nn.Sequential(
            nn.Conv2d(6, 16, 5),
            nn.ReLU(),      #(16*10*10)
            nn.MaxPool2d(2, 2)  #output_size=(16*5*5)
        )
        self.fc1 = nn.Sequential(
            nn.Linear(16 * 5 * 5, 120),
            nn.ReLU()
        )
        self.fc2 = nn.Sequential(
            nn.Linear(120, 84),
            nn.ReLU()
        )
        self.fc3 = nn.Linear(84, 10)
 
    # 定义前向传播过程,输入为x
    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        # nn.Linear()的输入输出都是维度为一的值,所以要把多维度的tensor展平成一维
        x = x.view(x.size()[0], -1)
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x
 
dummy_input = torch.rand(13, 1, 28, 28) #假设输入13张1*28*28的图片
model = LeNet()
with SummaryWriter(comment='LeNet') as w:
    # 第一个参数为需要保存的模型,第二个参数为输入值,元组类型
    w.add_graph(model, (dummy_input, ))

运行代码,生成一个文件夹,如下图,里面又保存了我们需要可视化的东西
在这里插入图片描述
打开终端,输入tensorboard --logdir=Nov07_16-35-05_gaoyao-N8xEJEKLeNet,复制网址,得到下图
在这里插入图片描述
接着点击上面的GRAPHS,就出现了网络结构。双击LeNet就出现了详细的网络结构。

3.3 feature maps教程

import torch 
import torch.nn as nn
from torchvision import models, transforms, datasets
from torchvision.utils import make_grid
from tensorboardX import SummaryWriter
from PIL import Image
'''动起手来就已经成功一半了'''
net = models.vgg16(pretrained= True).eval()  # 用预训练好的vgg16可视化lenna图片各层features map

'''我要利用net这个模型实例重建一个模型,大改net的话问题太多了'''
class Map(nn.Module):
    def __init__(self):
        super(Map, self).__init__()
        self.model = nn.Sequential()
        self.names = []
        i = j_1 = j_2 = j_3 = j_4 = 1
        # 卷积-BN-激活-池化(遇到池化就划分一截)为一个部分,用i表示;j_1,2,3,4表示每个部分内的卷积,BN,激活,池化
        '''实验过后发现,a=b=1,对a变化不影响b,尽管id一样;a,b=1,1时也不会相互影响'''
        for layer in net.features.children():  # 我们不需要classifier中的全连接等层(这个for循环主要就是为了给每层重新起个名字)
            if isinstance(layer, nn.Conv2d):
                name = 'conv%d_%d'%(i, j_1)
                j_1 += 1
            elif isinstance(layer, nn.BatchNorm2d):
                name = 'bn%d_%d'%(i, j_2)
                j_2 += 1
            elif isinstance(layer, nn.ReLU):
                name = 'relu%d_%d'%(i, j_3)
                j_3 += 1
            elif isinstance(layer, nn.MaxPool2d):
                name = 'maxpool%d_%d'%(i, j_4)
                i += 1
                j_1 = j_2 = j_3 = 1
            #else:
                #raise RuntimeError('Unrecognized layer: %s'%(layer.__class__.__name__)
            self.model.add_module(name, layer)  # 把layer添加到model并取名为name
            self.names.append(name)
        #print(self.model)  # 也可以打印出来模型看看哦
    def forward(self, input_img):
        writer = SummaryWriter(log_dir='feature_map')  # 定义tensorboard文件夹名称
        for i, layer in enumerate(self.model.children()):
            print(self.names[i])  # 输出这层名字
            print(input_img.size())
            input_img = layer(input_img) # feature maps
            input_img = input_img.permute(1, 0, 2 ,3)  # 第0和第1维转置,交换位置,是为了适应make_grid函数
            print(input_img.size())  # 打印维度看看,变化成功了
            # make_grid的作用是将若干幅图像拼成一幅图像; 
            # torchvision.utils.make_grid(tensor, nrow, padding, normalize, range, scale_each, padding_value)
            # 参数依次为:相同大小的图片列表(形状为N*C*H*W)、网格每一行显示的图片数(默认为8)、填充数量即子图像与子图像的间距(默认为2)、normal为True,减去最小像素值,除以最大像素值,将结果限制到(0,1)
            # range(min, max)--上一步提到的最小、最大像素值、padding_value:填充像素值
            result = make_grid(input_img, normalize=True)  # 一个channel代表一张图片,把每层的多个图片拼接成一张大图
            writer.add_image(self.names[i], result, i)  # 每次写入时step为i,不写这个step不报错,但你会发现新图可能会覆盖旧图(没试过)
            input_img = input_img.transpose(1, 0)  # Tensor维度还要变回去,否则下次循环,维度不是BCHW的话layer(input_img)会出错的
        writer.close()
        # permute(1,0,2,3)需要把所有维度都写出来;transpose(1,0)可以只把需要转置的几个维度写出来;功能是差不多的
model =  Map()  # 新模型实例
image_path = '1.jpg'
image = Image.open(image_path)
transform = transforms.Compose([
                                transforms.ToTensor(), #转为Tensor格式,并将值取在[0,1]中
                                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) #标准化,得到在[-1,1]的值
                                ])
image = transform(image).unsqueeze(0)  # 图片有三个通道,而VGG等网络的输入都需要BCHW,增加一个虚拟维度

model(image)  # 让新模型跑起来(坐等结果吧)

执行完之后,也会生成文件夹feature_map,在终端输入tensorboard --logdir=feature_map
打开浏览器即可看到效果
在这里插入图片描述
可能会遇到的错误
TypeError: clamp_(): argument ‘min’ must be Number, not Tensor
解决方法:在所安装的torchvision的utils.py的60行,改为下面的代码,可能是版本问题。

norm_ip(t, float(t.min()), float(t.max()))

2019.11.21

训练loss可视化

import torch
import torch.nn as nn
from tensorboardX import SummaryWriter
from matplotlib import pyplot as plt
import numpy as np

input_size = 1
output_size = 1
num_epoches = 60
learning_rate = 0.01
writer = SummaryWriter(comment = 'Linear')
x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],
                    [9.779], [6.182], [7.59], [2.167], [7.042],
                    [10.791], [5.313], [7.997], [3.1]], dtype=np.float32)
y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                    [3.366], [2.596], [2.53], [1.221], [2.827],
                    [3.465],[1.65], [2.904], [1.3]], dtype=np.float32)

model = nn.Linear(input_size, output_size)
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr= learning_rate)

for epoch in range(num_epoches):
    inputs = torch.from_numpy(x_train)
    targets = torch.from_numpy(y_train)
    output = model(inputs)
    loss = criterion(output, targets)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    writer.add_scalar('Train', loss, epoch)
    if (epoch + 1) % 5 == 0:
        print('Epoch {}/{}, loss:{:.4f}'.format(epoch + 1, num_epoches, loss.item()))

运行生成runs文件夹,进入runs文件夹
在这里插入图片描述
终端输入tensorboard --logdir=Nov21_09-30-47_gaoyao-N8xEJEKLinear ,在浏览器输入网址即可
在这里插入图片描述

参考
https://zhuanlan.zhihu.com/p/54947519utm_source=wechat_session&utm_medium=social&utm_oi=697408796275777536

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值