前言
TensorFlow是Google團(tuán)隊(duì)開發(fā)的一款開源的用于各種感知和語言理解任務(wù)的機(jī)器學(xué)習(xí)框架嫁盲。它的底層核心引擎由C++實(shí)現(xiàn)创泄,但提供了Python知染、C++肋僧、Java、Go等常用計(jì)算機(jī)語言的接口控淡,可謂是覆蓋面很廣嫌吠。開發(fā)平臺支持Windows、Linux和macOS逸寓。
相較于Caffe居兆,TensorFlow上手較難,運(yùn)行速度慢竹伸,且內(nèi)存耗費(fèi)高,但是TensorFlow使用了張量(tensor)運(yùn)算的符號圖方法簇宽,使得新網(wǎng)絡(luò)的指定變得相當(dāng)容易勋篓,可支持快速開發(fā),即靈活性很高魏割。加上是Google的親兒子譬嚣,很快得到了很多人的認(rèn)同。
什么是張量運(yùn)算的符號圖方法钞它?符號圖也稱作數(shù)據(jù)流圖拜银,使用tensorflow時(shí),使用的數(shù)據(jù)(以張量存在)都得放在數(shù)據(jù)流圖中進(jìn)行計(jì)算遭垛。下圖為一個(gè)數(shù)據(jù)流圖截?cái)啵?br>
節(jié)點(diǎn)在圖中表示對數(shù)據(jù)進(jìn)行相關(guān)操作尼桶,線則表示在節(jié)點(diǎn)間相互聯(lián)系的多維數(shù)據(jù)數(shù)組, 即張量(tensor)锯仪。訓(xùn)練模型時(shí)泵督,tensor會不斷的從數(shù)據(jù)流圖中的一個(gè)節(jié)點(diǎn)流到另一節(jié)點(diǎn), 這也是TensorFlow名字的由來。
最后提下張量庶喜,張量是矢量概念的推廣小腊,一維的張量稱作矢量或向量救鲤,如[1, 2, 3];二維的張量稱作矩陣秩冈,如[[2, 3], [2, 4]]本缠;以此類推,后面還有三維入问,四維等搓茬。
數(shù)據(jù)流圖中的基礎(chǔ)知識
1.session:
session是一個(gè)會話控制處理模塊,是Tensorflow為了控制和輸出對應(yīng)執(zhí)行語句队他。舉個(gè)栗子卷仑,考試的時(shí)候,老師在將卷子發(fā)完給所有同學(xué)之前是不可以動筆答題的(將所有變量進(jìn)行定義占位)麸折,發(fā)完卷子后锡凝,同學(xué)們得到了通知,進(jìn)行針對不同的題目進(jìn)行相應(yīng)的答題步驟(將之前所有定義的變量進(jìn)行賦值和計(jì)算垢啼,并針對這些變量進(jìn)行一系列處理)窜锯。
回到Tensorflow上,上面的例子中芭析,后序的答題過程锚扎,就是在session完成的,而啟動的開關(guān)就是session.run()
馁启。
import tesorflow as tf
#進(jìn)行定義占位驾孔,不作運(yùn)算和賦值
x1 = tf.constant(3) #定義一個(gè)常量張量
x2 = tf.constant(2)
res = tf.multiply(x1, x2) #乘法
#創(chuàng)建一個(gè)會話,并把之前所有變量進(jìn)行賦值和計(jì)算
with tf.Session() as sess:
ans = sess.run(res)
print(ans) #6
2.Variable:
Variable是tensorflow中變量定義的關(guān)鍵字惯疙,即定義變量需要使用tf.Variable()
翠勉。這里需要注意一點(diǎn),只要是定義了變量霉颠,就需要進(jìn)行初始化对碌,初始化的過程就是將你定義的變量變?yōu)閿?shù)據(jù)流圖中使用的張量格式。
import tesorflow as tf
x1 = tf.Variable(3) #定義一個(gè)變量
x2 = tf.Variable(2)
res = tf.multiply(x1, x2)
#將所有定義的變量初始化為張量
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init) #進(jìn)行激活蒿偎,執(zhí)行
print(sess.run(res)) #6
3.scope:
scope表示域朽们,即變量的作用域。平時(shí)在寫代碼過程中诉位,因?yàn)楹苌贂霈F(xiàn)很多變量的情況骑脱,所以很難體現(xiàn)出scope的作用。而在深度學(xué)習(xí)網(wǎng)絡(luò)中不从,如果不做處理惜姐,動則上百個(gè)變量是常見的,所以為了便于管理代碼,推薦使用scope歹袁。下面兩張圖生動形象的詮釋了scope的作用:
TensorFlow中有兩種scope坷衍,一種是name_scope,另一種是variable_scope条舔。name_scope主要用于管理一個(gè)數(shù)據(jù)流圖里面的各種layer(也稱op)枫耳,實(shí)現(xiàn)一種層次化且有條理的管理,避免各個(gè)layer之間命名沖突孟抗。而variable_scope一般也可以實(shí)現(xiàn)name_scope的作用迁杨,但它還有一個(gè)更重要的作用,用于管理一個(gè)數(shù)據(jù)流圖中變量的名字凄硼,避免變量之間的命名沖突铅协。
提到變量命名,先介紹下定義變量的方法也有兩種摊沉,一種是上面提到的Variable狐史,當(dāng)在使用Variable定義變量時(shí), 系統(tǒng)會自動檢測命名是否沖突并自動處理说墨;還有一種get_variable骏全,使用它定義變量,當(dāng)遇到要創(chuàng)建重名變量而該變量名沒有設(shè)置為共享變量時(shí)尼斧,會報(bào)錯(cuò)姜贡。
with tf.name_scope("scope1"):
x1 = tf.Variable(name='var1', initial_value=[1], dtype=tf.float32)
x2 = tf.Variable(name='var1', initial_value=[2], dtype=tf.float32)
init = tf.constant_initializer(value=1) #給x3賦值
#默認(rèn)為不共享
x3 = tf.get_variable(name='var2', shape=[1], dtype=tf.float32, initializer = init)
#x4 = tf.get_variable(name='var2', shape=[1], dtype=tf.float32, initializer = init)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer()) #初始化
print(x1.name) # scope1/var1:0
print(sess.run(x1)) # [1.]
print(x2.name) # scope1/var1_1:0
print(sess.run(x2)) # [2.]
print(x3.name) # var2:0
print(sess.run(x3)) # [1]
#print(sess.run(x4)) #error
使用變量共享:
with tf.variable_scope("scope") as scope:
x1 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32)
scope.reuse_variables() # 設(shè)置為使用共享變量
x2 = tf.get_variable(name='var1')
#或者使用 with tf.variable_scope("scope", reuse=reuse):
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(x1.name) #scope/var1:0
print(sess.run(x1)) #[0.34196675],默認(rèn)隨機(jī)初始化值
print(x2.name) #scope/var1:0
print(sess.run(x2)) #[0.34196675]
variable_scope的其它常見使用方式:
def fun(x1, x2, scope):
with tf.variable_scope(scope) :
return tf.multiply(x1, x2)
with tf.variable_scope("fun"):
x1 = tf.constant(1) #定義一個(gè)常量張量
x2 = tf.Variable(2) #定義一個(gè)變量棺棵,后面需要初始化
#在fun1域作運(yùn)算
res = fun(x1 = x1, x2 = x2, scope = "fun1")
#在fun2域作運(yùn)算
res = fun(x1 = res, x2 = x2, scope = "fun2")
#在fun3域作運(yùn)算
res = fun(x1 = res, x2 = res, scope = "fun3")
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(res)) #16
上圖為一個(gè)簡單的scope運(yùn)用楼咳。值得一提的是,可以把最外層的fun看成一個(gè)layer律秃,里面的fun1爬橡,fun2,fun3可以替換成相應(yīng)的卷積棒动,激活操作,最后多個(gè)layer進(jìn)行組合宾添,就是一個(gè)深度學(xué)習(xí)大概的網(wǎng)絡(luò)模型結(jié)構(gòu)啦船惨。
4.placeholder
在Tensorflow中,每生成一個(gè)常量缕陕,就需要在數(shù)據(jù)流圖中增加一個(gè)節(jié)點(diǎn)(如上圖)粱锐,數(shù)據(jù)量較大時(shí),會導(dǎo)致圖特別大扛邑。為了解決這個(gè)問題怜浅,需使用placeholder來輸入數(shù)據(jù),它相當(dāng)于定義了一個(gè)位置《褡總結(jié)下就是搀暑,placeholder是一個(gè)占位符,用來暫時(shí)儲存變量跨琳。將上面的代碼修改為使用placeholder:
def fun(x1, x2, scope):
with tf.variable_scope(scope) :
return tf.multiply(x1, x2)
with tf.variable_scope("fun"):
#placeholder需要定義type自点,一般為float32
x1 = tf.placeholder(tf.float32)
x2 = tf.placeholder(tf.float32)
#在fun1域作運(yùn)算
res = fun(x1 = x1, x2 = x2, scope = "fun1")
#在fun2域作運(yùn)算
res = fun(x1 = res, x2 = x2, scope = "fun2")
#在fun3域作運(yùn)算
res = fun(x1 = res, x2 = res, scope = "fun3")
with tf.Session() as sess:
#傳值
print(sess.run(res, feed_dict = {x1:2, x2:3})) #324
【關(guān)注公眾號DoCode,每日一道LeetCode脉让,還有更多其他博文桂敛,將零碎時(shí)間利用起來】