五. 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)
參考文獻