知識圖譜
TensorFlow運行機制
TensorFlow是基于計算圖的深度學習編程模型
Tensor表示張量,其實質上是某種類型的多維數組 ?
Flow表示基于數據流圖的計算,實質上是張量在不同節點間的轉化過程。
在TensorFlow中,計算圖中的節點稱為OP(即operation的縮寫),節點之間的邊描述了計算之間的依賴關系。
在計算過程中,一個節點可獲得0或多個張量,產生0或多個張量。
TensorFlow程序通常被組織成圖的構建階段和執行階段
在構建階段,節點的執行步驟被描述成一個圖
在執行階段,使用會話執行圖中的OP
TensorFlow系統架構
TensorFlow支持各種異構平臺,支持多CPU/GPU、移動設備、具有良好的跨平臺的特性;
架構靈活,能支持各種網絡模型,具有良好的通用性。
系統結構以C API為界限,將整個系統分為前端和后端兩個系統
?
如圖所示組件構成TensorFlow 系統分布式運行機制的核心,其中每個組件的作用如下。
Client: 是前端系統的主要組成部分。它是一個 支持多語言的編程環境, 提供了基于計算圖的編程模型,方便用戶構造各種復雜的計算圖,實現各種形式的模型設計。
Distrubuted Runtime: 在分布式的運行時環境中,Distributed Master根據Session.run的Fetching 參數,從計算圖中反向遍歷,找到所依賴的最小子圖。對于每個任務,TensorFlow 都將啟動一個Worker Service,按照計算圖中節點之間的依賴關系,根據當前的可用的硬件環境(CPU/GPU),調用節點的Kernel實現完成節點的運算。
Kermnel Implements: 大多數Kernel 基于Eigen::Tensor實現。Eigen:Tensor 是一 個使用C++模板技術,為多核CPU/GPU生成高效的并發代碼,包含200 多個標準的張量,包括數值計算、多維數組操作、控制流、狀態管理等。每一個節點根據設備類型都會存在一個優化了的Kernel實現,在運行時,運行時根據本地設備的類型,為節點選擇特定的Kernel實現,完成該節點的計算
構建計算圖
計算圖描述了一組需要依次序完成的計算單元以及這些計算單元之間相互依賴的關系。
計算圖的構建階段也稱為計算圖的定義階段,該過程會在圖模型中定義所需的運算,每次運算的結果以及原始的輸入數據都可稱為一個節點。
下面代碼給出了計算圖的定義過程
上述代碼定義了兩個張量相加的計算圖如下
每個節點表示一個運算,每條邊代表計算之間的依賴關系。
a、b節點表示兩個1行2列的矩陣,result節點則依賴于讀取a和b的值,從a、b有兩條到result的邊,沒有任何計算依賴result的結果,result節點沒有指向其他節點的邊。
#導入tensorflow類庫,取別名為tf
import tensorflow as tf
#定義一個整型張量a,表示1行2列的矩陣,其值為[3,5]
a = tf.constant([3,5],dtype=tf.int32)
#定義一個整型張量b,表示1行2列的矩陣,其值為[2,4]
b = tf.constant([2,4],dtype=tf.int32)
#tf.add()函數用于對張量a,b相加,并將計算結果返回給result節點。
result = tf.add(a,b)
#print(result)函數打印result節點的信息
print(result)
運行程序,輸出結果如下:
Tensor("Add_1:0", shape=(2,), dtype=int32)
從運行結果上可看出,上述程序并沒有輸出矩陣相加的結果,而是輸出了一個包含3個屬性的張量,第1個屬性表示加法運算,第2個屬性表示包含2個元素的一維數組,第3個屬性表示數據類型為整型。
需要注意的是,TensorFlow計算圖一般包含兩個特殊節點,分別為Source節點(也稱Start節點)與Sink節點(也稱為Finish節點)。其中,Sourse節點表示此節點不依賴任何其他節點作為輸入,Sink節點表示該節點無任何輸出作為其他節點的輸入。
在會話中運行計算圖
在TensorFlow中啟動會話有兩種方法:
①明確調用創建會話函數和關閉會話函數,代碼格式如下:
#創建一個會話
sess = tf.Session()
#使用該會話來運行相關節點,得到運算結果
sess.run(...)
#關閉會話
sees.close()
上述代碼中,所有計算完成后,需要明確調用close()函數來關閉會話并釋放資源。
若程序因為異常退出,就可能無法執行close()函數,進而導致資源泄露。為了解決異常退出時的資源泄露問題,TensorFlow中還可通過上下文管理器來管理會話。
②通過上下文管理器來管理會話,代碼格式如下:
#創建一個會話,并使用上下文管理器管理會話
with tf.Session() as sess:
#使用該會話來運行相關節點,得到運算結果
sees.run(...)
#不需要調用close()函數,當上下文退出時會話關閉,資源自動釋放
下面通過上下文管理器來實現兩個張量的相加,代碼如下:
在TensorFlow,系統會自動維護默認的計算圖
通過tf.get_default_graph()函數可以獲得當前的默認的計算圖,代碼如下
import tensorflow as tf
a = tf.constant([1.0,2.0],name = 'a')
b = tf.constant([1.0,2.0],name = 'b')
result = a + b
print(a.graph is tf.get_default_graph)
第五行代碼:通過a.graph查看張量所屬的計算圖。如果沒有特別指定,則查看當前默認的計算圖
指定GPU設備
如果下載的Tensorflow是GPU版本,在程序運行過程中系統會自動檢測可用利用的GPU來執行操作
如果計算機上有不止一個GPU資源,除第一個之外,其他的GPU不參與計算。為了讓Tensorflow能夠使用這些GPU資源,必須將節點明確地指派給定的GPU執行。
with……device語句用來指定CPU或GPU
示例:
import tensorflow as tf
with tf.device('/gpu:1') # 指定在第一塊GPU設備上運行v1 = tf.constant([1.0,2.0,3.0],shape = [3],name = 'v1')v2 = tf.constant([4.0,5.0,6.0],shape = [3],name = 'v2')sum = v1 + v2
with tf.Session() as sess:print(sees.run(sum))
TensorFlow數據類型
張量及其屬性
張量是TensorFlow中最重要的數據結構,用來表示程序中的數據。
在計算圖節點間傳遞的數據都是張量
可以把張量看作一個n維數組或列量,每個張量都包含 類型、階、形狀
類型
TensorFlow吸收了Python的原生數據類型,如布爾型,數值型(整數、浮點數)和字符串型。
除此之外,TensorFlow還有一些自有的數據類型
數據類型 | 描述 |
tf.float32 | 32位浮點數 |
tf.float64 | 64位浮點數 |
tf.int64 | 64位有符號整型 |
tf.int32 | 32位有符號整型 |
tf.int16 | 16位有符號整型 |
tf.int8 | 8位有符號整型 |
tf.uint8 | 8位無符號整型 |
tf.string | 可變長的字節數組,每一個張量元素都是一個字節數組 |
tf.bool | 布爾型 |
tf.complex64 | 由兩個32位浮點數組成的復數:實數和虛數 |
以下代碼定義了不同類型的張量
import tensorflow as tf
hello = tf.constant("Hello,world!",dtype=tf.string)
boolean = tf.constant(False,dtype=tf.bool)
int = tf.constant(100,dtype=tf.int8)
uint = tf.constant(100,dtype=tf.uint8)
float = tf.constant(100,dtype=tf.float32)
with tf.Session() as sess:print(sess.run(hello))print(sess.run(boolean))print(sess.run(int))print(sess.run(uint))print(sess.run(float))
階
在TensorFlow系統中,張量的維數被描述為階。
注意,張量的階和矩陣的階并不是同一個概念,張量的階是張量維數的數量描述。
例如:下面張量是2階張量
t = [[1,2,3],[4,5,6],[7,8,9]] (最外層中括號有幾個就是幾階)
一階張量可以認為是一個向量,二階張量可以認為是二維數組,用t[i,j]訪問其中的元素,三階張量可以用t[i,j,k]訪問其中的元素
常見的張量及其對應的階
階 | 實例 | 例子 |
0 | 純量(只有大小) | a = 1 |
1 | 向量(大小和方向) | v = [1,2,3] |
2 | 矩陣(二維數組) | m = [[1,2,3],[4,5,6],[7,8,9]] |
3 | 3階張量(數據立體) | t=[[[1],[2],[3]],[[4],[5],[6]],[[7],[8],[9]]] |
N | n階 | n中的括號數 |
形狀
?形狀用于描述張量內部的組織關系。
簡單來講,就是該張量有幾行幾列
下面來定義一個張量,并分別輸出張量的類型、形狀以及階
import tensorflow as tf
c = tf.constant([[3.0,4.0,5.0],[6.0,7.0,8.0]])
print("張量類型:",c.dtype)
print("張量形狀:",c.get_shape())
print("張量的階:",c.get_shape().ndims)
類型轉換
TensorFlow程序運行過程中,常常會涉及不同類型張量之間相互轉換。
TensorFlow提供了多種類型轉換函數,其語法格式為:
函數名 | 含義 |
tf.string_to_number(string_tensor,out_type = None,name = None) | 將字符串轉換為數字 out_type:可選tf.float32、tf.int32,默認為f.float32 |
tf.to_double(x,name = None) | 將其他類型轉換為double類型 |
tf.int32(x,name = None) | 將其他類型轉換為int32 |
tf.cast(x,dtype,name = None) | 將x的值轉換為dtype指定的類型 |
下面我們來將整型張量轉換為浮點張量
import tensorflow as tf
float_tensor = tf.cast(tf.constant([1,2,3]),dtype=tf.float32)
init = tf.global_variables_initializer()
with tf.Session() as sess:sess.run(init)print(sess.run(float_tensor))
形狀變換
在實際應用過程中,有時需要將張量從一個形狀轉換為另外一個形狀,以滿足計算需要
TensorFlow中,reshape()函數用來實現張量的形狀變換,其語法格式如表:
函數 | 說明 |
tf.reshape( ??????????? tensor, ??????????? shape, ??????????? name=None) | 將張量從一個形狀變換為另一個形狀 tensor:待改變形狀的tensor shape:必須是int32或int64,決定了輸出張量的形狀 name:可選,操作名稱 如果形狀的一個分量是特殊值-1,則計算該維度的大小,以使總大小不變 |
import tensorflow as tf #導入tensorflow類庫,別名為tf
#定義c1是一維張量,共有12個元素
c1 = tf.constant([1,2,3,4,5,6,7,8,9,10,11,12],dtype = tf.float32,name = "c1")
c2 = tf.reshape(c1,[2,3,2])
with tf.Session() as sess:sess.run(tf.global_variables_initializer())print(sess.run(c2))
下一節,簡單介紹變量的內容