TensorFlow學習筆記:編程模型 和 反向傳播模型

1 計算圖

在TensorFlow中,演算法都被表示成計算圖(computational graphs)。計算圖也叫數據流圖,可以把計算圖看做是一種有向圖,圖中的節點表示操作,圖中的邊代表在不同操作之間的數據流動。

如圖所示,左邊的圖表示z=x+y。從圖中可以看到,x y z是圖中的三個節點,xy分別有一個箭頭指到z,在z節點的下方有一個+號,表明是一個加法操作,因此最後的輸出結果就是z=x+y。右圖是一種相對複雜點的情況,隨著計算圖逐步分析可以得到y^=σ(xTw+b)

在這樣的數據流圖中,有四個主要的元素: * 操作(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,需要決定將這個節點分配到設備D={d1,...,dn}中的某一個設備上,具體分配將使用一個成本模型Cv(d)。這個成本模型需要考慮四個方面的信息來決定最優的執行設備d^=argmind∈DCv(d)

  • 該設備是否實現了這個操作,比如某個操作不能在GPU上實現,那麼所有的GPU成本都為無窮大。
  • 估計節點的輸入和輸出數據大小
  • 在設備上執行時間
  • 如果輸入的數據在另一個設備上,還需要考慮數據在不同設備間傳輸的成本
  • 跨設備執行

    如果用戶系統有多個設備,任務分配演算法就需要將節點分配到不同的設備上,在這個分配過程中,可能會出現一個設備中的輸入依賴於另一個設備上的輸出。此時就需要設備之間交叉執行。

    如圖所示,設備A上有節點ν,設備B上有節點αβ,其中ν的輸出是αβ的輸入。在計算圖中,ν→αν→β就需要跨設備執行。此時,TensorFlow將會自動在適當位置增加sendrecv節點,在節點ν後面增加一個send節點,在αβ前面增加recv節點,sendrecv節點之間使用額外的邊進行鏈接。當數據流過這兩個節點的時候就需要進行設備間通信,設備間通信方式包括TCP和RDMA等方式。此外,TensorFlow還會對recv節點進行進一步的優化,可以將設備B上的兩個recv節點進行合併,減少通信次數,如圖(c)所示。


    3 優化

    在編譯的時候,TensorFlow還會進行一些優化以提高性能。

    子圖消除

    在程序中,常常有一些重複的操作,可以把這些操作進行合併。可以將反覆進行計算的同一個子圖進行合併,保存其中的一個輸出,在其他地方只需要直接調用就可以了。

    調度優化

    節點的執行越晚越好,這樣的話,這個節點只在內存中保留較短的時間,可以有效降低內存的使用量。合理調度也能降低sendrecv節點的網路衝突。

    精度優化

    許多機器學習演算法不需要高的浮點精度,比如float32,只需要16位精度就夠了,因此可以將32位精度降低為16位精度。當需要轉換成32位精度時,只需要將尾部直接補0即可。


    4 反向傳播的計算圖

    在神經網路訓練中,需要使用到反向傳播演算法。在TensorFlow等深度學習框架中,梯度計算都是自動進行的,不需要人工進行梯度計算,這樣只需要使用者定義網路的結構,其他工作都由深度學習框架自動完成,大大簡化了演算法驗證。在TensorFlow中,梯度計算也是採用了計算圖的結構。

    如圖,在神經網路中常常需要對權重w進行求導。這樣的函數前向計算的式子為:

    z=h(y),y=g(x),x=f(w)整合一下就可以得到:z=h(g(f(w)))使用鏈式求導法則,可以得到dzdw=dzdydydxdxdw在計算圖中,每個節點邊上會自動增加梯度節點,然後每個梯度節點與前一個梯度節點相乘,最終在右下角可以得到dzdw的值。
    推薦閱讀:

    一次性解決數學筆記所有問題
    《欲樂與法樂的省思》要點筆記(2/4 )
    三主要道甚深引導筆記·開妙道門 一.序分 1.本文的說法上師與文字來源
    (1)孫軍暉舞蹈班學舞筆記

    TAG:編程 | 學習 | 筆記 | 傳播 | TensorFlow | 模型 |