TensorFlow學習筆記:編程模型 和 反向傳播模型
在TensorFlow中,演算法都被表示成計算圖(computational graphs)。計算圖也叫數據流圖,可以把計算圖看做是一種有向圖,圖中的節點表示操作,圖中的邊代表在不同操作之間的數據流動。
如圖所示,左邊的圖表示x
y
z
是圖中的三個節點,x
和y
分別有一個箭頭指到z
,在z
節點的下方有一個+
號,表明是一個加法操作,因此最後的輸出結果就是
在這樣的數據流圖中,有四個主要的元素: * 操作(operations) * 張量(tensors) * 變數(variables) * 會話(sessions)
操作
把演算法表示成一個個操作的疊加,可以非常清晰地看到數據之間的關係,而且這樣的基本操作也具有普遍性。在TensorFlow中,當數據流過操作節點的時候就可以對數據進行操作。一個操作可以有零個或多個輸入,產生零個或多個輸出。一個操作可能是一次數學計算,一個變數或常量,一個數據流走向控制,一次文件IO或者是一次網路通信。其中,一個常量可以看做是沒有輸入,只有一個固定輸出的操作。具體操作如下所示:
操作類型 | 例子 |
---|---|
元素運算 | Add,Mul |
矩陣運算 | MatMul,MatrixInverse |
數值產生 | Constant,Variable |
神經網路單元 | SoftMax,ReLU,Conv2D |
I/O | Save,Restore |
每一種操作都需要相對應的底層計算支持,比如在GPU上使用就需要實現在GPU上的操作符,在CPU上使用就要實現在CPU上的操作符。
張量在計算圖中,每個邊就代表數據從一個操作流到另一個操作。這些數據被表示為張量,一個張量可以看做是多維的數組或者高維的矩陣。 關於TensorFlow中的張量,需要注意的是張量本身並沒有保存任何值,張量僅僅提供了訪問數值的一個介面,可以看做是數值的一種引用。在TensorFlow實際使用中我們也可以發現,在run
之前的張量並沒有分配空間,此時的張量僅僅表示了一種數值的抽象,用來連接不同的節點,表示數據在不同操作之間的流動。 TensorFlow中還提供了SparseTensor
數據結構,用來表示稀疏張量。
變數是計算圖中可以改變的節點。比如當計算權重的時候,隨著迭代的進行,每次權重的值會發生相應的變化,這樣的值就可以當做變數。在實際處理時,一般把需要訓練的值指定為變數。在使用變數的時候,需要指定變數的初始值,變數的大小和數據類型就是根據初始值來推斷的。
在構建計算圖的時候,指定一個變數實際上需要增加三個節點: * 實際的變數節點 * 一個產生初始值的操作,通常是一個常量節點 * 一個初始化操作,把初始值賦予到變數
如圖所示,v
代表的是實際的變數,i
是產生初始值的節點,上面的assign
節點將初始值賦予變數,assign
操作以後,產生已經初始化的變數值v"
。
在TensorFlow中,所有操作都必須在會話(session)中執行,會話負責分配和管理各種資源。在會話中提供了一個run
方法,可以用它來執行計算圖整體或者其中的一部分節點。在進行run
的時候,還需要用feed_dict
把相關數據輸入到計算圖。 當run
被調用的時候,TensorFlow將會從指定的輸出節點開始,向前查找所有的依賴界節點,所有依賴節點都將被執行。這些操作隨後將被分配到物理執行單元上(比如CPU或GPU),這種分配規則由TensorFlow中的分配演算法決定。
2 執行
在執行的時候,TensorFlow支持兩種方式:一種是單機版本,可以在單機上支持多個計算設備,還有一種是分散式版本,支持多機多設備。在TensorFlow剛出來的時候,只支持第一種方式,後來開源了分散式版本。
當client發出run
請求時,master會將這個請求分配到不同的worker上,這些worker負責監控具體的計算設備。
計算設備
所有的計算任務最終都將分配到實際的硬體上執行。除了CPU和GPU之外,TensorFlow也支持自定義硬體,比如谷歌自己使用的TPU(Tensor Processing Unit)。一個worker需要管理多個設備,所以這些設備的名稱需要加上worker的名字,比如/cpu:0
表示第一個CPU。
如何將某個計算節點分配到具體設備上,TensorFlow提供了分配演算法(placement algorithm)。 分配演算法首先模擬計算圖的執行,從輸入節點到輸出節點進行遍歷,在遍歷過程中遇到節點v
,需要決定將這個節點分配到設備
跨設備執行
如果用戶系統有多個設備,任務分配演算法就需要將節點分配到不同的設備上,在這個分配過程中,可能會出現一個設備中的輸入依賴於另一個設備上的輸出。此時就需要設備之間交叉執行。
如圖所示,設備A上有節點send
和recv
節點,在節點send
節點,在recv
節點,send
和recv
節點之間使用額外的邊進行鏈接。當數據流過這兩個節點的時候就需要進行設備間通信,設備間通信方式包括TCP和RDMA等方式。此外,TensorFlow還會對recv
節點進行進一步的優化,可以將設備B上的兩個recv
節點進行合併,減少通信次數,如圖(c)所示。
3 優化
在編譯的時候,TensorFlow還會進行一些優化以提高性能。
子圖消除
在程序中,常常有一些重複的操作,可以把這些操作進行合併。可以將反覆進行計算的同一個子圖進行合併,保存其中的一個輸出,在其他地方只需要直接調用就可以了。
調度優化節點的執行越晚越好,這樣的話,這個節點只在內存中保留較短的時間,可以有效降低內存的使用量。合理調度也能降低send
和recv
節點的網路衝突。
許多機器學習演算法不需要高的浮點精度,比如float32,只需要16位精度就夠了,因此可以將32位精度降低為16位精度。當需要轉換成32位精度時,只需要將尾部直接補0即可。
4 反向傳播的計算圖
在神經網路訓練中,需要使用到反向傳播演算法。在TensorFlow等深度學習框架中,梯度計算都是自動進行的,不需要人工進行梯度計算,這樣只需要使用者定義網路的結構,其他工作都由深度學習框架自動完成,大大簡化了演算法驗證。在TensorFlow中,梯度計算也是採用了計算圖的結構。
如圖,在神經網路中常常需要對權重w
進行求導。這樣的函數前向計算的式子為:
推薦閱讀:
※一次性解決數學筆記所有問題
※《欲樂與法樂的省思》要點筆記(2/4 )
※三主要道甚深引導筆記·開妙道門 一.序分 1.本文的說法上師與文字來源
※(1)孫軍暉舞蹈班學舞筆記