@TOC
一、简介
Visdom 是一个基于 Python 的可视化工具包,能够用于 PyTorch 等深度学习框架中的实时数据可视化。它提供了一个 Web 界面,能够不便地创立图表、散点图和直方图等可视化元素。相比 tensorboard
、rensorboardX
具备更轻量、更便捷、更丰盛、更疾速等特点。
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
启动服务。并在浏览器中输出提醒的端口,并且须要放弃 黑框框
(cmd
、Anaconda
)始终开启。
当你关上后,会出现一个空白的界面,是因为目前还没有写入任何图形。
三、设计思路
假如你的电脑 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 visdom
viz = visdom.Visdom(env='main-8')
其中 env='main-8'
示意一个文件夹名称,main-8
能够替换为其余名称,假使不写该参数,则默认存储在 env='main'
中,接下来,咱们应用 viz
进行操作,就意味着操作对应的图存在 'main-8'
中。
此时,关上网页,会看到有两个环境Environment
,一个是“main”
, 一个是“main-8”
创立好文件夹后,接下来,咱们在这个文件夹上面写一些图。
先关上网页,确保是 “online”
在线模式
为了模仿迭代过程,这里设计一个循环语句。执行代码
import visdom
viz = 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 visdom
vizs = 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 visdom
viz = 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') # 设置环境窗口的名称, 如果不设置名称就默认为 main
opt = {
'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 visdom
import numpy as np
vis = visdom.Visdom()
vis.text('Hello, world!')
vis.image(np.ones((3, 10, 10)))
import visdom
vis = 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_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from visdom import Visdom
import numpy as np
import math
import os.path
import getpass
from sys import platform as _platform
from six.moves import urllib
viz = 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 time
Y = 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 time
win = 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',
)
)
# contour
x = 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'))
# surface
viz.surf(X=X, opts=dict(colormap='Hot'))
# boxplot
X = np.random.rand(100, 2)
X[:, 1] += 2
viz.boxplot(
X=X,
opts=dict(legend=['Men', 'Women'])
)
# stemplot
Y = 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 plot
X = 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 Callbacks
txt = 'This is a write demo notepad. Type below. Delete clears text:<br>'
callback_text_window = viz.text(txt)
# pie chart
X = np.asarray([19, 26, 55])
viz.pie(
X=X,
opts=dict(legend=['Residential', 'Non-Residential', 'Utility'])
)
# mesh plot
x = [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 多平台公布