首页 Paddle框架 帖子详情
学习之路(12)可视化工具VisualDL的使用
收藏
快速回复
Paddle框架 文章深度学习模型训练 11800 15
学习之路(12)可视化工具VisualDL的使用
收藏
快速回复
Paddle框架 文章深度学习模型训练 11800 15
目录
前言
VisualDL的安装使用pip安装
使用源码安装
简单使用VisualDL
在PaddlePaddle使用VisualDL定义VisualDL组件
编写PaddlePaddle代码
把数据都添加到VisualDL
项目代码
参考资料

前言

VisualDL是一个面向深度学习任务设计的可视化工具,包含了scalar、参数分布、模型结构、图像可视化等功能。可以这样说:“所见即所得”。我们可以借助VisualDL来观察我们训练的情况,方便我们对训练的模型进行分析,改善模型的收敛情况。

之前我们使用的paddle.v2.plot接口,也可以观察训练的情况,但是只是支持CSOT的折线图而已。而VisualDL可以支持一下这个功能:

scalar,趋势图,可用于训练测试误差的展示

image, 图片的可视化,可用于卷积层或者其他参数的图形化展示

histogram, 用于参数分布及变化趋势的展示

graph,用于训练模型结构的可视化

以上的图像来自VisualDL的Github
既然那么方便,那么我们就来尝试一下吧。VisualDL底层采用C++编写,但是它在提供C++ SDK的同时,也支持Python SDK,我们主要是使用Python的SDK。顺便说一下,VisualDL除了支持PaddlePaddle,之外,还支持pytorch, mxnet在内的大部分主流DNN平台。

VisualDL的安装
本章只讲述在Ubuntu系统上的安装和使用,Mac的操作应该也差不多。

使用pip安装
使用pip安装非常简单,只要一条命令就够了,如下:

pip install --upgrade visualdl

测试一下是否安装成功了,运行一个例子下载日志文件:

# 在当前位置下载一个日志
vdl_create_scratch_log
# 如果提示命令不存在,那就使用下面这条命令
vdl_scratch.py

然后再输入,启动VisualDL并加载这个日志信息:

visualDL --logdir ./scratch_log --port 8080

这里说明一下,visualDL的参数:

host 设定IP
port 设定端口
model_pb 指定 ONNX 格式的模型文件,这木方我们还没要用到

然后在浏览器上输入:

http://127.0.0.1:8080

即可看到一个可视化的界面,如下:

使用源码安装
如果读者出于各种情况,使用pip安装不能满足需求,那可以考虑使用源码安装VisualDL,操作如下:
首先要安装依赖库:

# 安装npm
apt install npm
# 安装node
apt install nodejs-legacy
# 安装cmake
apt install cmake
# 安装unzip
apt install unzip

然后在GitHub上clone最新的源码并打开:

git clone https://github.com/PaddlePaddle/VisualDL.git
cd VisualDL

之后是编译生成whl安装包:

python setup.py bdist_wheel

生成whl安装包之后,就可以使用pip命令安装这个安装包了,*号对应的是visualdl版本号,读者要根据实际情况来安装:

pip install --upgrade dist/visualdl-*.whl

安装完成之后,同样可以使用在上一部分的使用pip安装的测试方法测试安装是否成功。

简单使用VisualDL
我们编写下面这一小段的代码来学习VisualDL的使用,代码如下:

# coding=utf-8
# 导入VisualDL的包
from visualdl import LogWriter

# 创建一个LogWriter,第一个参数是指定存放数据的路径,
# 第二个参数是指定多少次写操作执行一次内存到磁盘的数据持久化
logw = LogWriter("./random_log", sync_cycle=10000)

# 创建训练和测试的scalar图,
# mode是标注线条的名称,
# scalar标注的是指定这个组件的tag
with logw.mode('train') as logger:
    scalar0 = logger.scalar("scratch/scalar")

with logw.mode('test') as logger:
    scalar1 = logger.scalar("scratch/scalar")

# 读取数据
for step in range(1000):
    scalar0.add_record(step, step * 1. / 1000)
    scalar1.add_record(step, 1. - step * 1. / 1000)

运行Python代码之后,在终端上输入,从上面的代码可以看到我们定义的路径是./random_log:

visualDL --logdir ./random_log --port 8080

然后在浏览器上输入:

http://127.0.0.1:8080

然后就可以看到刚才编写Python代码生成的图像了:

经过这个例子,读者对VisualDL有了进一步的了解了,那么在接下来的我们就在实际的PaddlePaddle例子中使用我们的VisualDL。

在PaddlePaddle使用VisualDL

定义VisualDL组件
创建三个组件:scalar,image,histogram,并指定存放日志的路径

# 创建VisualDL,并指定当前该项目的VisualDL的路径
logdir = "../data/tmp"
logwriter = LogWriter(logdir, sync_cycle=10)

# 创建loss的趋势图
with logwriter.mode("train") as writer:
    loss_scalar = writer.scalar("loss")

# 创建acc的趋势图
with logwriter.mode("train") as writer:
    acc_scalar = writer.scalar("acc")

# 定义没多少次重新输出一遍
num_samples = 4
# 创建卷积层和输出图像的图形化展示
with logwriter.mode("train") as writer:
    conv_image = writer.image("conv_image", num_samples, 1)
    input_image = writer.image("input_image", num_samples, 1)

# 创建可视化的训练模型结构
with logwriter.mode("train") as writer:
    param1_histgram = writer.histogram("param1", 100)

编写PaddlePaddle代码
然后创建PaddlePaddle代码,我们使用的是PaddlePaddle的Fluid版本,如果对Fluid版本不熟悉的话,可以阅读笔者的上一篇文章新版本Fluid的使用,了解Fluid版本之后再继续阅读下面的代码,如果读者已经很熟悉Fluid版本的使用了,那就往下看。

定义data和label,代码如下:

# 定义图像的类别数量
class_dim = 10
# 定义图像的通道数和大小
image_shape = [3, 32, 32]
# 定义输入数据大小,指定图像的形状,数据类型是浮点型
image = fluid.layers.data(name='image', shape=image_shape, dtype='float32')
# 定义标签,类型是整型
label = fluid.layers.data(name='label', shape=[1], dtype='int64')

然后是获取分类器,这里跟上一篇有点不一样,这里还要提供第一层卷积,这是在训练的时候要使用到,使用它来获得卷积层的输出。

# 获取神经网络
net, conv1 = vgg16_bn_drop(image)
# 获取全连接输出,获得分类器
predict = fluid.layers.fc(
    input=net,
    size=class_dim,
    act='softmax',
    param_attr=ParamAttr(name="param1", initializer=NormalInitializer()))

之后获取损失函数和batch_acc,在这些之后才能定义优化方法。

# 获取损失函数
cost = fluid.layers.cross_entropy(input=predict, label=label)
# 定义平均损失函数
avg_cost = fluid.layers.mean(x=cost)

# 每个batch计算的时候能取到当前batch里面样本的个数,从而来求平均的准确率
batch_size = fluid.layers.create_tensor(dtype='int64')
print batch_size
batch_acc = fluid.layers.accuracy(input=predict, label=label, total=batch_size)

# 定义优化方法
optimizer = fluid.optimizer.Momentum(
    learning_rate=learning_rate,
    momentum=0.9,
    regularization=fluid.regularizer.L2Decay(5 * 1e-5))

opts = optimizer.minimize(avg_cost)

然后就开始创建调试器,并让其初始化。

# 是否使用GPU
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
# 创建调试器
exe = fluid.Executor(place)
# 初始化调试器
exe.run(fluid.default_startup_program())

在训练之前,还有获取训的数据,这里没有使用到测试,所以就没有获取测试的数据。

# 获取训练数据
train_reader = paddle.batch(
    paddle.dataset.cifar.train10(), batch_size=BATCH_SIZE)

# 指定数据和label的对于关系
feeder = fluid.DataFeeder(place=place, feed_list=[image, label])

这里多了一步,这是为了让调试器在训练的时候也输出参数的分布和变化趋势。

step = 0
sample_num = 0
start_up_program = framework.default_startup_program()
param1_var = start_up_program.global_block().var("param1")

现在就可以开始训练了,一共输出的四个值:loss, conv1_out, param1, acc, weight,这些在图像输出上,我们都是用到的。

accuracy = fluid.average.WeightedAverage()
# 开始训练,使用循环的方式来指定训多少个Pass
for pass_id in range(num_passes):
    # 从训练数据中按照一个个batch来读取数据
    accuracy.reset()
    for batch_id, data in enumerate(train_reader()):
        loss, conv1_out, param1, acc, weight = exe.run(fluid.default_main_program(),
                                                       feed=feeder.feed(data),
                                                       fetch_list=[avg_cost, conv1, param1_var, batch_acc,
                                                                   batch_size])
        accuracy.add(value=acc, weight=weight)
        pass_acc = accuracy.eval()

把数据都添加到VisualDL
加载卷积层和输入图像的数据加载到VisualDL中

# 重新启动图形化展示组件
if sample_num == 0:
    input_image.start_sampling()
    conv_image.start_sampling()
# 获取taken
idx1 = input_image.is_sample_taken()
idx2 = conv_image.is_sample_taken()
# 保证它们的taken是一样的
assert idx1 == idx2
idx = idx1
if idx != -1:
    # 加载输入图像的数据数据
    image_data = data[0][0]
    input_image_data = np.transpose(
        image_data.reshape(image_shape), axes=[1, 2, 0])
    input_image.set_sample(idx, input_image_data.shape,
                           input_image_data.flatten())
    # 加载卷积数据
    conv_image_data = conv1_out[0][0]
    conv_image.set_sample(idx, conv_image_data.shape,
                          conv_image_data.flatten())

    # 完成输出一次
    sample_num += 1
    if sample_num % num_samples == 0:
        input_image.finish_sampling()
        conv_image.finish_sampling()
        sample_num = 0

加载趋势图的数据,这里包括了loss和平均错误率。

# 加载趋势图的数据
loss_scalar.add_record(step, loss)
acc_scalar.add_record(step, acc)

加载参数变化的数据

# 添加模型结构数据
param1_histgram.add_record(step, param1.flatten())

然后是运行项目,在运行项目的时候,会输出一下的日志信息:

loss:[16.7996] acc:[0.0703125] pass_acc:[0.0703125]
loss:[15.192436] acc:[0.1171875] pass_acc:[0.09375]
loss:[14.519127] acc:[0.109375] pass_acc:[0.09895833]
loss:[15.262356] acc:[0.125] pass_acc:[0.10546875]
loss:[13.626783] acc:[0.078125] pass_acc:[0.1]
loss:[11.8960285] acc:[0.09375] pass_acc:[0.09895833]

同时运行我们的VisualDL,笔者把VisualDL的日志都存放在data目录下,所以我们要去到该目录,然后输入以下命令:

visualDL --logdir ./tmp --port 8080

然后在浏览器上输入:

http://127.0.0.1:8080

即可看到我们项目的图像了:

我们训练的趋势图

卷积和输入图像的可视化页面

训练参数的变化情况

项目代码

GitHub地址:https://github.com/yeyupiaoling/LearnPaddle

参考资料

http://paddlepaddle.org/
https://github.com/PaddlePaddle/VisualDL

 

 

2
收藏
回复
全部评论(15)
时间顺序
beyondyourself
#2 回复于2018-06

1 帖子里不能添加动图

2 帖子刷新后经常页面为空白

1
回复
beyondyourself
#3 回复于2018-06

visualDL目前可以在docker中安装使用吗

0
回复
夜雨飘零1
#4 回复于2018-06
1 帖子里不能添加动图 2 帖子刷新后经常页面为空白

的确,不能添加动态图片。

我这边没有出现过空白。

0
回复
夜雨飘零1
#5 回复于2018-06
visualDL目前可以在docker中安装使用吗

可以的

0
回复
炙天
#6 回复于2019-09

说了好多代码,可是,,,你能先告诉我代码在哪里输入吗.........?

可能对你来说不是问题,可是对于想要学习这个工具的人来说是个巨大的障碍。

0
回复
夜雨飘零1
#7 回复于2019-11
炙天 #6
说了好多代码,可是,,,你能先告诉我代码在哪里输入吗.........? 可能对你来说不是问题,可是对于想要学习这个工具的人来说是个巨大的障碍。

PyCharm.

0
回复
AIStudio810258
#8 回复于2020-03

感谢分享,可以提高效率

0
回复
AIStudio810258
#9 回复于2020-03

最近跑word2vector,输出比较奇怪,也找不到原因。用这个看看各层的参数变化。

0
回复
s
s1mple-awp
#10 回复于2020-03

请问为什么做卷积和输入图片部分的可视化的时候图片加载不出来,别的趋势图都没问题

0
回复
乐观的GuQianYi
#11 回复于2021-12

您好,我在使用AI studio中输入!visualDL --logdir ./random_log --port 8080并运行之后进度条就一直在转,浏览器输入http://127.0.0.1:8080之后无法加载任何内容,请问这是什么原因?

0
回复
5
529112036yk
#12 回复于2021-12

非常详细,感谢分享

0
回复
玥亮
#13 回复于2022-01

nice

0
回复
fi_Past
#14 回复于2022-03

学习了

0
回复
潮流MI
#15 回复于2022-04

学到了

0
回复
潮流MI
#16 回复于2022-04

学到了

0
回复
需求/bug反馈?一键提issue告诉我们
发现bug?如果您知道修复办法,欢迎提pr直接参与建设飞桨~
在@后输入用户全名并按空格结束,可艾特全站任一用户