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中的變數 )這裡我要說的是,注意變數的初始值,變數都是用來改變的嘛,舉個例子來說,線性迴歸
定義線性模型的時候 這裡的
和
就定義成變數 ,然後在過程中修改引數來完成擬合的過程, 所以設定初始值的時候,除了像定義常量一樣直接指定具體值,更多是傳入隨機數值,使用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則是一般在 會話中傳入真實的訓練樣本。
以上~