• Python pytorch tensorflow可视化工具Visdom使用教程--堪比TensorboardX


    Python pytorch tensorflow可视化工具Visdom使用教程--堪比TensorboardX

    学习深度学习、机器学习、数据分析与科学计算的小伙伴们对数据可视化的需求是比较重视的。所以Python的第三方库种有很多Python可视化工具,比如常用的TensorboardX,而今天我要介绍的python可视化工具是与其性能效果旗鼓相当Visdom,在网上已经有比较多的简单的visdom的使用介绍了,今天俺就结合网上教程系统化地整理一下常用的一些Visdom的使用方法叭。

    概述

    Visdom:一个灵活的可视化工具,可用来对于 实时,富数据的 创建,组织和共享。支持Torch和Numpy还有pytorch。

    Visdom 可以实现远程数据的可视化,对科学实验有很大帮助。我们可以远程的发送图片和数据,并进行在ui界面显示出来,检查实验结果,或者debug.

    要用这个先要安装,对于python模块而言,安装都是蛮简单的直接pip 或者 conda 包安装:

    pip install visdom

    安装完每次要用直接输入代码打开:

    python -m visdom.server

    然后根据提示在浏览器中输入相应地址即可,默认地址为:http://localhost:8097/

    使用示例

    1. vis.text(), vis.image()

    1. import visdom # 添加visdom库
    2. import numpy as np # 添加numpy库
    3. vis = visdom.Visdom(env='test') # 设置环境窗口的名称,如果不设置名称就默认为main
    4. vis.text('test', win='main') # 使用文本输出
    5. vis.image(np.ones((3, 100, 100))) # 绘制一幅尺寸为3 * 100 * 100的图片,图片的像素值全部为1

    其中:

    visdom.Visdom(env=‘命名新环境') vis.text(‘文本', win=‘环境名') vis.image(‘图片',win=‘环境名')

    2. 画直线 .line() 一条

    1. import visdom
    2. import numpy as np
    3. vis = visdom.Visdom(env='my_windows') # 设置环境窗口的名称,如果不设置名称就默认为main
    4. x = list(range(10))
    5. y = list(range(10))
    6. # 使用line函数绘制直线 并选择显示坐标轴
    7. vis.line(X=np.array(x), Y=np.array(y), opts=dict(showlegend=True))

    vis.line([x], [y], opts=dict(showlegend=True)[展示说明])

    两条

    1. import visdom
    2. import numpy as np
    3. vis = visdom.Visdom(env='my_windows')
    4. x = list(range(10))
    5. y = list(range(10))
    6. z = list(range(1,11))
    7. vis.line(X=np.array(x), Y=np.column_stack((np.array(y), np.array(z))), opts=dict(showlegend=True))

    vis.line([x], [y=np.column_stack((np.array(y),np.array(z),np.array(还可以增加)))]) np.column_stack(a,b), 表示两个矩阵按列合并

    sin(x)曲线

    1. import visdom
    2. import torch
    3. vis = visdom.Visdom(env='sin')
    4. x = torch.arange(0, 100, 0.1)
    5. y = torch.sin(x)
    6. vis.line(X=x,Y=y,win='sin(x)',opts=dict(showlegend=True))

    持续更新图表

    1. import visdom
    2. import numpy as np
    3. vis = visdom.Visdom(env='my_windows')
    4. # 利用update更新图像
    5. x = 0
    6. y = 0
    7. my_win = vis.line(X=np.array([x]), Y=np.array([y]), opts=dict(title='Update'))
    8. for i in range(10):
    9.   x += 1
    10.   y += i
    11.   vis.line(X=np.array([x]), Y=np.array([y]), win=my_win, update='append')

    使用“append”追加数据,“replace”使用新数据,“remove”用于删除“name”中指定的跟踪。

    vis.images()

    1. import visdom
    2. import torch
    3. # 新建一个连接客户端
    4. # 指定env = 'test1',默认是'main',注意在浏览器界面做环境的切换
    5. vis = visdom.Visdom(env='test1')
    6. # 绘制正弦函数
    7. x = torch.arange(1, 100, 0.01)
    8. y = torch.sin(x)
    9. vis.line(X=x,Y=y, win='sinx',opts={'title':'y=sin(x)'})
    10. # 绘制36张图片随机的彩色图片
    11. vis.images(torch.randn(36,3,64,64).numpy(),nrow=6, win='imgs',opts={'title':'imgs'})

    绘制loss函数的变化趋势

    #绘制loss变化趋势,参数一为Y轴的值,参数二为X轴的值,参数三为窗体名称,参数四为表格名称,参数五为更新选项,从第二个点开始可以更新
    
    1. vis.line(Y=np.array([totalloss.item()]), X=np.array([traintime]),
    2.               win=('train_loss'),
    3.               opts=dict(title='train_loss'),
    4.               update=None if traintime == 0 else 'append'
    5.               )

    实际代码

    此代码出自CycleGAN的 utils.py 里一个实现

    # 记录训练日志,显示生成图,画loss曲线 的类
    
    1. class Logger():
    2.   def __init__(self, n_epochs, batches_epoch):
    3.       '''
    4.       :param n_epochs: 跑多少个epochs
    5.       :param batches_epoch: 一个epoch有几个batches
    6.       '''
    7.       self.viz = Visdom() # 默认env是main函数
    8.       self.n_epochs = n_epochs
    9.       self.batches_epoch = batches_epoch
    10.       self.epoch = 1 # 当前epoch数
    11.       self.batch = 1 # 当前batch数
    12.       self.prev_time = time.time()
    13.       self.mean_period = 0
    14.       self.losses = {}
    15.       self.loss_windows = {} # 保存loss图的字典集合
    16.       self.image_windows = {} # 保存生成图的字典集合
    17.   def log(self, losses=None, images=None):
    18.       self.mean_period += (time.time() - self.prev_time)
    19.       self.prev_time = time.time()
    20.       sys.stdout.write('
    21. Epoch %03d/%03d [%04d/%04d] -- ' % (self.epoch, self.n_epochs, self.batch, self.batches_epoch))
    22.       for i, loss_name in enumerate(losses.keys()):
    23.           if loss_name not in self.losses:
    24.               self.losses[loss_name] = losses[loss_name].data.item() #这里losses[loss_name].data是个tensor(包在值外面的数据结构),要用item方法取值
    25.           else:
    26.               self.losses[loss_name] = losses[loss_name].data.item()
    27.           if (i + 1) == len(losses.keys()):
    28.               sys.stdout.write('%s: %.4f -- ' % (loss_name, self.losses[loss_name]/self.batch))
    29.           else:
    30.               sys.stdout.write('%s: %.4f | ' % (loss_name, self.losses[loss_name]/self.batch))
    31.       batches_done = self.batches_epoch * (self.epoch - 1) + self.batch
    32.       batches_left = self.batches_epoch * (self.n_epochs - self.epoch) + self.batches_epoch - self.batch
    33.       sys.stdout.write('ETA: %s' % (datetime.timedelta(seconds=batches_left*self.mean_period/batches_done)))
    34.       # 显示生成图
    35.       for image_name, tensor in images.items(): # 字典.items()是以list形式返回键值对
    36.           if image_name not in self.image_windows:
    37.               self.image_windows[image_name] = self.viz.image(tensor2image(tensor.data), opts={'title':image_name})
    38.           else:
    39.               self.viz.image(tensor2image(tensor.data), win=self.image_windows[image_name], opts={'title':image_name})
    40.       # End of each epoch
    41.       if (self.batch % self.batches_epoch) == 0: # 一个epoch结束时
    42.           # 绘制loss曲线图
    43.           for loss_name, loss in self.losses.items():
    44.               if loss_name not in self.loss_windows:
    45.                   self.loss_windows[loss_name] = self.viz.line(X=np.array([self.epoch]), Y=np.array([loss/self.batch]),
    46.                                                                 opts={'xlabel':'epochs', 'ylabel':loss_name, 'title':loss_name})
    47.               else:
    48.                   self.viz.line(X=np.array([self.epoch]), Y=np.array([loss/self.batch]), win=self.loss_windows[loss_name], update='append') #update='append'可以使loss图不断更新
    49.               # 每个epoch重置一次loss
    50.               self.losses[loss_name] = 0.0
    51.           # 跑完一个epoch,更新一下下面参数
    52.           self.epoch += 1
    53.           self.batch = 1
    54.           sys.stdout.write('
    55. ')
    56.       else:
    57.           self.batch += 1

    train.py中调用代码是

    1. class Logger():
    2.   def __init__(self, n_epochs, batches_epoch):
    3.       '''
    4.       :param n_epochs: 跑多少个epochs
    5.       :param batches_epoch: 一个epoch有几个batches
    6.       '''
    7.       self.viz = Visdom() # 默认env是main函数
    8.       self.n_epochs = n_epochs
    9.       self.batches_epoch = batches_epoch
    10.       self.epoch = 1 # 当前epoch数
    11.       self.batch = 1 # 当前batch数
    12.       self.prev_time = time.time()
    13.       self.mean_period = 0
    14.       self.losses = {}
    15.       self.loss_windows = {} # 保存loss图的字典集合
    16.       self.image_windows = {} # 保存生成图的字典集合
    17.   def log(self, losses=None, images=None):
    18.       self.mean_period += (time.time() - self.prev_time)
    19.       self.prev_time = time.time()
    20.       sys.stdout.write('
    21. Epoch %03d/%03d [%04d/%04d] -- ' % (self.epoch, self.n_epochs, self.batch, self.batches_epoch))
    22.       for i, loss_name in enumerate(losses.keys()):
    23.           if loss_name not in self.losses:
    24.               self.losses[loss_name] = losses[loss_name].data.item() #这里losses[loss_name].data是个tensor(包在值外面的数据结构),要用item方法取值
    25.           else:
    26.               self.losses[loss_name] = losses[loss_name].data.item()
    27.           if (i + 1) == len(losses.keys()):
    28.               sys.stdout.write('%s: %.4f -- ' % (loss_name, self.losses[loss_name]/self.batch))
    29.           else:
    30.               sys.stdout.write('%s: %.4f | ' % (loss_name, self.losses[loss_name]/self.batch))
    31.       batches_done = self.batches_epoch * (self.epoch - 1) + self.batch
    32.       batches_left = self.batches_epoch * (self.n_epochs - self.epoch) + self.batches_epoch - self.batch
    33.       sys.stdout.write('ETA: %s' % (datetime.timedelta(seconds=batches_left*self.mean_period/batches_done)))
    34.       # 显示生成图
    35.       for image_name, tensor in images.items(): # 字典.items()是以list形式返回键值对
    36.           if image_name not in self.image_windows:
    37.               self.image_windows[image_name] = self.viz.image(tensor2image(tensor.data), opts={'title':image_name})
    38.           else:
    39.               self.viz.image(tensor2image(tensor.data), win=self.image_windows[image_name], opts={'title':image_name})
    40.       # End of each epoch
    41.       if (self.batch % self.batches_epoch) == 0: # 一个epoch结束时
    42.           # 绘制loss曲线图
    43.           for loss_name, loss in self.losses.items():
    44.               if loss_name not in self.loss_windows:
    45.                   self.loss_windows[loss_name] = self.viz.line(X=np.array([self.epoch]), Y=np.array([loss/self.batch]),
    46.                                                                 opts={'xlabel':'epochs', 'ylabel':loss_name, 'title':loss_name})
    47.               else:
    48.                   self.viz.line(X=np.array([self.epoch]), Y=np.array([loss/self.batch]), win=self.loss_windows[loss_name], update='append') #update='append'可以使loss图不断更新
    49.               # 每个epoch重置一次loss
    50.               self.losses[loss_name] = 0.0
    51.           # 跑完一个epoch,更新一下下面参数
    52.           self.epoch += 1
    53.           self.batch = 1
    54.           sys.stdout.write('
    55. ')
    56.       else:
    57.           self.batch += 1

    到此这篇常见的visdom使用方法的介绍就介绍到这了,希望能给到大家帮助啦。

  • 相关阅读:
    Java:Java 反射API简介
    Docker
    使用FineBI,轻松搞定汽车金融公司风险指标分析!
    [排序算法] 快速排序 (C++) (含三种写法)
    tomcat安装、部署JSPGOU项目、Tomcat多实例
    ZYNQ:串口-CAN协议转换
    扬帆牧哲:商标转让和商标变更的概念
    JS 数组扁平化
    MFC界面美化之自绘按钮控件的实现,圆角按钮,图片按钮
    linux下的gdb调试器
  • 原文地址:https://blog.csdn.net/qq_53904578/article/details/125542262