TensorFlow筆記(1)——TensorFlow中的相關基本概念

僱個城管打天下發表於2018-11-30

前言

Tensorflow 是一個程式設計系統,使用圖(graph)來表示計算任務,圖(graph)中的節點稱之為 op (operation),一個 op 獲得 0 個或多個 Tensor,執行計算,產生 0 個或多個 Tensor。Tensor 看作是一個 n 維的陣列或列表。圖必須在會話(Session)裡被啟動。

基本概念

  • 使用圖(Graph)來表示計算任務
  • 在被稱為會話(Session)的上下文(context)中執行圖
  • 使用tensor表示資料
  • 通過變數(Variable)維護狀態
  • 使用feed和fetch可以為任意的操作賦值或者從中獲取資料

下圖顯示了Session、Graph、Tensor、Variable之間的關係

關係圖

圖(Graph)

在TensorFlow的官方文件中,Graph 被定義為“一些 Operation 和 Tensor 的集合”。例如我們表達如下的一個計算的 python程式碼,

a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
c = tf.placeholder(tf.float32)
d = a*b+c
e = d*2
複製程式碼

就會生成相應的一張圖,在Tensorboard中看到的圖大概如下這樣。其中每一個圓圈表示一個Operation(輸入處為Placeholder),橢圓到橢圓的邊為Tensor,箭頭的指向表示了這張圖Operation 輸入輸出 Tensor 的傳遞關係。

圖(Graph)

會話(Session)

會話(Session)是TensorFlow中的一個非常重要的概念。上面提到了,在TensorFlow中的所有計算都構建在一張計算圖(Graph)中,這是一種對數學運算過程的視覺化方法。而會話(Session)就是負責讓這個圖運算起來,會話(Session)持有並管理TensorFlow程式執行時的所有資源,例如CPU或者GPU的分配。

使用會話(Session)的兩種方式

方式一:明確的呼叫會話的生成函式和關閉會話函式

# 建立一個會話
sess = tf.Session()

# 使用該會話執行一個結果
sess.run(...)

# 關閉會話,釋放記憶體
sess.close()
複製程式碼

呼叫這種方式時,要明確呼叫Session.close(),以釋放資源。當程式異常退出時,關閉函式就不能被執行,從而導致資源洩露。

方式二:上下文管理機制自動釋放所有資源 利用with結構將需要執行的程式碼包裹住,建立會話,並通過上下文機制管理器管理該會話

with tf.Session() as sess:
    sess.run(...)
# 不需要再呼叫"Session.close()"
# 在退出with statement時,會話關閉和資源釋放已自動完成
複製程式碼

Tips:一般情況下推薦使用方式二使用會話

張量(Tensor)

TensorFlow用張量這種資料結構來表示所有的資料.你可以把一個張量想象成一個n維的陣列或列表.一個張量有一個靜態型別和動態型別的維數.張量可以在圖中的節點之間流通

在TensorFlow系統中,張量的維數來被描述為階.但是張量的階和矩陣的階並不是同一個概念.張量的階(有時是關於如順序或度數或者是n維)是張量維數的一個數量描述.比如,下面的張量(使用Python中list定義的)就是2階.

t = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
複製程式碼

你可以認為一個二階張量就是我們平常所說的矩陣,一階張量可以認為是一個向量.對於一個二階張量你可以用語句t[i, j]來訪問其中的任何元素.而對於三階張量你可以用't[i, j, k]'來訪問其中的任何元素.

數學例項 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階 (自己想想看) ....

張量是所有深度學習框架中最核心的元件,因為後續的所有運算和優化演算法都是基於張量進行的。幾何代數中定義的張量是基於向量和矩陣的推廣,通俗一點理解的話,我們可以將標量視為零階張量,向量視為一階張量,那麼矩陣就是二階張量。

變數(Variable)

本質也是一個tensor張量,但variable主要用於資料儲存(可以理解為Java中的全域性變數) Variable 用於構建一個變數,在計算圖的運算過程中,其值會一直儲存到程式執行結束,而一般的tensor張量在tensorflow執行過程中只是在計算圖中流過,並不會儲存下來。 因此Varibale主要用來儲存tensorflow構建的一些結構中的引數,這些引數才不會隨著運算的消失而消失,才能最終得到一個模型。

Tips: 所有和varible有關的操作在計算的時候都要使用session會話來控制,包括計算,列印等等。

# 2.2變數
import tensorflow as tf

# 定義一個變數 X
X=tf.Variable([1,2])
# 定義一個常量 a
a=tf.constant([3,3])

# 增加一個減法op
sub=tf.subtract(X,a)
# 增加一個加法op
add=tf.add(X,sub)

# 初始化所有變數
init=tf.global_variables_initializer()

# 定義一段會話
with tf.Session() as sess:
    # 在會話中執行
    sess.run(init)
    print(sess.run(sub))
    print(sess.run(add))

# 建立一個變數,初始化為0
state=tf.Variable(0,name='counter')
# 建立一個op,作用是使state加1
new_value=tf.add(state,1)
# 賦值op
update=tf.assign(state,new_value)
# 變數初始化
init=tf.global_variables_initializer()
# 建立一個會話
with tf.Session() as sess:
    # 利用會話執行初始化操作
    sess.run(init)
    print(sess.run(state))
    for _ in range(5):
        sess.run(update)
        print(sess.run(state))
複製程式碼

feed和fetch

1.fetch

會話執行完成之後,如果我們想檢視會話執行的結果,可以使用fetch來實現

import tensorflow as tf

# Fetch
# 建立三個常量
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)

# 執行加法和乘法操作
add=tf.add(input2,input3)
mul=tf.multiply(input1,add)

# 建立會話執行
with tf.Session() as sess:
    result=sess.run([mul,add])
    print(result)
複製程式碼

執行結果為:

[21.0, 7.0]
複製程式碼

2.feed與佔位符(placeholder)

當我們構建一個模型的時候,有時候我們需要在執行時候輸入一些初始資料,這個時候定義模型資料輸入在tensorflow中就是用placeholder(佔位符)來完成。它的定義如下:

def placeholder(dtype, shape=None, name=None):
複製程式碼

其中dtype表示資料型別,shape表示維度,name表示名稱。它支援單個數值與任意維度的陣列輸入。 1. 單個數值佔位符定義

a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
c = tf.add(a, b)
複製程式碼

當我們需要執行得到c的執行結果時候我們就需要在會話執行時候,通過feed來插入a與b對應的值,程式碼演示如下:

with tf.Session() as sess:
    result = sess.run(c, feed_dict={a:3, b:4})
    print(result)
複製程式碼

其中 feed_dict就是完成了feed資料功能,feed中文有餵飯的意思,這裡還是很形象的,對定義的模型來說,資料就是最好的食物,所以就通過feed_dict來實現。

2. 多維資料 同樣對於模型需要多維資料的情況下通過feed一樣可以完成,定義二維資料的佔位符,然後相加,程式碼如下:

_x = tf.placeholder(shape=[None, 2], dtype=tf.float32, name="x")
_y = tf.placeholder(shape=[None, 2], dtype=tf.float32, name="y")
z = tf.add(_x, _y);
複製程式碼

執行時候需要feed二維陣列,實現如下:

with tf.Session() as sess:
    result = sess.run(z, feed_dict={_x:[[3, 4], [1, 2]], _y:[[8, 8],[9, 9]]})
    print(result)
複製程式碼

下面給出示例程式碼:

import tensorflow as tf

# Feed
# 常見佔位符
input4=tf.placeholder(tf.float32)
input5=tf.placeholder(tf.float32)
output=tf.multiply(input4,input5)

with tf.Session() as sess:
    # feed的資料以字典的形式傳入
    print(sess.run(output,feed_dict={input4:2.0,input5:45.2}))
複製程式碼

執行結果為:

90.4
複製程式碼

3. feed和fetch

總結下,feed和fetch的作用就和他的意思是一樣的,fetch用於從session中獲取結果資料,feed是用於將資料餵給operation,然後用session執行。

相關文章