五. Tensorflow图的可视化
深度学习模型通常使用错综复杂的神经网络。比如,文献【19】描述的谷歌Inception模型就是一个有36000个独立单元的卷积神经网络。而文献【8】描述的某种长短时记忆模型(LSTM)用到了15000个节点。为了使用和调优如此复杂的网络,必须依赖强有力的可视化工具。Tensorboard是Tensorflow的可视化仪表盘。本章节将讲述Tensorboard的功能。
A. Tensorboard的特性
Tensorboard的核心特性就是构建明细易懂计算图的可视化界面。如下图例子可以看到Tensorboard是如何展示计算图的。
name scope(命名空间)是Tensorflow里面一个重要可视化分类方法。它可以把同属于一个命名空间的算子,关系,输入和输出显示在同一个方框图内。下图展示了,从上图扩展一个layer1命名空间的详细算法细节。
另外,Tensorboard允许用户追踪单个变量在训练过程中的变化情况。你可以附加两类总结算子到计算图上去生成报告(scalar summaries和histogram summaries)。Scalar summaries显示的是张量伸缩的进度图,也就是在某次训练迭代的采样数据。这样你可以看到训练的精确度和损失变化情况。Histogram summaries节点允许用户去追踪数值分布情况,比如神经网络的权重或者softmax估值分布。下图展示了这两种报告。
我们注意到Tensorboard采用了网页交互形式。一旦你的计算图被加载进来,你就可以观察模型,监控算子运行。具体的Tensorboard在线演示可以在这里找到:https://www.tensorflow.org/tensorboard/index.html
B. Tensorboard的实操
为了把Tensorboard整合到你的Tensorflow代码,你需要至少做三步。第一,你需要使用命名空间来规划你的节点。第二,你需要给你的算子增加某种类型的报告。最后第三部,你需要调用SummaryWriter去把Summaries得到的张量写到文件中去。与其分别去写每一个summaries,还不如调用tf.merge_all_summaries()整合所有的summaries,然后一次性写入文件。下面展示了Tensorboard的样例代码。
with tf.name_scope(’Variables’):
x = tf.constant(1.0)
y = tf.constant(2.0)
tf.scalar_summary(’z’, x + y)
merged = tf.merge_all_summaries()
writer = tf.train.SummaryWriter(’/tmp/log’, graph)
with tf.Session(graph=graph):forstepinrange(1000):
writer.add_summary(
merged.eval(), global_step=step)
六. 比较其它深度学习框架
除了Tensorflow,我们还能找到其它一些深度学习框架。人气比较高的有Theano,Torch和Caffe。在这一章,我们会探索这些框架和Tensorflow的异同点,进行一系列定性和定量的分析。
A. 定性分析
下面我们分别比较上述三种深度学习框架和Tensorflow的差异。下图则是汇总了这个比较。
1)Theano:在我们需要讨论的三种Tensorflow的替代框架中,Theano是最像Tensorflow的。如同Tensorflow一样,Theano的编程模型也是声明式而不是命令式的基于计算图。而且,Theano也使用符号差异化。然后Theano有一个比较长时间的图编译时间,因为它需要把Python代码转化为C++/CUDA代码【5】。一方面,这是因为Theano采用了很多高级图优化的算法【5】,而Tensorflow仅仅是做了子图消减优化。对比Tensorboard, Theano的可视化工具可以用可怜来形容。它除了输出一些可读的文字来表示图或静态图像,它还需要一个插件来生成类似交互式网页可视化,剩下来的东西,Theano就是泛善可陈了。
2)Torch:Torch和Tensorflow根本不同的地方是Torch是C/CUDAde后端实现,加上Lua的前端编程接口。Lua确实是相当快的脚本语言,可以快速构建原型系统,但是相对于Python,它算是非主流。虽然Lua 具备各种性能和功能上的优势,但是对于工业界而言,对比Tensorflow的Python API而言,就显得曲高和寡了。除了编程语言的考量,Torch的编程模型也和Tensorflow不同。它采用命令式编程,也不声明计算图。这就要求程序员还要仔细安排算子执行的顺序。这也暗示了Torch在前向和反向传播计算梯度的时候,是用符号到数值而不是符号到符号差异化来优化。
3)Caffe:Caffe和Tensorflow有着天壤之别。Caffe的模型创建拥有MATLAB和Python编程接口,主要使用谷歌的协议缓冲语言,这样带来和Python截然不同的编程体验。另外,在Caffe里面的基本构建单元是神经网络的层,而不是Tensorflow里面的算子。这样Tensorflow算是更为底层的框架。和Torch相似,Caffe也不是专注于构建计算图,或者符号。所以计算导数是通过符号到数值的方法。Caffe特别适合于开发卷积神经网络,用于图像识别任务。但是,它就没有Tensorflow那样在神经网络领域具备普适性。比如Caffe在架构上不支持循环架构,而这时RNN,LSTM这样神经网络的基本构造。另外,Caffe也不支持分布式系统。
B. 定量分析
接下来,我们会对这几种框架做定量分析来,同时给出深度学习框架评估的整体发展趋势。
文献【20】的研究是由博世研发中心在2016年3月进行的,他们对比了Tensorflow,Torch,Theano和Caffe这几种不同的神经网络架构。他们在Intel Xeon E5-1650 v2 CPU @ 3.50 GHz and an NVIDIA GeForce GTX Titan X/PCIe/SSE2 GPU这样配置的机器上安装Ubuntu14.04,然后跑LeNet CNN模型【21】来看不同的框架的性能如何。他们特别留意神经网络的前向传播速度,因为他们相信这和框架部署策略有关;还有反向传播速度,这是和训练模型性能相关。我们摘要了他们结论如下表,这个结果是在两种情况下得到的,(a)是一个CPU跑12个线程,(b)是GPU。从结果来看,有趣的是Tensorflow无论是在CPU还是在GPU都跑不过Torch。最有意思的是Tensorflow在跑GPU的时候成绩掉的很厉害,是倒数第一。文献【20】的作者注意到这可能是由于测试Tensorflow使用的是NVIDIA的cuDNNv2,而其他库用的是v3. 他们在文中强调,这么做是因为Tensorflow的官方文档建议这么配置cuDNN的版本。
我们能够拿到的第二个测试来源是文献【22】卷积神经网络评测平台的结果,你可以在github上找到他们。它是由Facebook的一个AI研究工程师Soumith Chintala维护的。我们参考的结果是2016年五月25日提交的。Chintala提交了围绕卷积神经网络的许多框架的实现,当然包括Tensorflow,Torch和Caffe。Theano没有参加评测,所以我们这里看不到它的有关数据。该作者声称的硬件配置是6-core Intel Core i7-5930K CPU @ 3.50GHz配有an NVIDIA Titan X graphics chip,跑的是Ubuntu14.04。该评测也分别给出了正向传播和反向传播的速度如下表:
不出意料,Tensorflow是仅次于Torch的框架。最后我们来看一下文献【5】的评测,这是由Theano开发团队在2016年5月9日提交的报告。除了CNN模型之外,他们还测试了之前我们提到的AlexNet架构,测试还包括了在Penn Treebank【24】上跑LSTM的结果。他们的评测针对小模型(200个节点的单隐藏层,每个序列长20),统计每秒处理多少单词;针对大模型(两个650个节点的隐藏层,序列长为50)。在文献【5】还提到一个中等模型的测试,这里我们不做讨论,评测结果如下图所示:
这个结果是在硬件配置NVIDIA Digits DevBox with 4 Titan X GPUs and an Intel Core i7-5930K CPU的机器上跑出来的。,而且他们给所有框架使用的都是cuDNN v4。Caffe的运行结果没有在列。在他们的评测结果里,Tensorflow在小模型表现最好,大模型稍差。这个表格来源于文献【5】。
当Tensorflow刚刚发布的时候,表现奇差,整个深度学习社区都表示失望。随后,不断推出的新版本,不断改进和增强功能,给深度学习带来了惊人的进步。这也反映在我们的一系列挑选工作中。最早的三次评测【20】表明,Tensorflow完全不能和Torch,Theano和Caffe相提并论。但是仅仅两个月后,【22】的结果已经显示Tensorflow追赶上来,到了最后的评测【5】的时候,Tensorflow已经处在领先的地位了。我们预测Tensorflow的性能还会继续改进,前途无量。特别是在分布式处理的场景下,目前和可以预见的将来,Tensorflow都将是领先地位。
七. Tensorflow的实际应用
Tensorflow发布才短短六个月,学术界和工业界还没有能够完全拥抱Tensorflow,一些现有应用的移植还需要时间,新的研究还需时日。但是一点毋庸置疑,谷歌已经积极应用和推广Tensorflow在各种任务中【19】【25】【26】【27】【28】。我们将选择性的看一看这些应用是怎么使用Tensorflow的。
A. 学术界
首先提到Tensorflow的是2016年二月的文献【29】,来自谷歌大脑组的Szegedy,Ioffe和Vanhoucke发表的文章。他们用Tensorflow改进了Inception模型【19】,主要用于图像识别。作者给出了ImageNet测试集最高5档3.08%偏差的好成绩。
在文献【25】,Ramsunder等人对于药品发现的多任务网络的讨论使用了Tensorflow,这是斯坦福大学和谷歌之间的联合研究工作。这篇文章描述了使用Tensorflow构建深层神经网络做虚拟扫描来选择潜在的候选药物。这是为了帮助医药公司和科研社区寻找为治疗疾病的新药。
August和Ni应用Tensorflow创建了递归神经网络优化动态解耦,一种在量子内存抑制误差的技术。【30】作者旨在维持量子纠缠态,这是构建通用量子计算机的关键需求。
最后,文献【31】研究了自然语言处理的sequence-to-sequence模型,作者使用Tensorflow,采用滑动窗口技术去做字符级别的英语到拉脱维亚语在音频和视频内容的翻译。作者用这个方法去分类电视节目,广播节目,并且聚类单个的故事。
B. 工业界
除了谷歌之外,工业界还很少有人使用Tensorflow,至少公开的情况来看是这个样子。所以我们来看看谷歌的Tensorflow应用情况。
最近,谷歌在调整它的核心业务算法PageRank【32】系统RankBrain【33】,使用的技术就是Tensorflow。RankBrain使用大规模分布式深度神经网络来做搜索排序。根据文献【33】,超过15%发给www.google.com的查询是全新查询。RankBrain系统可以通过相似性比对来给出未知查询建议。
另一个应用是谷歌的智能邮件回复系统【27】。谷歌已经整合了智能回复功能在其邮件系统的Inbox里面。系统使用递归神经网络和特定LSTM模块进行序列到序列的学习和自然语言理解。一个编码器映射一个语料库到一个“思维向量”,而解码器则在语法和语义上合成正确的回复,然后以建议的形式呈现给用户。
在文献【26】,谷歌在使用卷积神经网络做图像识别和自动文本翻译。作为谷歌手机的内置功能,对于用户来说的外文可以被算法识别,然后翻译成用户识别语言,并且呈现在原文所在图像上。这种方法可以用来翻译图片里的街道名。文献【26】特别强调如果部署这种算法在低端手机设备和慢速网络上。因此,神经网络训练小模型,然后应用于资源首先的场景也在发展。
最后,我们已经注意到谷歌旗下的DeppMind,著名的AI研究机构已经把他们的研究平台从Torch7转移到Tensorflow了。【28】有消息称【17】,DeepMind使用Tensorflow,在谷歌新发布的张量处理单元(TPU)上训练他们的AlphaGo模型。该文献作者就是谷歌DeepMind的雇员,揭示了为什么Tensorflow对于DeepMind有好处的四个理由:
1)Tensorflow的大规模应用是构建在谷歌云平台上,可以很容易提供充足的计算力。
2)Tensorflow支持TPU这样的硬件扩展。
3)Tensorflow的主要编程接口是Python,这是谷歌的核心编程语言,要比Lua能够得到更好的支持。
4)Tensorflow是能够很好支持多GPU的框架。
八. 总结
我们已经从各个方面完整的讨论了Tensorflow,这种基于计算图的开源深度学习库的各种特性,包括能够快速计算梯度,它固有的支持分布式计算的特性,强有力可视化工具。它能够在很细颗粒度构建神经网络,允许高度定制模型,同时也支持一些快速原型搭建的封装库,比如TFLearn。相比Torch,Theano之类的框架,Tensorflow增加了新特征和改进了现有特性。它在性能方面的表现,开始不尽人意,但是随着时间的推移,不断的随着新库的发布在改进。
我们注意到对于Tensorflow的分布式运行性能的评测目前开展的很少。我们认为这是很重要的一环,也是学术界需要深入研究的一点。
Tensorflow已经在开源社区取得了相当的人气和强有力的第三方支持。谷歌已经做出了明智的决定。我们相信,Tensorflow不仅仅对于它的所有者有利,也会惠及更为广大的科研社区;它会打开通往更快更大规模的人工智能之门。
附录-1
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" A one-hidden-layer-MLP MNIST-classifier. """
from__future__importabsolute_importfrom__future__importdivisionfrom__future__importprint_function
# Import the training data (MNIST)
fromtensorflow.examples.tutorials.mnistimportinput_data
importtensorflow as tf
# Possibly download and extract the MNIST data set.
# Retrieve the labels as one-hot-encoded vectors.mnist = input_data.read_data_sets("/tmp/mnist",
one_hot=True)
# Create a new graph
graph = tf.Graph()
# Set our graph as the one to add nodes to
with graph.as_default():
# Placeholder for input examples (None =
variable dimension)
examples = tf.placeholder(shape=[None, 784],
dtype=tf.float32)
# Placeholder for labels
labels = tf.placeholder(shape=[None, 10],
dtype=tf.float32)
weights =
tf.Variable(tf.truncated_normal(shape=[784,
10], stddev=0.1))
bias = tf.Variable(tf.constant(0.1, shape=[10]))
# Apply an affine transformation to the input
features
logits = tf.matmul(examples, weights) + bias
estimates = tf.nn.softmax(logits)
# Compute the cross-entropy
cross_entropy = -tf.reduce_sum(labels*tf.log(estimates),
reduction_indices=[1])
loss = tf.reduce_mean(cross_entropy)
# Create a gradient-descent optimizer that
minimizes the loss.
# We choose a learning rate of 0.01
optimizer =
tf.train.GradientDescentOptimizer(0.5).minimize(loss)
# Find the indices where the predictions were
correct
correct_predictions = tf.equal(
tf.argmax(estimates, dimension=1),
tf.argmax(labels, dimension=1))
accuracy =
tf.reduce_mean(tf.cast(correct_predictions,
tf.float32))
with tf.Session(graph=graph) as session:
tf.initialize_all_variables().run()forstepinrange(1001):
# And finally the loss
example_batch, label_batch =
mnist.train.next_batch(100)
feed_dict = {examples: example_batch, labels:
label_batch}
ifstep % 100 == 0:
_, loss_value, accuracy_value =
session.run(
[optimizer, loss, accuracy],
feed_dict=feed_dict
)print("Loss at time {0}: {1}".format(step,
loss_value))print("Accuracy at time {0}:
{1}".format(step, accuracy_value))
optimizer.run(feed_dict)
参考文献