白天跟著tensorflow的官方文件把最簡單的mnist模型跑通了,基本過程算是大致理清了,但程式看一遍下來,發現tensorflow中很多基本概念還不是很理解,比如tensor這個東西怎麼理解,基於圖又是怎麼回事,於是打道回府從基本概念開始看起。
慶幸的是目前有很多人在學這個,很多學習資料已經歸類整理好了,省去了自己重新找的時間,這裡整理了一下自己查閱的資料,彙總了一篇。
tensorflow是基於計算圖的框架:
tensorflow程式通常可以分為兩個階段: 圖的構建階段和圖的執行階段
現在假如我們要計算下面的表示式,可見,要計算c就需要a和b,計算d需要b,計算e需要c和d,這樣就形成了依賴關係。這種有向無環圖就叫做計算圖。
圖中的每個節點就是乙個操作(operation),operation
以0個或多個tensor
作為輸入,以0個或多個tensor
作為輸出。比如圖中節點c=a+b
,a和b是作為輸入的兩個tensor
,c是作為輸出的tensor
。tensor
就在圖中沿著箭頭方向流動,我想這就是為什麼這個框架叫做tensorflow的原因吧。tensor
的概念在第二節再細講。
在tensorflow的python庫中已經有乙個預設圖了,使用者可以在圖中新增節點,對於大多數程式,這個預設圖已經夠用了,當然,使用者也可以根據需要管理多張圖。
graph
僅僅定義了operation
和tensor
的流向,並不進行任何運算。之後session
通過graph
的定義預分配資源,計算operation
,得出結果。tensor
是各個操作之間的輸入或者輸出,除了用variable
維護的tensor
外所有的tensor
在流入下乙個節點後都不再儲存。
在tensorflow中,資料用tensor
表示,在計算圖中,所有operation之間傳遞的資料都是tensor
。其實乙個tensor
可以看成乙個多維陣列,裡面可以存放不同型別的資料。(本來還糾結tensor
到底是個什麼東西,和matlab對比後秒懂=.=)。將tensor
在控制台輸出,裡面有3個屬性:
>>>
import tensorflow as tf
>>> a = tf.ones([2, 3])
>>> print(a)
tensor("ones:0", shape=(2, 3), dtype=float32)
>>> b = tf.zeros([2, 3])
>>> print(b)
tensor("zeros:0", shape=(2, 3), dtype=float32)
>>> c = a + b;
>>> print(c)
tensor("add:0", shape=(2, 3), dtype=float32)
括號裡第乙個屬性是操作的型別(後面那個數字好像是裝置號還是什麼,這個問題先放在這,以後遇到再去查),第二個是tensor
的維度,第三個是tensor
的型別。
和單純的多維陣列不同,tensor
中還有有rank
這個概念,自己敲了幾行**試了下:
>>>
import tensorflow as tf
>>> a = tf.ones([4])
>>> b = tf.ones([3, 4])
>>> c = tf.ones([2, 3, 4])
>>> sess = tf.session()
creating tensorflow device (/gpu:0) -> (device: 0, name: geforce gtx 960m, pci bus id: 0000:01:00.0)
>>> print(sess.run(a)) # rank=1,a是乙個向量
[ 1.
1.1.
1.]>>> print(sess.run(b)) # rank=2, b是乙個二維陣列,由3個4維向量組成
[[ 1.
1.1.
1.] [ 1.
1.1.
1.] [ 1.
1.1.
1.]]
>>> print(sess.run(c)) # rank=3, c是乙個三維陣列,由2個3×4的二維陣列組成
[[[ 1.
1.1.
1.] [ 1.
1.1.
1.] [ 1.
1.1.
1.]]
[[ 1.
1.1.
1.] [ 1.
1.1.
1.] [ 1.
1.1.
1.]]]
可以看出,tensorflow中用一對中括號
表示乙個行向量,高維陣列就是由若干個行向量組成,中括號可以巢狀使用。所以,乙個tensor
前面或者末尾有幾個中括號,其rank值就等於幾。
構造階段完成後,才能啟**。啟**的第一步是建立乙個session
物件,如果無任何建立引數,會話構造器將啟動預設圖。
import tensorflow as tf
a = tf.ones([1, 3])
b = tf.ones([1, 3])
myplus = a + b
# 啟動預設圖
sess = tf.session()
# 呼叫session()的run()方法執行操作
# 整個執行過程是自動化的,會話負責傳遞操作所需的所有輸入。操作通常是併發執行的。
# 返回值 'result' 是乙個 numpy `ndarray` 物件.
result = sess.run(myplus)
print(result)
# 關閉會話,釋放資源
sess.close()
在實現上, tensorflow 將圖形定義轉換成分布式執行的操作, 以充分利用可用的計算資源(如 cpu 或 gpu). 一般你不需要顯式指定使用 cpu 還是 gpu, tensorflow 能自動檢測. 如果檢測到 gpu, tensorflow 會盡可能地利用找到的第乙個 gpu 來執行操作.
如果機器上有超過乙個可用的 gpu, 除第乙個外的其它 gpu 預設是不參與計算的. 為了讓 tensorflow 使用這些 gpu, 你必須將 op 明確指派給它們執行.with...device
語句用來指派特定的 cpu 或 gpu 執行操作.
with tf.device("/gpu:1"):
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.],[2.]])
product = tf.matmul(matrix1, matrix2)
...
變數維護圖執行過程中的狀態資訊。tensor一旦擁有variable的指向就不會隨session的多次載入而丟失。在session中variable是單獨儲存的,在使用時必須進行初始化。
init = tf.global_variables_initializer()
sess.run(init)
當我們定義一張graph時,有時候並不知道需要計算的值,比如模型的輸入資料,其只有在訓練與**時才會有值。這時就需要placeholder與feed_dict的幫助。
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.mul(input1, input2)
with tf.session() as sess:
print sess.run([output], feed_dict=)
# 輸出:
# [array([ 14.], dtype=float32)]
在上面程式中,input1
和input2
開始的值是未知的,在sess.run()中才傳給它們實際的值,feed_dict=
中input1和input2是索引名,預設等於tensor的名字,也可以在定義佔位符時自己定義索引名。
input1 = tf.placeholder(tf.float32, name = 'var1')
注意,在計算圖中,可以用feed_dict
來替換任何tensor
,並不侷限於佔位符。
tensorflow官方文件 | 基本用法tensorflow自學之前的bigpicture
tensorflow系列03 | tensorflow基本概念tensor理解
關於tensorflow計算圖與tensor的理解
Tensorflow的一些基本用法
在使用tensorflow中會遇到一些其基本的用法,再次作為記錄備忘 在計算整體的loss是會將不同部分的loss放入乙個集合中,最後計算整體的loss,因此會用到tf.add to collection,具體參考tensorflow中的cifar10的例子,用法如下所示 tf.add to col...
TensorFlow的一些學習筆記
1 靈活性tensorflow不是乙個嚴格的神經網路工具包,只要你可以使用資料流圖來描述你的計算過程,你可以使用tensorflow做任何事情。你還可以方便地根據需要來構建資料流圖,用簡單的python語言來實現高層次的功能。2 可移植性tensorflow可以在任意具備cpu或者gpu的裝置上執行...
tensorflow遇到的一些錯誤
1 tensorflow dtype t.dtype.base dtype attributeerror float object has no attribute dtype 參考 我報錯的行是 disc gradients disc optimizer.compute gradients dis...