1. 程式人生 > >淺談tensorflow框架和深度學習應用

淺談tensorflow框架和深度學習應用

由於本框架支援python和C++介面,從系統和程式碼的角度分析內部實現的原理,從核心框架到Opkemels模組、Graph模組、Session模組。由於具有良好的延展性所以得到廣泛應用,設計理念我認為和現在的模組式並沒有多大區別這種基於UML的建模方法計算框架應用已經非常成熟。從底層的裝置管理層-通訊層-資料操作層-圖計算層
裝置管理層主要是對CPU、GPU、Mobile的MPU、APU的呼叫問題,理多執行緒就是非同步,單執行緒就是同步
同步是阻塞模式,非同步是非阻塞模式。

從一定意義上講,程序就是一個應用程式在處理機上的一次執行過程,它是一個動態的概念,而執行緒是程序中的一部分,程序包含多個執行緒在執行。
程式是一個沒有生命的實體,只有處理器賦予程式生命時,它才能成為一個活動的實體,我們稱其為程序。
通常在一個程序中可以包含若干個執行緒,它們可以利用程序所擁有的資源。在引入執行緒的作業系統中,通常都是把程序作為分配資源的基本單位,而把執行緒作為獨立執行和獨立排程的基本單位。由於執行緒比程序更小,基本上不擁有系統資源,故對它的排程所付出的開銷就會小得多,能更高效的提高系統內多個程式間併發執行的程度。
執行緒和程序的區別在於,子程序和父程序有不同的程式碼和資料空間,而多個執行緒則共享資料空間,每個執行緒有自己的執行堆疊和程式計數器為其執行上下文
多執行緒主要是為了節約CPU時間,發揮利用,根據具體情況而定。**要使用計算機的記憶體資源和CPU。
程序間相互獨**
程序間相互獨立,同一程序的各執行緒間共享。某程序內的執行緒在其它程序不可見。
**體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位。執行緒自己基本上不擁有系統資源,
只擁有一點在執行中必不可少的資源(如程式計數器,一組暫存器和棧),但是它可與同屬一個程序的其他的執行緒共享程序所擁有的全部資源。**程所擁有的全部資源。

CPU和GPU之所以大不相同,是由於其設計目標的不同,它們分別針對了兩種不同的應用場景。CPU需要很強的通用性來處理各種不同的資料型別,同時又要邏輯判斷又會引入大量的分支跳轉和中斷的處理。這些都使得CPU的內部結構異常複雜。而GPU面對的則是型別高度統一的、相互無關聯的大規模資料和不需要重複性大規模計算環境下面就是CPU和GPU架構的比對
tensorflow目錄包括tf核心程式碼模組
public API介面標頭檔案目錄用於外部介面的API定義呼叫,主要是session.h和tensor_c_api.h
client API實現檔案目錄
plattrom OS系統的介面檔案,file、system、env and so on
common_runtime公共執行庫主要是session、excutor,threadpool randezvous,memory管理,裝置分配排程演算法
distracted_runtime分散式模組,rpc,session,master、rpc,worker、graph、manager
framework ,(log、memory、tensor)。 graph: 計算流圖相關操作,如construct, partition, optimize, execute等
kernels: 核心Op,如matmul, conv2d, argmax, batch_norm等
lib: 公共基礎庫,如gif、gtl(google模板庫)、hash、histogram等。
ops: 基本ops運算,ops梯度運算,io相關的ops,控制流和資料流操作
Tensorflow/stream_executor目錄是平行計算框架,由google stream executor團隊開發。
Tensorflow/contrib目錄是contributor開發目錄。Tensroflow/python目錄是python API客戶端指令碼。Tensorflow/tensorboard目錄是視覺化分析工具,不僅可以模型視覺化,還可以監控模型引數變化。third_party目錄是TF第三方依賴庫eigen3: eigen矩陣運算庫,TF基礎ops呼叫gpus: 封裝了cuda/cudnn程式設計庫。
理論核心框架
基於Grahp展開,原理是演算法和引數封裝到tensor裡面順著Graph傳遞閉合包flow的,這裡設計量子數學知識。
Graph之前需要進行的輔助工程是符合程式設計、計算流圖、梯度計算、控制流的概念。
從Matrix表示二維線性對映開始,tensor主要表示多維線性對映,這種維度上為了達到泛化和高維特徵的對映,對映關係不是等於不要出現邏輯錯誤打算用數學的反證法證明是絕對不行的,但是可以從幾何角度可以證明,相關案例在紐約大學顧險峰教授的部落格,表示在1-dim、2-dim、3-dim到n-dim的高維空間
張量積運算是在matmul和conv2D運算中用到的,張量積和矩陣乘法是兩個概念

加速張量並行運算是TF優先考慮的問題,如add,contract, slice, reshape, reduce, shuffle等運算。TF中Tensor的維數描述為階,數值是0階,向量是1階,矩陣是2階,以此類推,可以表示n階高維資料。TF中Tensor支援的資料型別有很多,如tf.float16, tf.float32, tf.float64, tf.uint8, tf.int8, tf.int16, tf.int32, tf.int64, tf.string, tf.bool, tf.complex64等,所有Tensor運算都使用泛化的資料型別表示。TF的Tensor定義和運算主要是呼叫Eigen矩陣計算庫完成的。TF中Tensor的UML定義如圖 2 2。其中TensorBuffer指標指向Eigen::Tensor型別。其中,Eigen::Tensor[5][6]不屬於Eigen官方維護的程式,由貢獻者提供文件和維護,所以Tensor定義在Eigen unsupported模組中。
Tensor主要包含兩個變數m_data和m_dimension,m_data儲存了Tensor的資料塊,T是泛化的資料型別,m_dimensions儲存了Tensor的維度資訊。Eigen::Tensor的成員變數很簡單,卻支援非常多的基本運算,再借助Eigen的加速機制實現快速計算,參考章節3.2。Eigen::Tensor主要包含了
一元運算(Unary),如sqrt、square、exp、abs等。
二元運算(Binary),如add,sub,mul,div等
選擇運算(Selection),即if / else條件運算
歸納運算(Reduce),如reduce_sum, reduce_mean等
幾何運算(Geometry),如reshape,slice,shuffle,chip,reverse,pad,concatenate,extract_patches,extract_image_patches等
張量積(Contract)和卷積運算(Convolve)是重點運算,後續會詳細講解。
程式設計模式通常分為指令式程式設計(imperative style programs)和符號式程式設計(symbolic style programs)。指令式程式設計容易理解和除錯,命令語句基本沒有優化,按原有邏輯執行。符號式程式設計涉及較多的嵌入和優化,不容易理解和除錯,但執行速度有同比提升。這兩種程式設計模式在實際中都有應用,Torch是典型的命令式風格,caffe、theano、mxnet和Tensorflow都使用了符號式程式設計。其中caffe、mxnet採用了兩種程式設計模式混合的方法,而Tensorflow是完全採用了符號式程式設計,Theano和Tensorflow的程式設計模式更相近指令式程式設計是常見的程式設計模式,程式語言如python/C++都採用指令式程式設計。指令式程式設計明確輸入變數,並根據程式邏輯逐步運算,這種模式非常在除錯程式時進行單步跟蹤,分析中間變數
符號式程式設計將計算過程抽象為計算圖,計算流圖可以方便的描述計算過程,所有輸入節點、運算節點、輸出節點均符號化處理。計算圖通過建立輸入節點到輸出節點的傳遞閉包,從輸入節點出發,沿著傳遞閉包完成數值計算和資料流動,直到達到輸出節點。這個過程經過計算圖優化,以資料(計算)流方式完成,節省記憶體空間使用,計算速度快,但不適合程式除錯,通常不用於程式語言中。舉上面的例子,先根據計算邏輯編寫符號式程式並生成計算圖

目前的符號語言比起來,TF最大的特點是強化了資料流圖,引入了mutation的概念。這一點是TF和包括Theano在內的符號程式設計框架最大的不同。所謂mutation,就是可以在計算的過程更改一個變數的值,而這個變數在計算的過程中會被帶入到下一輪迭代裡面去。
Mutation是機器學習優化演算法幾乎必須要引入的東西(雖然也可以通過immutable replacement來代替,但是會有效率的問題)。 Theano的做法是引入了update statement來處理mutation。TF選擇了純符號計算的路線,並且直接把更新引入了資料流圖中去。從目前的白皮書看還會支援條件和迴圈。這樣就幾乎讓TF本身成為一門獨立的語言。不過這一點會導致最後的API設計和使用需要特別小心,把mutation 引入到資料流圖中會帶來一些新的問題,比如如何處理寫與寫之間的依賴
梯度計算主要應用在誤差反向傳播和資料更新,是深度學習平臺要解決的核心問題。梯度計算涉及每個計算節點,每個自定義的前向計算圖都包含一個隱式的反向計算圖。從資料流向上看,正向計算圖是資料從輸入節點到輸出節點的流向過程,反向計算圖是資料從輸出節點到輸入節點的流向過程。對應的反向計算圖。由於C=A*B,則dA=B*dC, dB=A*dC。在反向計算圖中,輸入節點dD,輸出節點dA和dB,計算表示式為dA=B*dC=B*dD, dB=A*dC=A*dD。每一個正向計算節點對應一個隱式梯度計算節點。
控制流主要為了提高邏輯計算控制,介面函式是pred判別表示式,fn1和fn2運算表示式當pred為true時執行fn1,反正false時執行fn2.
TF還可以協調多個數據流,在存在依賴節點的場景下非常有用,例如節點B要讀取模型引數θ更新後的值,而節點A負責更新引數θ,則節點B必須等節點A完成後才能執行,否則讀取的引數θ為更新前的數值,這時需要一個運算控制器。介面函式如下,tf.control_dependencies函式可以控制多個數據流執行完成後才能執行接下來的操作,通常與tf.group函式結合使用。

TF支援的控制運算元有Switch、Merge、Enter、Leave和NextIteration等。TF不僅支援邏輯控制,還支援迴圈控制。TF使用和MIT Token-Tagged machine相似的表示系統,將迴圈的每次迭代標記為一個tag,迭代的執行狀態標記為一個frame,但迭代所需的資料準備好的時候,就可以開始計算,從而多個迭代可以同時執行。