@TOC

一、简介

Visdom是一个基于Python的可视化工具包,能够用于PyTorch等深度学习框架中的实时数据可视化。它提供了一个Web界面,能够不便地创立图表、散点图和直方图等可视化元素。相比tensorboardrensorboardX具备更轻量、更便捷、更丰盛、更疾速等特点。

visdom的github主页:https://github.com/fossasia/visdom

visdom的中文参考文档:https://ptorch.com/news/77.html

visdom的优良教程:https://blog.csdn.net/weixin_41010198/article/details/117853358

二、装置与启动

应用Visdom须要先装置visdom包,能够通过pip命令进行装置:

pip install visdom

接下来,在cmd或者Anaconda中应用python -m visdom.server启动服务。并在浏览器中输出提醒的端口,并且须要放弃黑框框cmdAnaconda)始终开启。


当你关上后,会出现一个空白的界面,是因为目前还没有写入任何图形。

三、设计思路

假如你的电脑C盘中有很多文件夹,每个文件夹有很多文件,每个文件能够填入你想要的信息。

同样,visdom启动服务后,呈现出一个网页页面,会随时依据你电脑跑的程序中无关visdom的局部,呈现出可视化图。这个网页中,能够抉择不同的文件夹进行存储,让你的图文件分门别类,比方程序A相干的图存在A文件夹中,程序B相干的图存在B文件夹下,当然也能够各个程序生成的图都存在C文件夹下。每个文件夹中能够画不同的图,每个图也能够画多个点、线、柱等等。

在每个文件夹下,能够存入视频图像文本等等

图像分为图片、以及生成的一些数据图,这里简略介绍一下生成的数据图,比方折线图

vis.scatter:2D或3D散点图
vis.line:线图
vis.stem:stem图
vis.heatmap:热图地块
vis.bar:条形图
vis.histogram:直方图
vis.boxplot:盒子
vis.surf:外表反复
vis.contour:等高线图
vis.quiver:颤动的情节
vis.mesh:网格图
vis.dual_axis_lines:双y轴线图

四、在迭代训练中的绘图

首先创立一个可视化界面和文件夹:

import visdomviz = visdom.Visdom(env='main-8')

其中env='main-8' 示意一个文件夹名称,main-8能够替换为其余名称,假使不写该参数,则默认存储在env='main'中,接下来,咱们应用viz进行操作,就意味着操作对应的图存在'main-8'中。
此时,关上网页,会看到有两个环境Environment,一个是“main”,一个是“main-8”

创立好文件夹后,接下来,咱们在这个文件夹上面写一些图。
先关上网页,确保是“online”在线模式

为了模仿迭代过程,这里设计一个循环语句。执行代码

import visdomviz = visdom.Visdom(env='main-8')viz.line(X=[0.],  # x坐标         Y=[0.],  # y值        win="line1",  # 窗口id        name="Adam梯度",  # 线条名称        update='append',  # 以增加形式退出        opts={            'showlegend': True,  # 显示网格            'title': "Demo line in Visdom",            'xlabel': "x1",  # x轴标签            'ylabel': "y1",  # y轴标签        },)for i in range(10):    viz.line(X=[i], Y=[i*2],name="Adam梯度", win='line1', update='append')    viz.line(X=[i], Y=[i**2],name="SGD梯度", win='line1', update='append')    viz.line(X=[i], Y=[5*i+2],name="GDM梯度", win='line1', update='append')

先看一下,生成的后果。关上网页

假如当初我想要在main-8文件夹上面,画另外一个图,执行程序

import visdomvizs = visdom.Visdom(env='main-8')vizs.line(X=[0.],  # x坐标         Y=[0.],  # y值        win="line2",  # 窗口id        name="Adam梯度",  # 线条名称        update='append',  # 以增加形式退出        opts={            'showlegend': True,  # 显示网格            'title': "Demo line in Visdom-1",            'xlabel': "x1",  # x轴标签            'ylabel': "y1",  # y轴标签        },)for i in range(10):    vizs.line(X=[i], Y=[5*i**3],name="Adam梯度", win='line2', update='append')    vizs.line(X=[i], Y=[i**2],name="SGD梯度", win='line2', update='append')

查看后果

下面的内容,还不具备一般性,上面给出局部代码示例和效果图,以满足理论中的简单需要

背景:假如,当初有一批数据,数据来自总体一元线性方程,咱们依据A、B、C三种梯度降落算法,在不同的采样率rate下,比照剖析,三种梯度降落算法中的损失值w值b值

形容:
图1:loss损失图,横轴为采样比rate、纵轴为loss损失值,图中有3个折线,对应A(无梯度)、B(小梯度)、C(随机梯度)三种梯度降落办法
同理,图2为w值图,图3为b值图,其余相似。

生成文件夹上面的三个图窗口,生成图窗口只须要执行一次就行,放在env='main-9'文件夹中

name_1 = '无梯度'name_2 = '小梯度'name_3 = '随机梯度'import visdomviz = visdom.Visdom(env='main-9')window_loss = viz.line(        X=[0.1],  # x坐标        Y=[0.],  # y值        win="line_loss_1",  # 窗口id        name= name_1,  # 线条名称        update='append',  # 以增加形式退出        opts={            'showlegend': True,  # 显示网格            'title': "loss",            'xlabel': "rate",  # x轴标签            'ylabel': "loss",  # y轴标签        },)window_w = viz.line(        X=[0.1],  # x坐标         Y=[0.],  # y值        win="line_w_1",  # 窗口id        name=name_1,  # 线条名称        update='append',  # 以增加形式退出        opts={            'showlegend': True,  # 显示网格            'title': "W value",            'xlabel': "rate",  # x轴标签            'ylabel': "w",  # y轴标签        },)window_b = viz.line(        X=[0.1],  # x坐标         Y=[0.],  # y值        win="line_b_1",  # 窗口id        name=name_1,  # 线条名称        update='append',  # 以增加形式退出        opts={            'showlegend': True,  # 显示网格            'title': "b value",            'xlabel': "rate",  # x轴标签            'ylabel': "b",  # y轴标签        },)

在迭代训练中,每次result生成的后果为([loss_A, loss_B, loss_C],[A_w,B_w, C_w],[A_b, B_b, C_b])

for i in range(9):        va = 'append'        if i == 0:            va = "replace"        rate += 0.1        result = main()                #result: ([loss_A, loss_B, loss_C],[A_w,B_w, C_w],[A_b, B_b, C_b])        viz.line(X=[rate], Y=[result[0][0]],name=name_1, win=window_loss, update=va)        viz.line(X=[rate], Y=[result[0][1]],name=name_2, win=window_loss, update=va)        viz.line(X=[rate], Y=[result[0][2]],name=name_3, win=window_loss, update=va)        viz.line(X=[rate], Y=[result[1][0]],name=name_1, win=window_w, update=va)        viz.line(X=[rate], Y=[result[1][1]],name=name_2, win=window_w, update=va)        viz.line(X=[rate], Y=[result[1][2]],name=name_3, win=window_w, update=va)        viz.line(X=[rate], Y=[result[2][0]],name=name_1, win=window_b, update=va)        viz.line(X=[rate], Y=[result[2][1]],name=name_2, win=window_b, update=va)        viz.line(X=[rate], Y=[result[2][2]],name=name_3, win=window_b, update=va)

关上网页

假使是在机器学习、深度学习中:

#训练模型vis = visdom.Visdom(env='main')  # 设置环境窗口的名称,如果不设置名称就默认为mainopt = {        'xlabel': 'epochs',        'ylabel': 'loss_value',        'title': 'SGD_loss'    }loss_window = vis.line(    X=[0],    Y=[0],    opts=opt)for epoch in range(400):    y_pred = model(x_data)    loss = criterion(y_pred, y_data)    print(epoch, loss.item())    #所有梯度归零化    optimizer.zero_grad()    #反向流传求出梯度    loss.backward()    #更新权重和偏置值,即w和b    optimizer.step()    vis.line(X=[epoch], Y=[loss.item()], win=loss_window, opts=opt, update='append')

五、个别绘图

放在“main”上面,可疏忽参数。在jupyter notebook中执行代码:

import visdomimport numpy as npvis = visdom.Visdom()vis.text('Hello, world!')vis.image(np.ones((3, 10, 10)))
import visdomvis = visdom.Visdom()trace = dict(x=[1, 2, 3], y=[4, 5, 6], mode="markers+lines", type='custom',             marker={'color': 'red', 'symbol': 104, 'size': "10"},             text=["one", "two", "three"], name='1st Trace')layout = dict(title="First Plot", xaxis={'title': 'x1'}, yaxis={'title': 'x2'})vis._send({'data': [trace], 'layout': layout, 'win': 'mywin'})
from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionfrom __future__ import unicode_literalsfrom visdom import Visdomimport numpy as npimport mathimport os.pathimport getpassfrom sys import platform as _platformfrom six.moves import urllibviz = Visdom()assert viz.check_connection()try:    import matplotlib.pyplot as plt    plt.plot([1, 23, 2, 4])    plt.ylabel('some numbers')    viz.matplot(plt)except BaseException as err:    print('Skipped matplotlib example')    print('Error message: ', err)
#单张viz.image(    np.random.rand(3, 512, 256),    opts=dict(title='Random!', caption='How random.'),)#多张viz.images(    np.random.randn(20, 3, 64, 64),    opts=dict(title='Random images', caption='How random.'))
#画出随机的散点图import timeY = np.random.rand(100)old_scatter = viz.scatter(    X=np.random.rand(100, 2),    Y=(Y[Y > 0] + 1.5).astype(int),    opts=dict(        legend=['Didnt', 'Update'],        xtickmin=-50,        xtickmax=50,        xtickstep=0.5,        ytickmin=-50,        ytickmax=50,        ytickstep=0.5,        markersymbol='cross-thin-open',    ),)time.sleep(5)#对窗口进行更新,包含标注,坐标,款式等viz.update_window_opts(    win=old_scatter,    opts=dict(        legend=['Apples', 'Pears'],        xtickmin=0,        xtickmax=1,        xtickstep=0.5,        ytickmin=0,        ytickmax=1,        ytickstep=0.5,        markersymbol='cross-thin-open',    ),)
## 通过update='new'增加新散点import timewin = viz.scatter(    X=np.random.rand(255, 2),    opts=dict(        markersize=10,        markercolor=np.random.randint(0, 255, (255, 3,)),    ),)# 判断窗口是否存在assert viz.win_exists(win), 'Created window marked as not existing'time.sleep(2)# 向散点图中退出新的形容viz.scatter(    X=np.random.rand(255),    Y=np.random.rand(255),    win=win,    name='new_trace',    update='new')
# 2D散点图,调配不同色彩viz.scatter(    X=np.random.rand(255, 2),    #随机指定1或者2    Y=(np.random.rand(255) + 1.5).astype(int),    opts=dict(        markersize=10,        ## 调配两种色彩        markercolor=np.random.randint(0, 255, (2, 3,)),    ),)
#3D 散点图viz.scatter(    X=np.random.rand(100, 3),    Y=(Y + 1.5).astype(int),    opts=dict(        legend=['Men', 'Women'],        markersize=5,    ))
viz.line(Y=np.random.rand(10), opts=dict(showlegend=True))Y = np.linspace(-5, 5, 100)viz.line(    Y=np.column_stack((Y * Y, np.sqrt(Y + 5))),    X=np.column_stack((Y, Y)),    opts=dict(markers=False),)
viz.bar(X=np.random.rand(20))viz.bar(    X=np.abs(np.random.rand(5, 3)),    opts=dict(        stacked=True,        legend=['Facebook', 'Google', 'Twitter'],        rownames=['2012', '2013', '2014', '2015', '2016']    ))viz.bar(    X=np.random.rand(20, 3),    opts=dict(        stacked=False,        legend=['The Netherlands', 'France', 'United States']    ))
viz.heatmap(    X=np.outer(np.arange(1, 6), np.arange(1, 11)),    opts=dict(        columnnames=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],        rownames=['y1', 'y2', 'y3', 'y4', 'y5'],        colormap='Electric',    ))# contourx = np.tile(np.arange(1, 101), (100, 1))y = x.transpose()X = np.exp((((x - 50) ** 2) + ((y - 50) ** 2)) / -(20.0 ** 2))viz.contour(X=X, opts=dict(colormap='Viridis'))# surfaceviz.surf(X=X, opts=dict(colormap='Hot'))
# boxplotX = np.random.rand(100, 2)X[:, 1] += 2viz.boxplot(    X=X,    opts=dict(legend=['Men', 'Women']))# stemplotY = np.linspace(0, 2 * math.pi, 70)X = np.column_stack((np.sin(Y), np.cos(Y)))viz.stem(    X=X,    Y=Y,    opts=dict(legend=['Sine', 'Cosine']))# quiver plotX = np.arange(0, 2.1, .2)Y = np.arange(0, 2.1, .2)X = np.broadcast_to(np.expand_dims(X, axis=1), (len(X), len(X)))Y = np.broadcast_to(np.expand_dims(Y, axis=0), (len(Y), len(Y)))U = np.multiply(np.cos(X), Y)V = np.multiply(np.sin(X), Y)viz.quiver(    X=U,    Y=V,    opts=dict(normalize=0.9),)
# text window with Callbackstxt = 'This is a write demo notepad. Type below. Delete clears text:<br>'callback_text_window = viz.text(txt)# pie chartX = np.asarray([19, 26, 55])viz.pie(X=X,opts=dict(legend=['Residential', 'Non-Residential', 'Utility']))# mesh plotx = [0, 0, 1, 1, 0, 0, 1, 1]y = [0, 1, 1, 0, 0, 1, 1, 0]z = [0, 0, 0, 0, 1, 1, 1, 1]X = np.c_[x, y, z]i = [7, 0, 0, 0, 4, 4, 6, 6, 4, 0, 3, 2]j = [3, 4, 1, 2, 5, 6, 5, 2, 0, 1, 6, 3]k = [0, 7, 2, 3, 6, 7, 1, 1, 5, 5, 7, 6]Y = np.c_[i, j, k]viz.mesh(X=X, Y=Y, opts=dict(opacity=0.5))

生成的图片

六、根本调整与保留文件

在下面应用代码生成的这些图片,我应该怎么保留呢?我下次再关上网页,能不能还是显示这样的动静网页呢?我能不能调整某一个图片大小,显示它的数据之类的呢?答案是必定的!

1、调整大小、拖拽:长按拖动即可,右下角落长按挪动即可放大放大


2、查看图片对应的数据:点击右下角Edit,会跳转到新网页,能够灵便进行数据调整

3、图内控件调整:比方,放大某一区域,或者图内整体放大放大等等

4、保留单个图

5、保留整个环境:逐渐将每个文件夹都保留一下

点击文件夹图标,而后更改名称,再点击fork,再点击“save”,即可保留,咱们将上图中的4个文件夹都进行保留。

还有许多其余性能,自行理解
此时,能够敞开网页,敞开黑框框,不必放心数据失落。

6、从新加载关上环境

很久当前,当咱们须要查看这些图形的时候,不须要从新跑代码,间接启动服务,关上网页即可。

同样的操作:在黑框框中启动服务关上网页。应用python -m visdom.server启动服务。并在浏览器中输出提醒的端口,那么咱们就能够看到之前生成的图形了。

7、不小心敞开了网页

只有黑框框没有敞开,不小心将网页敞开了,没有关系,数据不会失落,从新复制端口在浏览器中拜访即可。

本文由mdnice多平台公布