對于 tf.get_variable() vs tf.Variable(),tf.name_scope() vs tf.variable_scope()
最近剛接手tf扎阶,有些函數(shù)乘陪,理解不清楚雕擂,做一下筆記井赌。
對于函數(shù),知道平時的用法就行了流部,不用糾結(jié)里面的每一個參數(shù)的意思纹坐,基本用不到耘子,還浪費時間
一谷誓、name-scope 和 variable-scope
name-scope 和 variable-scope 都是命名空間,意思就是户辱,定義一個空間糙臼,在這個空間里面的弓摘,定義的變量,基本都會以這個命名空間作為其變量名的前綴末患。(但是也有例外)
比如下圖中璧针,盡管是兩段代碼渊啰,但都是在variable-scope定義的名稱為“V1”的空間中。而reuse命令隧膏,允許共享當前scope(同一個命名空間)下的所有變量胞枕,所以a1和a3的變量名都是 V1/a1:0
import tensorflow as tf
import numpy as np
with tf.variable_scope('V1'):
a1 = tf.get_variable(name='a1', shape=[1], initializer=tf.constant_initializer(1))
with tf.variable_scope('V1', reuse=True):
a3 = tf.get_variable('a1')
- name_scope對 get_variable()創(chuàng)建的變量 的名字不會有任何影響,而創(chuàng)建的op會被加上前綴.
- tf.get_variable_scope() 返回的只是 variable_scope,不管 name_scope.所以以后我們在使用tf.get_variable_scope().reuse_variables() 時可以無視name_scope
- name_scope 是給op_name加前綴, variable_scope是給get_variable()創(chuàng)建的變量的名字加前綴腐泻。
二 派桩、tf 的 reduce(降維)操作
1. 基礎(chǔ)理解
1.1 向量的“維”
這里加入基礎(chǔ)理解的意思,是為了防止概念不清晰范嘱。
比如若說X是一個n維向量彤侍,表示X中逆趋,含有n個元素闻书,可以在n維坐標系中表示出來(原點到X坐標的向量)。另外砰盐,在機器學習的降維中岩梳,是把X從n維降到k維晃择。 ---但這不是tf中的‘‘降維”
n維向量宫屠!= n維數(shù)組!5终弧!
1.2 tf中的“維”
在tf中斥赋,用constant定義的tensor
- 0維數(shù)組灿渴,表示一個數(shù)胰舆,如:6缚窿。(可以理解為“點”)
- 1維數(shù)組倦零,表示一個a = [1,2,3]吨悍。(可以理解為“線”育瓜,這也和上面的向量聯(lián)系起來了。一方面躏仇,這是一個三維向量恋脚,另一方面,在n維坐標系中焰手,向量是一條直線糟描,是“線”)
- 2維數(shù)組,表示一個
b = [[1,2,3],
[4,5,6]]书妻。(可以理解為“面”船响,或者矩陣) - 3維數(shù)組,表示一個
c = [[[1,2,3],[4,5,6]],
[[7,8,9],[1,1,1]],
[[2,2,2],[3,3,3]]]
可以理解為“體”躲履。
1.3 對數(shù)組進行索引
索引见间,類似于Python中的列表索引工猜,0表示第一個元素缤剧,但又不一樣。
比如域慷,對上面的2維數(shù)組b進行索引 荒辕,得到
b[0] = [1,2,3],
c[0] = [[1.2.3].[4.5.6]] (都是數(shù)組里的第一個元素)
1.4 tf.reduce_xxx操作中的axis
因為版本的不同汗销,有時參數(shù)axis(軸)等同于參數(shù)reduction_indices(減去索引)
這里所說的,應(yīng)該是側(cè)重于axis軸的意思
這里作者就按照坐標軸來理解抵窒。比如弛针,上面的三維數(shù)組c,我把它理解為由x李皇,y削茁,z軸組成的坐標系中的三個自變量組成的“體”,c的0維就相當于x變量掉房,剩下的由y和z兩個組成的幾個平面茧跋,也就是剩下的3個二維數(shù)組。這里的“c的0維”不等于“c[0]”卓囚。
那么瘾杭。去掉c的0維,就相當于只剩下y哪亿,z兩個變量組成的三個平面粥烁。
reduc_sum(c,0)那就理解為蝇棉,先把三個平面相加讨阻,再去掉x自變量。
所以篡殷,就相當于钝吮,先把每個第0維里面的元素(即三個二維數(shù)組)按照規(guī)則相加,再去掉最外面的“0維”板辽。于是搀绣,最后剩一個二維數(shù)組。
最外面的中括號代表了第0維戳气,再往里代表了第1維(比如[[1,2,3],[4,5,6]],第一維里面的元素相加链患,就是[1,2,3]+[4,5,6]),再往里代表了第2維(比如[1,2,3].)
1.5 代碼
具體別的情況瓶您,就看下面代碼麻捻。其中,keep_dims表示的意思就是呀袱,照常計算贸毕,但不消除該維。
import tensorflow as tf
import numpy as np
x = [[[1,2,3],[4,5,6]],
[[7,8,9],[1,1,1]],
[[2,2,2],[3,3,3]]]
x = tf.constant(x)
# x 后面沒有參數(shù)夜赵,就默認為把所有的元素相加
a = tf.reduce_sum(x)
#把所有0維里的元素都按照規(guī)則相加明棍,再消去0維度(即消去代表0維度的中括號)
b = tf.reduce_sum(x,0)
#以下沒有消去的維度都是保留的
#只舉一個例子,把目前所有1維里的元素都相加如 ==>得到相加的結(jié)果 ==>再消去1維度
# [1,2,3]+[4,5,6] ==> [5,7,9] ==>5,7,9
c = tf.reduce_sum(x,1)
#只舉一個例子寇僧, 把所有第2維的元素都相加 ==> 得到結(jié)果 ==> 消去2維度
# [1+2+3],[4+5+6] ==> [6],[15] ==> 6,15
d = tf.reduce_sum(x,2)
# 把第1維所有元素相加摊腋,得到結(jié)果 ==> 再把第2維所有元素相加沸版,得到結(jié)果 ==>消去1,2維度
# [[[5,7,9]],[[8,9,10]],[[5,5,5]]]==>[[[21]],[[27]],[[15]]]==>[21,27,15]
f = tf.reduce_sum(x,[1,2])
#把0維所有元素相加以后,1維所有元素相加以后兴蒸,2維所有元素相加以后消去012維
g = tf.reduce_sum(x,[0,1,2])
#把目前所有1維里的元素都相加如 ==>得到相加的結(jié)果 ==>但不消去1維度(即括號不去掉)== 保留該維度
# [1,2,3]+[4,5,6] ==> [5,7,9] ==>[5,7,9]
h = tf.reduce_sum(x,1,keep_dims=True)
#只舉一個例子视粮, 把所有第2維的元素都相加 ==> 得到結(jié)果 ==> 但不消去2維度 == 保留該維度
# [1+2+3],[4+5+6] ==> [6],[15] ==> [6],[15]
i = tf.reduce_sum(x,2,keep_dims=True)
with tf.Session() as sess:
print('a',sess.run(a))
print('b',sess.run(b))
print('c',sess.run(c))
print('d',sess.run(d))
print('f',sess.run(f))
print('g',sess.run(g))
print('h',sess.run(h))
print('i',sess.run(i))
三、tf.nn.embedding_lookup()函數(shù)
基礎(chǔ)知識
shape橙凳,列表和數(shù)組蕾殴,
1 shape方法
shape方法得到的結(jié)果的是一個tuple,從第一個元素到最后一個元素岛啸,依次表示的是從數(shù)組第0維里含有元素的個數(shù)钓觉,第1維含有元素的個數(shù),第2維坚踩。荡灾。。如上面的x數(shù)組堕虹,x.shape ==>(3,2,3);再如a=[1,2,3]是一個列表芬首,那么a.shape ==>(3赴捞,)一定有一個逗號,表示這是一個元組的數(shù)據(jù)結(jié)構(gòu)2 列表和數(shù)組
在運用一個函數(shù)或者方法之前郁稍,一定要弄明白赦政,需要傳入的參數(shù)是什么數(shù)據(jù)結(jié)構(gòu)的!R恢着!就比如這個方法,作者一開始定義好x之后财破,沒有用np.array設(shè)置成數(shù)組掰派,或者用constant設(shè)置成一個整體的tensor,結(jié)果x一直是列表形式左痢,最終出現(xiàn)毛病靡羡。
def embedding_lookup(params, ids, partition_strategy="mod"),主要講這三個參數(shù)俊性。
params可以是一個tensor略步,也可以是多個tensor,不過輸入多個tensor的時候定页,需要用作為params=[a,b,c]的形式進行輸入趟薄。
當系統(tǒng)認為,params的長度等于1時候典徊,就和平時的索引一樣杭煎,按照ids中的id索引就行恩够。
但是當系統(tǒng)認為params的長度大于1的時候,就會用第三個參數(shù)(默認是“mod”)的模式岔帽,將params去掉里面每個tensor的中括號以后所有的元素個數(shù)玫鸟,按照求余數(shù)相同的方式分成len(params)個切片,每個切片里的第i個id對應(yīng)該切片里的第i個元素犀勒。
舉個栗子:
a = [[1,2,3],[4,5,6]]
b = [[7,8,9],[1,1,1]]
c = [[2,2,2],[3,3,3]]
a = tf.constant(a)
b = tf.constant(b)
c = tf.constant(c)
那么傳入params=[a,b,c],此時屎飘,系統(tǒng)認為params里是多個量了(3個tensor),那么去掉每個tensor的最外面中括號共有3*2=6個元素贾费,所以一共可以有6個id钦购,分別是012345,有3個tensor褂萧,就有3個切片押桃。按照余數(shù)相同分組,不均勻就前面的分的多导犹。分為[0,3],[1,4],[2,5],對應(yīng)的分別是 a唱凯,b,c谎痢。索引id時磕昼,id等于3,就相當于索引的是a中第二個元素节猿,所以索引的是[4,5,6].
另外票从,返回的tensor的shape應(yīng)該是shape(ids) + shape.params[1:]
這里的params指的是被索引的那個param
比如ids = [3],那么返回的結(jié)果的shape應(yīng)該是shape.[3] + shape.a[1:]=(1,)+(2,3)[1:] = (1,)+(3,) = (1,3),所以結(jié)果應(yīng)該是[[4,5,6]],二維數(shù)組
但這里滨嘱,這個函數(shù)是把a作為一個params了峰鄙,作為一個tensor了。
另外需要注意的是太雨,tf中傳入多個參數(shù)吟榴,就是用中括號把參數(shù)作為一個整體,以列表的方式傳給函數(shù)囊扳。所以煤墙,有的函數(shù)一旦遇到[a,b,c]這種形式的,就會認為a,b,c是參數(shù)宪拥。
所以仿野,若是x一開始定義為列表格式的話,那么這個函數(shù)就會把這個‘表示為列表的中括號’認為是類似于上面的[a,b,c]這個傳參的中括號她君,從而把x認為是由三個tensor組成的脚作。然后就會啟動上面所說的切片模式。比如用上面說的x,那么就會認為x是三個[2,3]的數(shù)組球涛。
但是如果用np.array(x)或者用x=tf.constant(x)以后劣针,x就被認為是一個整個的tensor了,那么這時候就認為x是1個亿扁,就不會啟動上面的切片模式捺典,就是正常的索引現(xiàn)象。
以后在遇到的時候从祝,需要先明確x是列表襟己,還是由constant定義好了的一個tensor(或者nparray定義的數(shù)組)。自己用的時候牍陌,最好用后者擎浴,把x當成是一個整體,若是需要輸入多個毒涧,那么就用[a,b,c]的方式輸入贮预。
四、 tf.gather(params,indices,..)
合并 - 索引indices所指示的params中的切片
比如a = tf.gather(x,[0契讲,2])仿吞,就是索引x這個tensor的0維下的元素的位置索引為0,2的兩個元素 并合并起來,即結(jié)果再放進一個列表中捡偏, 即使只有一個元素也要放進列表中
import tensorflow as tf
x = [[[1,2,3],[4,5,6]],
[[7,8,9],[1,1,1]],
[[2,2,2],[3,3,3]]]
a = tf.gather(x,[0,2])
with tf.Session() as sess:
print('a',sess.run(a))#輸出123,456和222,333
五唤冈、tf 的onehot函數(shù)
參考[tf.one_hot()函數(shù)簡介](http://www.reibang.com/writer#/notebooks/17771847/notes/18446692/preview
比如,輸入indices是一維列表霹琼,[1,3,5,7,9]务傲,depth等于10
那么就會輸出一個shape為[5,10]的二維數(shù)組凉当,其中第一行中的索引為1的位置為1枣申,其余為0.第二行中索引為3的位置為1,其余值為0.
如果輸入的indices是一個shape是[1,5]的二維數(shù)組看杭,[[1,3,5,7,9]]忠藤,那么輸出就會使一個[1,5,10]的三維數(shù)組。其中的onehot形式是一樣的楼雹。