可视化工具Visdom的使用

Visdom介绍

​ Visdom是Facebook专为PyTorch开发的实时可视化工具包,其作用相当于TensorFlow中的Tensorboard,灵活高效且界面美观。如果想更多了解关于Visdom的使用可以参考官方文档

安装

打开cmd窗口,输入命令即可

pip install visdom

使用

要是用Visdom,需要在终端先开启监控命令,根据显示在浏览器中输入: http://localhost:8097 。监控命令有两种方式:

'''方式1'''
python -m visdom.server
'''方式2'''
直接visdom

界面

可视化工具Visdom的使用_第1张图片

  1. env被保存在$HOME/.visdom/ 这里,里面保存的是.json文件,如果json被删除,相应保存的env也就没了。
  2. 浏览器界面中environment右边可以选择env,默认是main,点击哪个env就会显示对应的绘制。
  3. clear旁边的可以保存env,再右边哪个manage只能保存view,为了将数据保存到本地,只能使用clear旁边将env保存下来

Visdom可视化函数及其参数一览

visdom基本可视化函数

vis.image : #图片
vis.line: #曲线
vis.images : #图片列表
vis.text : #抽象HTML 输出文字
vis.properties : #属性网格
vis.audio : #音频
vis.video : #视频
vis.svg : #SVG对象
vis.matplot : #matplotlib图
vis.save : #序列化状态服务端

上述函数参数

  • 注意opt的参数都可以用python字典的格式传入
opts.title : #图标题
win:#窗口名称
opts.width : #图宽
opts.height : #图高
opts.showlegend : #显示图例 (true or false)
opts.xtype : #x轴的类型 ('linear' or 'log')
opts.xlabel : #x轴的标签
opts.xtick : #显示x轴上的刻度 (boolean)
opts.xtickmin : #指定x轴上的第一个刻度 (number)
opts.xtickmax : #指定x轴上的最后一个刻度 (number)
opts.xtickvals : #x轴上刻度的位置(table of numbers)
opts.xticklabels : #在x轴上标记标签 (table of strings)
opts.xtickstep : #x轴上刻度之间的距离 (number)
opts.xtickfont :#x轴标签的字体 (dict of font information)
opts.ytype : #type of y-axis ('linear' or 'log')
opts.ylabel : #label of y-axis
opts.ytick : #show ticks on y-axis (boolean)
opts.ytickmin : #first tick on y-axis (number)
opts.ytickmax : #last tick on y-axis (number)
opts.ytickvals : #locations of ticks on y-axis (table of numbers)
opts.yticklabels : #ticks labels on y-axis (table of strings)
opts.ytickstep : #distances between ticks on y-axis (number)
opts.ytickfont : #font for y-axis labels (dict of font information)
opts.marginleft : #左边框 (in pixels)
opts.marginright :#右边框 (in pixels)
opts.margintop : #上边框 (in pixels)
opts.marginbottom: #下边框 (in pixels)
opts.lagent=['']#显示图标

应用

实时曲线绘制

  • 方法:起始点+数据点更新
from Visdom import Visdom
vis = Visdom()   #初始化visdom类。
#括号内可以添加参数,如使用“env = ‘环境名称’ ”对绘图环境进行命名。此时在可视化界面需在上方的 Environment中勾选相应的环境名称才可以将图片显示出来。如果没有env,则默认环境名称为main
'''起点'''
vis.line([0.],     #第一个点的Y坐标
         [0.],     #第一个点的X坐标
         win='train loss',  #窗口名称
         opts=dict(title = 'train_loss',xlabel='episodes',ylabel='loss') #图标题、x轴和Y轴标签
         ) #设置起点
'''模型数据'''
vis.line([1.],[1.],       #下一点的Y坐标及X坐标
         win='train loss',  ## 窗口名称 与上个窗口同名表示显示在同一个表格里
         update='append')  # 添加到上一个点的后面

从上图中可以看出:

  1. 窗口名称显示在图片的右上角;
  2. 右下角有一个Edit,点击进去,可以对图片类型等进行修改,甚至可以保存数据;
'''多条曲线绘制 实际上就是传入y值时为一个向量'''
vis = Visdom(env='my wind') # 环境名称为'my wind'
 #设置起始点
vis.line([[0.0,0.0]],    ## Y的起始点
          [0.],    ## X的起始点
         win="test loss",    ##窗口名称
         opts=dict(title='test_loss')  ## 图像标例
        )
'''模型数据'''
vis.line([[1.1,1.5]],   ## Y的下一个点
        [1.],   ## X的下一个点
        win="test loss", ## 窗口名称
        update='append'   ## 添加到上一个点后面

实际应用

'''
导入库文件
'''

import  torch
import  torch.nn as nn
import  torch.nn.functional as F
import  torch.optim as optim
from    torchvision import datasets, transforms
from visdom import Visdom
import numpy as np
'''
构建简单的模型:简单线性层+Relu函数的多层感知机
'''
class MLP(nn.Module):

   def __init__(self):
    super(MLP, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(784, 200),
            nn.ReLU(inplace=True),
            nn.Linear(200, 200),
            nn.ReLU(inplace=True),
            nn.Linear(200, 10),
            nn.ReLU(inplace=True))
    def forward(self, x):
        x = self.model(x)

        return x
batch_size = 128
earning_rate = 0.01
epochs = 10
train_loader = torch.utils.data.DataLoader(datasets.MNIST(
    'D:/data/MNIST', # 
    train=True,
   download=True,
    transform=transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.1307, ), (0.3081, ))])),
                                           batch_size=batch_size,
                                           shuffle=True)
test_loader = torch.utils.data.DataLoader(datasets.MNIST(
    'D:/Jupyter/工作准备/data/MNIST',
    train=False,
    transform=transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.1307, ), (0.3081, ))])),
                                          batch_size=batch_size,
                                          shuffle=True)

# 注意此处初始化visdom类
viz = Visdom()
# 绘制起点
viz.line([0.], [0.], win="train loss", opts=dict(title='train_loss'))
device = torch.device('cuda:0')
net = MLP().to(device)
optimizer = optim.SGD(net.parameters(), lr=learning_rate)
criteon = nn.CrossEntropyLoss().to(device)

for epoch in range(epochs):

    for batch_idx, (data, target) in enumerate(train_loader):
        data = data.view(-1, 28 * 28)
        data, target = data.to(device), target.cuda()
        logits = net(data)
        loss = criteon(logits, target)

      optimizer.zero_grad()
        loss.backward()
        # print(w1.grad.norm(), w2.grad.norm())
        optimizer.step()
       if batch_idx % 100 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
              epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))

   test_loss = 0
    correct = 0
    for data, target in test_loader:
        data = data.view(-1, 28 * 28)
       data, target = data.to(device), target.cuda()
       logits = net(data)
       test_loss += criteon(logits, target).item()

        pred = logits.argmax(dim=1)
       correct += pred.eq(target).float().sum().item()

    test_loss /= len(test_loader.dataset)
    # 绘制epoch以及对应的测试集损失loss
  	viz.line([test_loss], [epoch], win="train loss", update='append') # win是必须的 
   	print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
   	test_loss, correct, len(test_loader.dataset), correct / len(test_loader.dataset)))

远程显示服务器上的代码结果

  1. 在xshell上运行visdom
  2. 通过浏览器访问远程服务器地址的8097(默认)端口来远程观察模型的训练情况
    • 假设服务器ip为192.168.1.2
    • 在本地浏览器上打开192.168.1.2:8097即可观察到训练结果

暂停与恢复

经常需要的一个功能是,train到一个阶段,暂停/终止训练,下次训练想从断点处继续。因为visdom正常会用新图覆盖原来的图,所以要在这里读取以前的数据,然后接着绘制数据。

第一步需要保存env,env被保存在$HOME/.visdom/ 这里,里面保存的是.json文件,如果json被删除,相应保存的env也就没了。

保存方式如下:

浏览器中的界面,点击manage environment——设置环境名——fork——save(这里的fork意指保存json文件,即保存在$HOME/.visdom/ 这里)。保存完并没有什么提示,而且保存界面不会消失,很奇怪,为了保险反正每次点完等一小会吧。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NNH1RBiU-1659922203818)(https://cdn.jsdelivr.net/gh/Yicen-y/Markdown_image@main/images/20210402213453.png)]

保存完之后,从代码中获取visdom保存的数据。使用如下代码可以获得之前保存下来的数据

vis=Visdom(port=8888)
print(vis.get_env_list())
# 可以得到保存的env list
print(vis.win_exists(win="train",env="main1.0"))
# 可以查看指定win是否存在,此处win不是保存的view的名字,可是代码中指定的win
win_data=vis.get_window_data(win="train",env="main1.0")
# 可以获得指定win数据,即我们想恢复的数据,但是要指定号win和env要不然会是None
# 返回的是str数据,但是其实可以使用json来处理,因为数据本来就是储存在json中的
pre_data= json.loads(win_data)
# 这样就将str转换回dict,可以更方便的处理了
xdata=pre_data["content"]["data"][0]["x"]
ydata=pre_data["content"]["data"][0]["y"]
# 得到横纵轴的数据,是float数据的list
  1. 将旧数据与新数据拼接在一起,共同绘制。。在保存在本地中的json中读取数据继续绘制。
 with open("$HOME/.visdom/main1.0.json","r") as f:predata=json.load(f)
# 当然此处地址不能直接写$HOME,应该用正确的地址,剩下的就和上面的处理一样了
  1. 数据拼接
ydata.append(0.5)
vis.line(
       X=np.arange(len(ydata)),
       Y=np.array(ydata),
       opts=dict(title="try"),
       win="little"
)
  1. 配合matplotlib画折线
import matplotlib.pyplot as plt
from visdom import Visdom
   
viz=Visdom(port=8888)   #(需要先在cmd中激活python -m visdom.server -port 8888)
plt.plot([1,2,3,4])  #默认给定的是y轴数据,x轴会自动从0补全
plt.plot([10,20,30,40])  #默认给定的是y轴数据,x轴会自动从0补全
#plt.axis([0,1,0,3]) 可以使用这个分别指定x轴的起始终止、y轴的起始终止
plt.title("折线")
viz.matplot(plt)

参考

  1. 轻松学 Pytorch–Visdom 可视化
  2. Pytorch中文网
  3. Visdom官方Github指南
  4. Visdom PyTorch可视化工具(https://www.cnblogs.com/luckforefforts/p/13736158.html#visdom-pytorch可视化工具)https://www.cnblogs.com/luckforefforts/p/13736158.html (这个帖子讲了环境的保存和重新载入)

你可能感兴趣的:(Pytorch学习,python)