1. 程式人生 > >TensorFlow:基礎概念

TensorFlow:基礎概念

首先祝自己生日快樂!! 趁著大學最後的一點時間學習一點新的東西,希望自己能堅持下去。

這裡記錄一點這幾天學習中記錄下的一些概念以及注意點。

基礎概念

  • 計算圖(graph)

這是TensorFlow中最為重要的概念,整個TensorFlow是一個通過計算圖的形式來進行表述計算的變成系統,每一次計算都是這個圖上的一個節點,節點之間的連線是計算之間的依賴關係,資料,或者說Tensor就是沿著這些邊 “流動” 的。

對於一個TensorFlow程式來說,一般可以劃分為兩個階段,第一個階段定義圖中所有的計算,第二個階段執行計算。

TensorFlow程式中,系統會自動維護一個預設的計算圖,當然也可以自己建立新的計算圖,不同的圖之間的張量和計算都不會共享。

  • 張量(tensor)

在TensorFlow系統中,所有的資料都會以張量(tensor)的形式表示,從功能上來說,可以簡單的將張量理解為多維陣列,但是實際的實現不是陣列的形式,而是計算結果的引用,也就是說,不是直接儲存數字,而是儲存一個張量的結構,有名字,維度和型別:

import tensorflow as tf

a = tf.constant([1], name='a')
b = tf.constant([2], name='b')

add_op = tf.add(a, b, name="add1")
print(add_op)

輸出:

Tensor("add1:0", shape=(1,), dtype=int32)Tensor("Add:0", shape=(1,), dtype=int32)

第一個add表示是從 add1 計算節點輸出的, 後邊的0表示該節點的第一個輸出, 第二個屬性是形狀, 像上例中的(1,)就表示輸出的是結果是一個一維陣列,第三個屬性是型別,每個張量都會有一個唯一的型別,TensorFlow會對所有參與計算的張量型別進行型別檢查。

  • 會話(session)

使用會話可以執行定義好的計算,也就是之前提到的執行計算部分,會話是用來管理資源的,在計算關閉之後會回收系統資源。一般兩種方式:

一:

sess = tf.Session()
....
sess.run()
....
sess.close()

二:這裡與Python是一致的,會自動關閉會話並釋放資源

with tf.Session() as sess:
    ....
    sess.run()
    ....

暫時想到的內容就這麼多,如果以後發現有什麼概念很重要的話再進行補充,接下來記錄一些我這幾天學習中覺得有點重要的內容吧!

不同節點的建立格式

這個問題看起來可能比較簡單,實際上因為TensorFlow與之前敲的Python程式碼還是有點不一樣的,所以很容易寫的時候突然一個小點就想不起來(我是這樣的。。),所以還是都放在一起記錄一下:

  • constant(常量節點)

呼叫格式如下:

constant ( 
    value ,  # 必填項 形式與Numpy陣列建立的初始值一致,比如 1, [1, 2], [[1, 2], [3, 4]]等等
    dtype = None ,  # 指定型別,這個型別一定要注意 ,對我這樣的新手真的超級坑的,下面詳細講
    shape = None ,  # 指定形狀, 當然 一般省略
    name = 'Const' ,  # 名稱 
    verify_shape = False # 預設值式False 如果改成 True 則檢查value 和dtype是否一致 否丟擲錯誤
)

這裡重點說一下TensorFlow的型別,一定要儘量指定清楚型別, 因為型別的檢查真的很嚴格,比如:

a = tf.constant(1, dtype= tf.float32)
# a = tf.constant(1)
b = tf.constant(1.5)

add_op1 = a + b

很簡單的兩個常量相加 ,如果寫成註釋的形式結果會報錯 型別不匹配,這裡不要想當然,一般我們寫別的程式碼,雖然兩種的型別分別是float 和int 仍然會進行自動的轉化,向精度更高的float轉化,Numpy中也是如此,但是TensorFlow中不是!!,我這幾天學習的過程中總是煩這個錯誤,所以記一下,希望看到的人注意這個地方,TensorFlow中進行運算時候一般都用tf.float32型別,所以就算是 2,3 這樣的整數,最好也是直接寫成 2.0, 3.0這樣的形式,避免出錯。

  • Variable(變數)

如果計算中的值進行改變,那麼就要使用到變數,變數的定義如下,注意變數在使用之前要先進性初始化:

Variable(
    initial_value=None,
    trainable=True,
    collections=None,
    validate_shape=True,
    caching_device=None,
    name=None,
    variable_def=None,
    dtype=None,
    expected_shape=None,
    import_scope=None,
    constraint=None

然鵝我目前只是用到其中一小部分引數來定義變數,(具體的可以看這位大佬的記錄:TensorFlow中的變數 )這裡我要說的是,注意變數的初始值,變數都是用來改變的嘛,舉個例子來說,線性迴歸 y = k x + b y = kx+b 定義線性模型的時候 這裡的 k k b b 就定義成變數 ,然後在過程中修改引數來完成擬合的過程, 所以設定初始值的時候,除了像定義常量一樣直接指定具體值,更多是傳入隨機數值,使用TensorFlow或者Numpy的隨機函式建立,或者直接使用 tf.zeros([2, 3]) 這樣指定全X陣列,關於隨機值之類的函式我的另一篇中記錄了。

舉個例子,計數器的實現:

state = tf.Variable(0, name='counter')
delta = tf.constant(1, name='delta')

add_op = tf.add(state, delta)
ass_op = tf.assign(state, add_op)

init_op = tf.global_variables_initializer()  # 注意初始化全域性的變數函式已經更新了 有些教程中還是在使用之前的

with tf.Session() as sess:
    sess.run(init_op)
    for _ in range(5):
        sess.run(ass_op)
        print(sess.run(state))
  • placeholder(佔位符)

聽這個名字已經表示了它存在的意義,就像是形參一樣,先定義好型別,使用的時候再具體傳入數值。

呼叫格式如下:

placeholder(
    dtype,
    shape=None,
    name=None
)

這裡的引數列表就簡單多了,少了必要的初始值(當然,這也是placeholder存在的意義),對於這個shape ,如果不確定維數(一般都不會確定),可以使用 None 代替,例如 shape = [None, 2] 這樣就表示某行2列的常量了,在session中執行的時候,要使用字典的形式傳入具體值,例如:

a = tf.placeholder(shape=(None, 2), dtype=tf.float32)  # 未指定行的維數
b = tf.placeholder(shape=(None, 2), dtype=tf.float32)

a_data = np.array([[1.0, 2.0]])     # 使用Numpy生成資料
b_data = np.array([[3.0, 4.0]])

add_op1 = tf.add(a, b)

with tf.Session() as sess:
    print(sess.run(add_op1, feed_dict={a: a_data, b: b_data}))  # 注意如何使用字典形式傳入資料

注意辨析Variable和placeholder之間的區別,在實際使用中比較清楚各自的作用,Variable一般用來要進行更新優化的值,比如模型的引數或者偏置之類的,而placeholder則是一般在 會話中傳入真實的訓練樣本。

以上~