机器之心编辑部发布

还在「黑盒炼丹」? 教你如何实现一行代码透视炼丹过程

开发者在炼丹的过程中会不会遇到这些问题呢?比如说深度学习模型训练过程中盯 Log 盯得头晕眼花?复杂模型结构全靠脑补?网络各层效果无法评估?模型评估指标难以综合权衡?想必各位「炼丹师」、「调参侠」都中过招吧?莫慌,飞桨给大家「送解药」来了!

这剂解药就是VisualDL 2.0——飞桨可视化分析工具全面改版升级,帮众位开发者们从 「炼丹萌新」 变身「太上老君」

怀疑我们自吹自擂?那就让我们一起看看 VisualDL 到底是啥?先上图为证!

VisualDL 2.0 是什么?

看到这里,有些小伙伴可能已经大概知道 VisualDL 是什么了,不知道的同学请继续往下看,反正花花绿绿的,至少比 log 看着养眼多了! 

具体来说,VisualDL 是飞桨团队为广大深度学习开发者订制的功能完备的可视化分析工具,可以帮助深度学习开发者了解训练过程中模型参数的变化趋势、 网络层对数据特征的提取情况、网络结构应该如何调整、精度与召回是否达到了理想的平衡等,从而实现有方向性的错误排查,实现高效的模型调优。

其实,VisualDL 1.0 早在 2017 年就推出了,随着飞桨开源深度学习框架历经 3 年深入产业实践的不断打磨,VisualDL 本次也完成了 2.0 版本的全新蜕变!相较 VisualDL 1.0,新版本的 API 设计更加简洁易用、与框架衔接更为顺畅、功能更丰富,界面设计也全面进行了升级,致力为老用户带来全新体验,为新用户带来使用上的惊喜

VisualDL 2.0 能做什么?

VisualDL 2.0 共有五大可视化功能,下面我们来逐一讲解。

标量(Scalar) 

标量可以通过图表的形式展示 Loss、Accuracy、Learning Rate 等参数指标在训练过程中的变化趋势,帮助开发者了解其是否朝着理想的方向优化,便于发现异常情况,及时排查并修复问题;另外,通过对比多组实验的训练参数,开发者们能深入探究参数对模型效果的影响,加速模型的调优。

实现代码如下:

add_scalar(tag, value, step, walltime=None)

数据样本分析(Sample) 

数据样本分析可以在多种深度学习任务中发挥重要作用。例如在计算机视觉任务中,该功能不仅可以查看每个训练批次中的指定的样本图片,也可以展示图像数据的在训练过程中间阶段的提取特征情况,便于开发者们观察图片数据在训练过程中的状态,进而深入了解训练过程及效果。

实现代码如下:

add_image(tag, img, step, walltime=None)

语音识别或合成任务中,数据样本分析功能可以帮助开发者实时获取训练过程中的音频数据,评估语音识别或合成的效果,挑选最优的训练模型。

实现代码如下:

add_audio(tag, audio_array, step, sample_rate)

模型结构(Graph)

模型结构功能支持一键可视化模型网络结构。开发者们可查看模型属性、节点信息、节点输入输出等,并支持节点搜索功能,协助开发者们快速分析模型结构并了解数据流向。

当前支持如下两种操作方式:

  • 模型文件拖拽上传

  • 在命令行加入参数 --model 并指定模型文件路径(非文件夹路径),运行命令后即可启动:

visualdl --model ./log/model --port 8080

直方图(Histogram) 

直方图可以展示 Tensor(weight、bias、gradient 等)数据在训练过程中的变化趋势,深入了解模型各层效果,帮助开发者精准调整模型结构

实现代码如下:

add_histogram(tag, values, step, walltime=None, buckets=10)

PR 曲线(PR Curve)

PR 曲线可以展示每一分类在不同阈值下的精度(Precision)- 召回率(Recall)曲线,帮助开发者权衡模型精度和召回率之间的平衡,设定最佳阈值。精度是指正样本的数量除以所有被选中样本的数量,而召回率是指所有正样本中被推理正确的比例,由此可见精度越高,召回率越高,我们的模型就越好。但是很多情况下,鱼和熊掌不可兼得,无法同时保证精度和召回率都是最高,此时需要通过 PR 曲线,权衡精度与召回率,确定最佳阈值。

实现代码如下:

add_pr_curve(tag, labels, predictions, step=None, num_thresholds=10)

为了便于大家更好的了解 VisualDL,我们结合一个简单的实际模型例子来更直观的看下这几个功能。真的是很简单的例子——那就是深度学习中的「Hello World」,手写数字识别!

VisualDL 2.0 怎么用?

假设在一个风和日丽的早晨,作为深度学习爱好者的你,想要建立一个简单的 LeNet 模型进行手写数字识别,在辛苦完成模型搭建后,进入模型训练时,却看到了如下一幕:

你心里一沉,这精度怎么抖得那么厉害啊。训练中哪里出现问题了呢?到底谁是「凶手」?可是连问题出在哪都不知道,模型优化和修复更是无从下手。这时你想起几日前偶然发现的深度学习可视化分析工具——VisualDL,心中顿时升起希望,因为在训练之前,已经把下面的代码添加到训练脚本中了。

#使用VisualDL的第一步是在训练脚本中添加如下代码创建日志文件,用于记录训练中产生的数据。
from visualdl import LogWriter
log_writer = LogWriter("./paddle_lenet_log")

# 使用标量(Scalar)记录Loss、Accuracy参数,用于观察其变化趋势
writer.add_scalar(tag="train/loss", step=step, value=cost)
writer.add_scalar(tag="train/acc", step=step, value=accuracy)

# 使用数据样本分析功能记录每批次第一张数据,用于查看图像数据
img = np.reshape(batch[0][0], [28, 28, 1]) * 255
writer.add_image(tag="train/input", step=step, img=img)

# 使用直方图功能记录所有参数,用于查看weight、bias在训练步数中的分布变化
for param in params:
     values = fluid.global_scope().find_var(param).get_tensor()
     writer.add_histogram(tag='train/{}'.format(param), step=step, values=values)

# 记录PR曲线查看不同阈值下的精度和召回率
labels = np.array(batch)[:, 1]
for i in range(10):
label_i = np.array(labels == i, dtype='int32')
prediction_i = pred[:, i]
writer.add_pr_curve(tag='train/class_{}_pr_curve'.format(i),
                            labels=label_i,
                            predictions=prediction_i,
                            step=step,
                            num_thresholds=20)
# 使用save_inference_model保存模型结构至“./model”目录,便于训练后使用模型结构(Graph)功能查看模型网络结构
fluid.io.save_inference_model(dirname='./model', feeded_var_names=['img'],target_vars=[predictions], executor=exe)

接下来就执行下面的命令来开始奇幻的破案(调优)之旅吧!

visualdl--logdir ./paddle_lenet_log --port 8080

执行命令后,即可得到这样一个网址 http://localhost:8080/,打开浏览器输入这个网址即可查看究竟发生了什么。首先来看看案发现场。。

1. 点击 「标量数据」 页签查看模型的 Loss 和 Accuracy 整体变化趋势,也就是把刚才的日志信息通过图形直观的展示出来。这部分对应的代码如下所示:

writer.add_scalar(tag="train/loss", step=step, value=cost)
writer.add_scalar(tag="train/acc", step=step, value=accuracy)

一眼望去,这哪是 Loss 和 Accuracy 的变化曲线啊,这明显是心率不齐啊,让人有打 120 叫救护车的冲动了!

显而易见,Accuracy 一直在 10% 左右徘徊,Loss 一直无法下降,由此我们开始逐个查看问题出在哪个环节。首先看看模型结构的实际样子,是否是结构设计出了问题。

2. 点击 「网络结构」 页签,将保存在 「./model」 目录下的模型文件拖进页面即可看到模型的结构。

通过观察模型结构、节点属性、模型属性、数据流向,咱们可以直观的发现整体结构是符合预期的,也就是说模型网络本身是清白的,那么是否是模型 「吃进」 的数据有问题呢? 

3. 点击 「样本数据」 查看训练中的样本数据。这部分对应的代码如下所示:

# 使用数据样本分析功能记录每批次第一张数据,用于查看图像数据
img = np.reshape(batch[0][0], [28, 28, 1]) * 255
writer.add_image(tag="train/input", step=step, img=img)

通过查看每批次数据的第一张图片,发现输入数据也是没有问题的。那么咱们再来「回放录像」,看看每一时间步的参数变化情况吧。

4. 点击 「直方图」 页签,查看训练过程中每一时间步权重和偏差的变化情况,就如同回放整个训练过程的监控录像一样,让训练过程中参数变化不正常的问题无所遁形!这部分对应的代码如下所示:

for param in params:
         values = fluid.global_scope().find_var(param).get_tensor()
         writer.add_histogram(tag='train/{}'.format(param), step=step, 
values=values)

通过查看后发现,每一层的权重和偏差的变化正常。由此证明不是特定层的初始参数配置出现问题,排除了模型结构、数据样本、每层网络参数配置后,还剩下超参数的配置,因此决定尝试不同的学习率(0.001,0.03,0.05,0.08,0.1),并通过 VisualDL 的多实验对比功能,来观察学习率对模型训练效果的影响情况。

5. 启动多实验对比功能非常的简单,只需要在训练脚本中参考如下代码实现同一个目录下记录多份不同学习率的训练日志文件,并启动相应训练即可。接着启动 VisualDL,就会得到多组实验记录对比图了。

#创建日志文件,储存当lr=0.001时训练结果
log_writer = LogWriter("paddle_lenet_log/lr0.001")
#创建日志文件,储存当lr=0.03时训练结果
log_writer = LogWriter("paddle_lenet_log/lr0.03")
#创建日志文件,储存当lr=0.05时训练结果
log_writer = LogWriter("paddle_lenet_log/lr0.05")
#创建日志文件,储存当lr=0.08时训练结果
log_writer = LogWriter("paddle_lenet_log/lr0.08")
#创建日志文件,储存当lr=0.1时训练结果
log_writer = LogWriter("paddle_lenet_log/lr0.1")

你终于发现了问题所在了,原来是学习率设置的过大了,导致 Loss 无法下降收敛,根据 「标量数据」 展示的效果,当学习率为 0.001 时(深蓝色线条),Loss 呈现优美的下降趋势且后续渐渐收敛,Accuracy 呈现逐渐上升并趋于平稳,因此你将学习率设置为 0.001,使得模型呈现最佳效果。

但是你还不满足于现状,想要选择一个最佳阈值,使得模型的精准度和召回率都达到最优,于是又开始使用 「PR 曲线」 功能。

6. 点击 「PR 曲线」 页签,权衡精确度与召回间的关系,确定最佳阈值。这部分对应的代码如下所示:

labels = np.array(batch)[:, 1]
for i in range(10):
label_i = np.array(labels == i, dtype='int32')
prediction_i = pred[:, i]
writer.add_pr_curve(tag='train/class_{}_pr_curve'.format(i),
                            labels=label_i,
                            predictions=prediction_i,
                            step=step,
                            num_thresholds=20)

以上图为例,该图是手写数字识别任务中类别 7 对应的 PR 曲线,从图中可以看出,当阈值为 0.10、0.15 或 0.20 时,准确率和召回率同时达到最高值,因此选择上述中的任意阈值,模型都可达到最佳效果。

最终,在 VisualDL 的帮助下,你确定了模型阈值为 0.15,学习率为 0.001,至此,一个效果理想的手写数字识别模型搭建完成。

如需查看完整应用案例代码,请参考:

  • https://aistudio.baidu.com/aistudio/projectdetail/622772 

如需查看较复杂的应用案例 -- 眼疾识别,请参考:

  • https://aistudio.baidu.com/aistudio/projectdetail/502834

写在最后

看到这里,相信大家已经对 VisualDL 2.0 有了一个比较全面的了解,也发现它是真的又有用,又好用吧?然而这还不够,飞桨团队还为它增加了诸多软实力:

  • 高兼容:全面支持飞桨、ONNX、Caffe 等市面主流模型结构可视化,广泛支持各类用户实现可视化分析。

  • 生态支持全面:与飞桨的多个套件、工具组件以及 AI 学习和实训社区 AI Studio 全面打通,为开发者们在飞桨生态系统中提供最佳使用体验。

在未来,VisualDL 将会持续加入新的功能组件,致力于为开发者们提供简单易用、功能丰富、性能强大的可视化分析工具,助力模型的优化过程。

小伙伴们是不是已经破迫不及待想要亲自上手尝试了呢?欢迎登录 VisualDL 2.0 官网查看功能示例,GitHub 上也提供了详细的使用指南,大家可以踊跃尝试!想要与其他使用 VisualDL 的小伙伴们交流心得么?请加入 VisualDL 官方 QQ 群:1045783368,提出使用中遇到的问题与对于可视化的其他需求,同时还有机会与深度学习高手们面对面过招!

如果您加入飞桨官方 QQ 群,您将遇上大批志同道合的深度学习同学。官方 QQ 群:1108045677。

如果您想详细了解更多飞桨的相关内容,请参阅以下文档。

  • 飞桨官网地址:https://www.paddlepaddle.org.cn

  • VisualDL 官网地址:https://www.paddlepaddle.org.cn/paddle/visualdl

飞桨 VisualDL 项目地址:

  • GitHub:https://github.com/PaddlePaddle/VisualDL

  • Gitee: https://gitee.com/paddlepaddle/VisualDL 

飞桨开源框架项目地址:

  • GitHub: https://github.com/PaddlePaddle/Paddle 

  • Gitee:  https://gitee.com/paddlepaddle/Paddle 

工程可视化分析工具百度飞桨VisualDL 2.0
相关数据
收敛技术

在数学,计算机科学和逻辑学中,收敛指的是不同的变换序列在有限的时间内达到一个结论(变换终止),并且得出的结论是独立于达到它的路径(他们是融合的)。 通俗来说,收敛通常是指在训练期间达到的一种状态,即经过一定次数的迭代之后,训练损失和验证损失在每次迭代中的变化都非常小或根本没有变化。也就是说,如果采用当前数据进行额外的训练将无法改进模型,模型即达到收敛状态。在深度学习中,损失值有时会在最终下降之前的多次迭代中保持不变或几乎保持不变,暂时形成收敛的假象。

学习率技术

在使用不同优化器(例如随机梯度下降,Adam)神经网络相关训练中,学习速率作为一个超参数控制了权重更新的幅度,以及训练的速度和精度。学习速率太大容易导致目标(代价)函数波动较大从而难以找到最优,而弱学习速率设置太小,则会导致收敛过慢耗时太长

超参数技术

在机器学习中,超参数是在学习过程开始之前设置其值的参数。 相反,其他参数的值是通过训练得出的。 不同的模型训练算法需要不同的超参数,一些简单的算法(如普通最小二乘回归)不需要。 给定这些超参数,训练算法从数据中学习参数。相同种类的机器学习模型可能需要不同的超参数来适应不同的数据模式,并且必须对其进行调整以便模型能够最优地解决机器学习问题。 在实际应用中一般需要对超参数进行优化,以找到一个超参数元组(tuple),由这些超参数元组形成一个最优化模型,该模型可以将在给定的独立数据上预定义的损失函数最小化。

计算机视觉技术

计算机视觉(CV)是指机器感知环境的能力。这一技术类别中的经典任务有图像形成、图像处理、图像提取和图像的三维推理。目标识别和面部识别也是很重要的研究领域。

准确率技术

分类模型的正确预测所占的比例。在多类别分类中,准确率的定义为:正确的预测数/样本总数。 在二元分类中,准确率的定义为:(真正例数+真负例数)/样本总数

语音识别技术

自动语音识别是一种将口头语音转换为实时可读文本的技术。自动语音识别也称为语音识别(Speech Recognition)或计算机语音识别(Computer Speech Recognition)。自动语音识别是一个多学科交叉的领域,它与声学、语音学、语言学、数字信号处理理论、信息论、计算机科学等众多学科紧密相连。由于语音信号的多样性和复杂性,目前的语音识别系统只能在一定的限制条件下获得满意的性能,或者说只能应用于某些特定的场合。自动语音识别在人工智能领域占据着极其重要的位置。

模型优化技术

像卷积神经网络(CNN)这样的深度学习模型具有大量的参数;实际上,我们可以调用这些超参数,因为它们原本在模型中并没有被优化。你可以网格搜索这些超参数的最优值,但需要大量硬件计算和时间。改进模型的最佳方法之一是基于在你的领域进行过深入研究的专家的设计和体系结构,他们通常拥有强大的硬件可供使用。常见的简单模型优化技巧包括迁移学习、dropout、学习率调整等

暂无评论
暂无评论~