1. Getting Start
1.1 import
TensorFlow應用程序需要引入編程架包,才能訪問TensorFlow的類、方法和符號。如下所示的方法:
import tensorflow as tf |
2. Tensor
TensorFlow用Tensor這種數據結構來表示所有的數據。可以把一個Tensor想象成一個n維的數組或列表。Tensor有一個靜態的類型和動態的維數。Tensor可以在圖中的節點之間流通。
2.1 秩(Rank)
Tensor對象由原始數據組成的多維的數組,Tensor的rank(秩)其實是表示數組的維數,如下所示的tensor例子:
Rank |
數學實例 |
Python 例子 |
0 |
常量 (只有大小) |
s = 483 |
1 |
向量(大小和方向) |
v = [1.1, 2.2, 3.3] |
2 |
矩陣(數據表) |
m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] |
3 |
3階張量 (數據立體) |
t = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]] |
n |
n階 (自己想想看) |
… |
2.2 形狀(Shape)
TensorFlow為了描述Tensor每一維的長度,相當於描述每一維數組的長度,所以定義了Shape概念。其可以描述Tensor的維數,又可以描述每一維的長度。
Rank |
Shape |
Dimension number |
Example |
0 |
[] |
0-D |
一個常量. |
1 |
[D0] |
1-D |
[5]:表示一個向量有5個元素 |
2 |
[D0, D1] |
2-D |
[3, 4]:表示一個矩陣,共有3*4個元素 |
3 |
[D0, D1, D2] |
3-D |
[2, 4, 3]:總共有2*4*3個元素 |
n |
[D0, D1, D2,… DN-1] |
n-D |
…. |
2.3 類型(Data type)
除了維度,Tensor有一個數據類型屬性,你可以為一個張量指定下列數據類型中的任意一個類型,但是一個Tensor所有元素的類型必須相同。
數據類型 |
Python 類型 |
描述 |
DT_FLOAT |
tf.float32 |
32 位浮點數. |
DT_DOUBLE |
tf.float64 |
64 位浮點數. |
DT_INT64 |
tf.int64 |
64 位有符號整型. |
DT_INT32 |
tf.int32 |
32 位有符號整型. |
DT_INT16 |
tf.int16 |
16 位有符號整型. |
DT_INT8 |
tf.int8 |
8 位有符號整型. |
DT_UINT8 |
tf.uint8 |
8 位無符號整型. |
DT_STRING |
tf.string |
可變長度的字節數組.每一個張量元素都是一個字節數組. |
DT_BOOL |
tf.bool |
布爾型. |
DT_COMPLEX64 |
tf.complex64 |
由兩個32位浮點數組成的復數:實數和虛數. |
DT_QINT32 |
tf.qint32 |
用於量化Ops的32位有符號整型. |
DT_QINT8 |
tf.qint8 |
用於量化Ops的8位有符號整型. |
DT_QUINT8 |
tf.quint8 |
用於量化Ops的8位無符號整型. |
3. Computational graph
3.1 定義
Computational graph 是由一系列邊(Tensor)和節點(operation)組成的數據流圖。每個節點都是一種操作,其有0個或多個Tensor作為輸入邊,且每個節點都會產生0個或多個Tensor作為輸出邊。即節點是將多條輸入邊作為操作的數據,然后通過操作產生新的數據。可以將這種操作理解為模型,或一個函數,如加減乘除等操作。
簡單地說,可以將Computational graph理解為UML的活動圖,活動圖和Computational graph都是一種動態圖形。TensorFlow的節點(操作)類似活動圖的節點(動作),TensorFlow每個節點都有輸入(Tensor),可以將用戶創建的起始Tensor看做是活動圖的起始節點,而TensorFlow最終產生的Tensor看做是活動圖的終止節點,如圖 31所示。
圖 31
圖 31所示,常量3和常量4.5兩個起始Tensor通過add操作后產生了一個新Tensor(值7.5);接着新Tensor(值7.5)和常量3經multi操作后產生一個新Tensor(值22.5),因為22.5是TensorFlow最后產生的Tensor,所以其是終止節點。
3.2 Session
TensorFlow通過一個對象(Session)來管理Computational graph 節點動態變換。由於Tensor是一種數據結構,為了獲取Tensor存儲的數據,需要手動調用Session對象的run方法獲得。
實現一個TensorFlow應用程序,用戶需要進行兩個步驟:
Computational Graph建立其實是建立節點和邊的一些依賴關系,這個過程是建立一種靜態結構。
Computational Graph執行其實就是調用session.run()方法。由於Computational Graph是有邊和節點組成,所以可以向run方法傳遞的兩種參數:
-
邊( Tensor ):若傳遞的是 Tensor 對象,則是獲取 Tensor 對象的數據;
-
節點:若傳遞的是節點,則會先獲取節點返回的 Tensor 對象,然后再獲取 Tensor 對象的數據。
綜上所述執行Computational Graph其實是獲取Tensor的數據。在執行Tensor對象數據時,會根據節點的依賴關系進行計算,直至初始節點。
如下建立兩個TensorFlow節點,節點的類型是constant,然后通過add操作后產生一個新節點,如下所示:
##1.建立computational graph node1 = tf.constant(3., tf.float32) node2 = tf.constant(4.5) tensor = tf.add(node1, node2)
print(node1) print(node2)
##2.執行computational graph session = tf.Session() print(session.run(node1)) print(session.run(node2)) print(session.run(tensor)) |
輸出: Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(), dtype=float32) 3.0 4.5 7.5 |
圖 32
注意:
-
在執行 computational graph 之前, TensorFlow 節點是一種靜態結構,所以輸出的並不是 3.0 和 4.0 ,而是 tensor 對象;
-
在執行 computational graph 之后,才輸出了節點的值,即為了讓某個節點從初始節點開始變換,需要通過 Session 對象的 run 方法手動變換。
3.3 InteractiveSession
文檔中的 Python 示例使用一個會話 Session 來 啟動圖, 並調用 Session.run() 方法執行操作.為了便於使用諸如 IPython 之類的 Python 交互環境, 可以使用 InteractiveSession 代替 Session 類, 使用 Tensor.eval() 和 Operation.run() 方法代替 Session.run(). 這樣可以避免使用一個變量來持有會話.
# 進入一個交互式 TensorFlow 會話. import tensorflow as tf sess = tf.InteractiveSession()
x = tf.Variable([1.0, 2.0]) a = tf.constant([3.0, 3.0])
# 使用初始化器 initializer op 的 run() 方法初始化 'x' x.initializer.run()
# 增加一個減法 sub op, 從 'x' 減去 'a'. 運行減法 op, 輸出結果 sub = tf.sub(x, a) print sub.eval() # ==> [-2. -1.] |
4. 起始節點
目前了解的,TensorFlow有三種類型的起始節點:constant(常量)、placeholder(占位符)、Variable(變量)。
4.1 常量 (constant)
TensorFlow的常量節點是通過constant方法創建,其是Computational Graph中的起始節點,在圖中以一個圓點表示,如圖 32所示。
如下述程序中所示,直接創建,但創建的節點不會開始執行,需要由Session對象的run方法開始啟動。
tensor1 = tf.constant(3., tf.float32) print(tensor1)
tensor2 = tf.constant([1, 2, 3, 4, 5, 6, 7]) print(tensor2)
tensor3 = tf.constant(-1.0, shape=[2, 3]) print(tensor3)
session = tf.Session() print(session.run(tensor1)) print(session.run(tensor2)) print(session.run(tensor3)) |
輸出: Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(7,), dtype=int32) Tensor("Const_2:0", shape=(2, 3), dtype=float32) 3.0 [1 2 3 4 5 6 7] [[-1. -1. -1.] [-1. -1. -1.]] |
4.2 占位符 (placeholder)
TensorFlow的placeholder節點是由placeholder方法創建,其也是一種常量,但是由用戶在調用run方法是傳遞的,也可以將placeholder理解為一種形參。即其不像constant那樣直接可以使用,需要用戶傳遞常數值。
如下所示在執行node3:
import tensorflow as tf
node1 = tf.placeholder(tf.float32) node2 = tf.placeholder(tf.float32) tensor = tf.add(node1, node2)
print(node1) print(node2)
session = tf.Session() print(session.run(tensor, {node1:3,node2:4} )) |
輸出: Tensor("Placeholder:0", dtype=float32) Tensor("Placeholder_1:0", dtype=float32) 7.0 |
注意:
由於在執行node3節點時,需要node1和node2作為輸入節點,所以此時需要傳遞"實參",即3和4.
圖 41
4.3 變量 (Variable)
TensorFlow的Variable節點是通過Variable方法創建,並且需要傳遞初始值。常量在執行過程中無法修改值,變量可以在執行過程修改其值。但是TensorFlow的變量在創建之后需要再進行手動初始化操作,而TensorFlow常量在創建時就已進行了初始化,無需再進行手動初始化。
如下示例,創建兩個變量,分別初始化為0.3和-0.3,然后傳入一個向量值,最后計算出一個新的向量:
from __future__ import print_function import tensorflow as tf
w = tf.Variable([.3], tf.float32) b = tf.Variable([-.3], tf.float32) x = tf.placeholder(tf.float32)
linear = w * x + b
session = tf.Session() init = tf.global_variables_initializer() session.run(init)
print(session.run(linear, {x: [1, 2, 3, 4]})) |
輸出: [ 0. 0.30000001 0.60000002 0.90000004] |

圖 42
從W展開細節看,變量其實只是一個命名空間,其內部由一系列的節點和邊組成。同時有一個常量節點,即初始值節點。
5. 模型評估
模型評估是指比較期望值和模型產生值之間的差異,若差異越大,則性能越差;差異越小,性能越好。模型評估有很多種方法,如均分誤差或交差熵。
如下以常用的"均分誤差"法舉例說明,其等式為:
Y為期望向量,X為輸入向量,f(X)為計算向量,如下所示:
from __future__ import print_function import tensorflow as tf #1. 構建計算流圖 w = tf.Variable([.3], tf.float32) b = tf.Variable([-.3], tf.float32) x = tf.placeholder(tf.float32) y = tf.placeholder(tf.float32) #期望向量 linear_model = w * x + b
squared_deltas = tf.square(linear_model - y) #對兩個向量的每個元素取差並平方,最后得出一個新的向量 loss = tf.reduce_sum(squared_deltas) #對向量取總和
#2. 執行計算流圖 session = tf.Session() init = tf.global_variables_initializer() session.run(init)
print(session.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]})) |
輸出: 23.66 |
注意:
loss的值是依賴W、B和Y三個向量的值,所以計算loss Tensor會根據依賴關系獲取W、B和Y三個Tensor的值,其計算流程圖如圖 51所示:
圖 51
6. 優化
優化是指減少期望值與模型產生值之間的差異,即減少均分誤差或交差熵的計算結果,如減少上述的loss變量值。
6.1 手動優化
我們可以通過修改上述的w和b的變量值,來手動優化上述的模型。由於TensorFlow的變量是通過tf.Variable方法創建,而重新賦值是通過tf.assign方法來實現。注意修改變量的動作需要執行Session.run方法來開始執行。
比如可以修改w=-1,b=1參數來優化模型,如下
from __future__ import print_function import tensorflow as tf
w = tf.Variable([.3], tf.float32) b = tf.Variable([-.3], tf.float32) x = tf.placeholder(tf.float32) y = tf.placeholder(tf.float32 ") linear_model = w * x + b
squared_deltas = tf.square(linear_model - y) loss = tf.reduce_sum(squared_deltas)
session = tf.Session() init = tf.global_variables_initializer() session.run(init)
#1.變量w和b初始值為3和-3時,計算loss值 print(session.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
#2.重置變量w和b值為-1和1時,再計算loss值 fixw = tf.assign(w,[-1.]) fixb = tf.assign(b,[1.]) session.run(fixw) session.run(fixb) print(session.run(loss, {x:[1,2,3,4],y:[0,-1,-2,-3]})) |
輸出: 23.66 0.0 |
注意:
loss的值是依賴W、B和Y三個向量的值來計算,即每次計算loss都需要上述三個變量的值進行計算。由於通過調用Session.run()方法來執行某個節點(Computational graph的節點為操作)時,會自動根據節點前后依賴關系,自動從初始節點開始計算到該節點。在第一次執行session.run(loss)時,W和B的值是3和-3;第二次執行session.run(loss)時,W和B的值被修改為-1和1后。所以session.run(loss)時會自動根據W和B的不同進行計算。
圖 61
6.2 自動優化
上述通過手動調整變量w和b的值來改善模型的執行性能,雖然也行的通,但是非常單調且工作量太大。所以TensorFlow提供一些優化器(optimizers)來提高用戶的工作效率,可以自動完成優化,即可以自動更新相關變量的值。
如下所示,以最簡單的優化器gradient descent為例,其可以根據執行loss值逐漸修改每個變量值,:
import numpy as np import tensorflow as tf w = tf.Variable([.3], tf.float32) b = tf.Variable([-.3], tf.float32) x = tf.placeholder(tf.float32) linear_model = w * x + b y = tf.placeholder(tf.float32)
squared_deltas = tf.square(linear_model - y) loss = tf.reduce_sum(squared_deltas)
#1. optimizer optimizer = tf.train.GradientDescentOptimizer(0.01) train = optimizer.minimize(loss)
#2. training loop init = tf.global_variables_initializer() session = tf.Session() session.run(init)
for i in range(1000): session.run(train, {x:[1,2,3,4], y:[0, -1, -2, -3]})
#3. evaluate training accuracy curr_w, curr_b, curr_loss = session.run([w,b,loss], {x:[1, 2, 3, 4], y:[0, -1, -2, -3]}) print("w:%s b:%s loss:%s"%(curr_w,curr_b,curr_loss)) |
輸出: w:[-0.9999969] b:[ 0.99999082] loss:5.69997e-11 |
注意:
則dV是參數調整數幅度,如若v是權值w,則
如圖 62所示是產生的Computational graph圖變換:
圖 62
圖中帶有箭頭的邊緣是指依賴,如節點b有一個指向tain_min節點,表明b的值依賴tain_min節點。