写给初学者的Tensorflow介绍
Tensorflow是廣泛使用的實現機器學習以及其它涉及大量數學運算的算法庫之一。Tensorflow由Google開發,是GitHub上最受歡迎的機器學習庫之一。Google幾乎在所有應用程序中都使用Tensorflow來實現機器學習。 例如,如果您使用到了Google照片或Google語音搜索,那么您就間接使用了Tensorflow模型。它們在大型Google硬件集群上工作,在感知任務方面功能強大。
本文的主要目的是為TensorFlow提供一個對初學者友好的介紹,我假設您已經知道一些python知識。 TensorFlow的核心組件是通過邊遍歷所有節點的計算圖和張量。我們來逐個簡單介紹一下。
張量(Tensor)
在數學上,張量是N維向量,這意味著張量可以用來表示N維數據集。上面的圖有點復雜,難以理解。我們看看它的簡化版本:
上圖顯示了一些簡化的張量。隨著維度的不斷增加,數據表示將變得越來越復雜。例如,一個3x3的張量,我可以簡單地稱它為3行和列的矩陣。如果我選擇另一個形式的張量(1000x3x3),我可以稱之為一個向量或一組1000個3x3的矩陣。在這里我們將(1000x3x3)稱為張量的形狀或尺寸。張量可以是常數也可以是變量。
計算圖(流, flow)
現在我們理解了Tensor的含義,是時候了解流(Flow)了。流是指一個計算圖或簡單的一個圖,圖不能形成環路,圖中的每個節點代表一個操作,如加法、減法等。每個操作都會導致新的張量形成。
上圖展示了一個簡單的計算圖,所對應的表達式為:
e = (a+b)x(b+1)- 1
計算圖具有以下屬性:
-
葉子頂點或起始頂點始終是張量。意即,操作永遠不會發生在圖的開頭,由此我們可以推斷圖中的每個操作都應該接受一個張量并產生一個新的張量。同樣,張量不能作為非葉子節點出現,這意味著它們應始終作為輸入提供給操作/節點。
-
計算圖總是以層次順序表達復雜的操作。通過將a + b表示為c,將b + 1表示為d,可以分層次組織上述表達式。 因此,我們可以將e寫為:
- 1
-
以反序遍歷圖形而形成子表達式,這些子表達式組合起來形成最終表達式。
-
當我們正向遍歷時,遇到的頂點總是成為下一個頂點的依賴關系,例如沒有a和b就無法獲得c,同樣的,如果不解決c和d則無法獲得e。
-
同級節點的操作彼此獨立,這是計算圖的重要屬性之一。當我們按照圖中所示的方式構造一個圖時,很自然的是,在同一級中的節點,例如c和d,彼此獨立,這意味著沒有必要在計算d之前計算c。 因此它們可以并行執行。
計算圖的并行
上面提到的最后一個屬性當然是最重要的屬性之一。它清楚地表明,同級的節點是獨立的,這意味著在c被計算之前不需空閑,可以在計算c的同時并行計算d。Tensorflow充分利用了這個屬性。
分布執行
Tensorflow允許用戶使用并行計算設備更快地執行操作。計算的節點或操作自動調度進行并行計算。這一切都發生在內部,例如在上圖中,可以在CPU上調度操作c,在GPU上調度操作d。下圖展示了兩種分布式執行的過程:
第一種是單個系統分布式執行,其中單個Tensorflow會話(將在稍后解釋)創建單個worker,并且該worker負責在各設備上調度任務。在第二種系統下,有多個worker,他們可以在同一臺機器上或不同的機器上,每個worker都在自己的上下文中運行。在上圖中,worker進程1運行在獨立的機器上,并調度所有可用設備進行計算。
計算子圖
子圖是主圖的一部分,其本身就是計算圖。例如,在上面的圖中,我們可以獲得許多子圖,其中之一如下所示
上面的圖是主圖的一部分,從屬性2我們可以說子圖總是表示一個子表達式,因為c是e的子表達式。 子圖也滿足最后一個屬性。同一級別的子圖也相互獨立,可以并行執行。因此可以在一臺設備上調度整個子圖。
上圖解釋了子圖的并行執行。這里有2個矩陣乘法運算,因為它們都處于同一級別,彼此獨立,這符合最后一個屬性。由于獨立性的緣故,節點安排在不同的設備gpu_0和gpu_1上。
在worker之間交換數據
現在我們知道Tensorflow將其所有操作分配到由worker管理的不同設備上。更常見的是,worker之間交換張量形式的數據,例如在e =(c)*(d)的圖表中,一旦計算出c,就需要將其進一步傳遞給e,因此Tensor在節點間前向流動。 該流動如圖所示:
此處張量從設備A傳遞到設備B。這在分布式系統中引起了一些性能延遲。延遲取決于一個重要屬性:張量大小。設備B處于空閑模式,直到它接收到設備A的輸入。
壓縮的必要性
很顯然,在計算圖中,張量在節點之間流動。在流到達可以處理的節點之前,減少流造成的延遲非常重要。一個方法是使用有損壓縮減小尺寸。
張量的數據類型可以發揮重要作用,讓我們來理解為什么。很明顯機器學習中的操作中有更高的精度。例如,如果我們使用float32作為張量的數據類型,那么每個值都表示為32位浮點數,因此每個值占用32位的大小,這同樣適用于64位。假設一個形狀為(1000,440,440,3)的張量,其包含的值的數量為1000 * 440 * 440 * 3。如果數據類型是32位,那么占用的空間是這個巨大數字的32倍,從而增加了流的延遲。壓縮技術可以用來減小尺寸。
有損壓縮
有損壓縮涉及壓縮數據的大小,并不在意它的值,這意味著它的值可能會在壓縮過程中被破壞或不準確。 但是,如果我們有一個像1.01010e-12這樣的32位浮點數,那么對于最低有效數字的重要性就會降低。 更改或刪除這些值不會在我們的計算中產生太大的差異。因此,Tensorflow會自動將32位浮點數轉換為16位表示,忽略所有可忽略的數字。如果它是64位數,則會將其大小減少近一半。如果將64位數壓縮到16位將幾乎縮小75%。因此張量所占用的空間可以盡可能減少。
一旦張量到達節點,16位表示可以通過追加0回到它的原始形式。因此,32或64位表示將在到達節點進行處理后被還原。
到這里,我們就結束了Tensorflow介紹的第1部分,編程和構建簡單的子圖將在下一部分進行介紹。
總結
以上是生活随笔為你收集整理的写给初学者的Tensorflow介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五分钟带你入门TensorFlow
- 下一篇: Tensorflow从入门到精通之——T