雷锋网 AI 研习社按,日前,MXNet 作者李沐在知乎上发文,介绍他们开发了一个记录 MXNet 数据类型的库,称作 MXBoard,记录结果可以用 TensorBoard 来呈现。原文如下,雷锋网 AI 研习社获其授权转载。
写在前面
深度神经网络自出现以来就一直饱受争议。从实践角度来讲,设计并训练出一个可用的模型非常困难,需要涉及大量的调参、修改网络结构、尝试各种优化算法等等;从理论角度来看,深度神经网络的数学理论证明并不完备,从而造成人们对其基本原理缺乏清晰的认识。而数据可视化带来的直观效果可以很大程度上弥补上述的不足。比如,模型训练时如果能实时画出梯度数据分布,可以很快发现并纠正梯度消失或者梯度爆炸的现象。再比如,词嵌入(word embedding)的可视化表明文字根据语义在低维空间聚合成不同的流形(manifold),这也从数学上解释了,为什么增加词向量的维度可以更好地区分不同语义的聚类(低维空间缠绕的流形在高维可以分开)。优秀可视化工具对深度学习的份量可见一斑。
TensorBoard 的横空出世给 TensorFlow 的使用者带来了可视化的福音。我们曾听到过很多用户(包括企业用户)介绍,选择TensorFlow 是因为可以用 TensorBoard。这么好的东西能否给各大深度学习框架共享呢?多亏了 TeamHG-Memex 这个组织,将 TensorFlow 中写数据到事件文件 (event files)的算法提取出来。自此,开发者们只需要将这个算法嵌入到深度学习的框架中,就可以使用 TensorBoard 来可视化框架特有的数据结构了。
正是基于这样的基础,我们开发了一个记录 MXNet 数据类型的库,称作 MXBoard,记录结果得以用 TensorBoard 来呈现。安装 MXBoard 请参考这里。
注:请安装 MXNet 1.2.0 版本来使用 MXBoard 的全部功能。在 MXNet 1.2.0 正式发布前,请安装 MXNet nightly 版本来使用 MXBoard,pip install --pre mxnet
MXBoard 快速上手指南
MXBoard 支持了 TensorBoard 中大部分的数据类型,如下图所示。
MXBoard API 的设计参考了 tensorboard-pytorch,所有的记录 API 都定义在一个叫 SummaryWriter 的类当中,这个类含有诸如记录的文件地址、写文件的频率、写文件的队列大小等等信息,用户可以根据需求设置。当需要把当前数据记录成 TensorBoard 中某种数据类型时,用户只要调用相应的 API 即可。
比如,我们想画一个正态分布标准差逐渐缩小的数据分布图。首先定义一个写记录的对象如下,它会把数据写入到当前文件夹下的名为 logs 的文件夹。
from mxboard import *
sw = SummaryWriter(logdir='./logs')
接着在每个循环里,用 MXNet 的随机正态分布算子创建一个 NDArray,把这个 NDArray 传给写数据的 API add_histogram,指定画分布图时 bin 的数量和当前的循环数。最后,和 Python 里常用的文件写入器一样,记得关闭这个 SummaryWriter。
import mxnet as mx
for i in range(10):
# create a normal distribution with fixed mean and decreasing std
data = mx.nd.random.normal(loc=0, scale=10.0/(i+1), shape=(10, 3, 8, 8))
sw.add_histogram(tag='norml_dist', values=data, bins=200, global_step=i)
sw.close()
为了看到效果图,打开命令行窗口,进入到当前文件夹,键入如下命令以打开 TensorBoard:
tensorboard --logdir=./logs --host=127.0.0.1 --port=8888
接着在浏览器地址栏输入 127.0.0.1:8888,点击 HISTOGRAM,就可以看到如下效果图了。
实战 MXBoard
有了使用 MXBoard 的基本概念,我们来尝试通过可视化完成下面两个任务:
监督模型训练
理解卷积神经网络的工作原理
训练 MNIST 模型
借用 Gluon 里训练 MNIST 模型的 Python 程序,用 MXBoard 记录下交叉熵、训练和测试精度、参数的梯度数据分布,可以实时反映出模型训练的进度。
首先定义一个 SummaryWriter 的对象,
sw = SummaryWriter(logdir='./logs', flush_secs=5)
这里加了 flush_secs=5 是为了每五秒就写一次记录到文件,以便在浏览器中及时看到结果。接着在每个 mini-batch 循环结束时记录下交叉熵,
sw.add_scalar(tag='cross_entropy', value=L.mean().asscalar(), global_step=global_step)
在每个 epoch 结束时记录下参数的梯度为 HISTOGRAM,记录下训练和测试精度为 SCALAR,
grads = [i.grad() for i in net.collect_params().values()]
assert len(grads) == len(param_names)
# logging the gradients of parameters for checking convergence
for i, name in enumerate(param_names):
sw.add_histogram(tag=name, values=grads[i], global_step=epoch, bins=1000)
name, acc = metric.get()
# logging training accuracy
sw.add_scalar(tag='train_acc', value=acc, global_step=epoch)
name, val_acc = test(ctx)
# logging the validation accuracy
sw.add_scalar(tag='valid_acc', value=val_acc, global_step=epoch)
然后运行 Python 程序,并运行 TensorBoard,就可以在浏览器中看到以下效果了。小伙伴们可以尝试着用 MXBoard 监督训练更复杂神经网络。更多本实例的代码和解说请点击这里。
可视化卷积层的 filters 和 feature maps
将卷积层的 filters 和 feature maps 当成图片可视化有两个意义:
特征平滑规律的 filters 是模型训练良好的标志之一,未收敛或过拟合模型的卷积层 filters 会出现很多 noise。
观察 filters 和 feature maps 的图片,特别是第一层卷积的图片可以总结出该层所关注的图片特征,这有助于我们理解卷积神经网络的工作原理。
这里将 MXNet Model Zoo 中三个 CNN 模型,Inception-BN,Resnet-152,和 VGG16 的 filters 当成图像输出到 TensorBoard,并将这三组 filters 作用于一张黑天鹅的图片(来自验证数据集 val_256_q90.rec)上观察 feature maps。
Inception-BN
Resnet-152
VGG16
可以看出三个模型的 filters 都表现出良好的光滑性和规律性,彩色 filters 负责提取原始图片前景和背景的局部特征,灰白图片负责提取图片中物体的轮廓特征。复现代码和解释请点击这里。
可视化图片的 embedding
最后这个例子比较有趣。Embedding 在自然语言处理中是一个常用的概念,它是真实世界中物体在高维向量空间中的表示。我们也可以借用此概念到卷积神经网络中。卷积神经网络最后一个全连接层的输出可以看成是一个 batch_size 行、num_labels 列的矩阵,每一行作为一个 num_labels 维的向量就是对应输入图片的 embedding。本质上这个 embedding 就是卷积神经网络对图片的编码,softmax 层通过此编码来判断图片所属类别。当理解了图片 embedding 的概念后,我们就可以把一个图片集的所有 embedding 通过没有 softmax 层的卷积神经网络求出来,调用 MXBoard 的 add_embedding API,从而来观察他们在二维或者三维空间中的聚合效应,即同类别图片应该聚合在一起。
这里我们从上一个例子里的验证数据集中随机选取了 2304 张图片,用 Resnet-152 模型算出了它们的 embeddings,用 MXBoard 写入事件文件,并由 TensorBoard 读取,效果如下。
这里2304张图片的 embeddings 默认由 PCA 算法压缩到了三维空间,不过图片聚合效应似乎不是那么明显,这是因为 PCA 算法不能保持原始物体之间的空间关系。因此,我们选用 TensorBoard 界面上提供的 t-SNE 算法,重新对 embeddings 进行降维操作,这是个动态的过程。
随着 t-SNE 算法的收敛,可以很明显地看到图片集在三维空间中被分成了几类。
最后我们来验证一下图片分类是否正确。在 TensorBoard GUI的右上角输入“dog”,所有打了“dog”标记的图片将被高亮。拖动并放大至高亮图片处,可以看到很多狗的图片,这表明预训练的 Resnet-152 模型是准确的。
全部代码和具体说明请点这里。
后记
通过实战 MXBoard,我们可以看到,可视化工具在监督训练模型和解释深度学习原理方面的强大作用。MXBoard 给 MXNet 提供了一个在科研和生产环境中简单、易用、集中的可视化方案。当所有的代码在后台运行时,你需要的只是一个浏览器。
看了这么多,聪明的你是不是有很多精彩的可视化点子跃跃欲试呢?点击文末链接分享炫酷图片,让 MXNet 动起来。
特别感谢郑子豪在项目开发时提供的技术支持。