變量名字由兩部分組成:scope/變量name。
name 參數才是對象的唯一標識。
1、tf.name_scope()
Graph中保存着一個屬性_name_stack(string類型),_name_stack的值保存着當前的name_scope的名字,在這個圖中創建的對象Variable、Operation、Tensor的名字之前都加上了這個前綴。
#它的主要目的是為了更加方便地管理參數命名。
# 與 tf.Variable() 結合使用。簡化了命名
with tf.name_scope('conv1') as scope:
weights1 = tf.Variable([1.0, 2.0], name='weights')
bias1 = tf.Variable([0.3], name='bias')
# 下面是在另外一個命名空間來定義變量的
with tf.name_scope('conv2') as scope:
weights2 = tf.Variable([4.0, 2.0], name='weights')
bias2 = tf.Variable([0.33], name='bias')
# 所以,實際上weights1 和 weights2 這兩個引用名指向了不同的空間,不會沖突
print (weights1.name) print (weights2.name) 輸出:
conv1/weights:0 conv2/weights:0
********************************************************************
# 注意,這里的 with 和 python 中其他的 with 是不一樣的
# 執行完 with 里邊的語句之后,這個 conv1/ 和 conv2/ 空間還是在內存中的。這時候如果再次執行上面的代碼
# 就會再生成其他命名空間(執行完上面的代碼,接着執行這里的,上面的空間還在內存中)
with tf.name_scope('conv1') as scope:
weights1 = tf.Variable([1.0, 2.0], name='weights')
bias1 = tf.Variable([0.3], name='bias')
with tf.name_scope('conv2') as scope:
weights2 = tf.Variable([4.0, 2.0], name='weights')
bias2 = tf.Variable([0.33], name='bias')
print (weights1.name)
print (weights2.name)
輸出:
conv1_1/weights:0
conv2_1/weights:0
注意,tf.Variable再次命名相同變量時(本來又要產生 conv1/weights:0 conv2/weights:0),結果這里產生了(conv1_1/weights:0 conv2_1/weights:0),所以這就是tf.Variable()的一個特性,遇到同名時,產生一個新的,並不共享。
2、 tf.variable_scope
Graph中維護一個collection,這個collection中的 鍵_VARSCOPE_KEY對應一個 [current_variable_scope_obj],保存着當前的variable_scope。使用 get_variable() 創建變量的時候,就從這個collection 取出 current_variable_scope_obj,通過這個 variable_scope創建變量。
tf.variable_scope() 主要結合 tf.get_variable() 來使用,實現變量共享。
如果tf.variable_scope函數使用參數reuse=None或者reuse=False創建上下文管理器,則tf.get_variable函數可以創建新的變量。但不可以創建已經存在的變量即為同名的變量。
如果tf.variable_scope函數使用參數reuse=True創建上下文管理器,則tf.get_variable函數可以使用已在當前空間定義的變量賦值來創建變量。但不可以使用不存在的變量來創建。
# 這里是正確的打開方式~~~可以看出,name 參數才是對象的唯一標識
with tf.variable_scope('v_scope') as scope1:
Weights1 = tf.get_variable('Weights', shape=[2, 3])
bias1 = tf.get_variable('bias', shape=[3])
# 下面來共享上面已經定義好的變量
# note: 在下面的 scope 中的變量必須已經定義過了,才能設置 reuse=True,否則會報錯
with tf.variable_scope('v_scope', reuse=True) as scope2:
Weights2 = tf.get_variable('Weights')
Weights3 = tf.get_variable('Weights', [2,3]) #shape如果不同會報錯
print (Weights2.name)
print (Weights3.name)
輸出
v_scope/Weights:0
v_scope/Weights:0
# 可以看到這兩個引用名稱指向的是同一個內存對象
*********************************************************************
# 注意, bias1 的定義方式
with tf.variable_scope('v_scope') as scope1:
Weights1 = tf.get_variable('Weights', shape=[2, 3])
bias1 = tf.Variable([0.52], name='bias')
# 下面來共享上面已經定義好的變量
# note: 在下面的 scope 中的get_variable()變量必須已經定義過了,才能設置 reuse=True,否則會報錯
with tf.variable_scope('v_scope', reuse=True) as scope2:
Weights2 = tf.get_variable('Weights')
bias2 = tf.Variable([0.53], name='bias')
print (Weights1.name)
print (Weights2.name)
print (bias1.name)
print (bias2.name)
輸出:
v_scope / Weights:0
v_scope / Weights:0
v_scope / bias:0
v_scope_1 / bias:0
使用tf.get_variable發現之前有定義好的的該變量,則進行權值共享。
而bias1 = tf.Variable([0.52], name='bias')發現之前定義好的名字,則重新定一個新的,並沒有共享權值。
tf.get_variable_scope() :獲取當前scope
tf.get_variable_scope().reuse_variables() 共享變量
3、對比
簡單來說name_scope是給Op_name加前綴的,variable_scope是給變量variable_name和Op_name加前綴的.作用域在使用Tensorboard對Graph對象進行可視化的時候很有幫助,作用域會把一些Op划分到較大的語句塊當中.使用tensorboard可視化數據流圖的時候,每個作用域都對自己的Op進行封裝,從而獲得更好的可視化效果.
- 如果在 tf.name_scope() 環境下分別使用 tf.get_variable() 和 tf.Variable(),兩者的主要區別在於
- tf.get_variable() 創建的變量名不受 name_scope 的影響;
- tf.get_variable() 創建的變量,name 屬性值不可以相同;tf.Variable() 創建變量時,name 屬性值允許重復(底層實現時,會自動引入別名機制)
- 此外 tf.get_variable() 與 tf.Variable() 相比,多了一個 initilizer (初始化子)可選參數;
- tf.Variable() 對應地多了一個 initial_value 關鍵字參數,也即對於 tf.Variable 創建變量的方式,必須顯式初始化;
name_scope
with tf.name_scope("ns") as ns:
b = tf.Variable(1.0, name='b')
w = tf.get_variable("w", shape=[2,10],dtype=tf.float32)
a = tf.add(b, [3],name='a')
print ns
print b.name
print w.name
print a.name
輸出:
ns /
ns / b:0
w:0
ns / a:0
*********************************************************************
with tf.name_scope("ns") as ns:
with tf.name_scope("ns1") as ns1:
b1 = tf.Variable(0, name='b1')
w1 = tf.get_variable("w1", shape=[10], dtype=tf.float32)
a1 = tf.add(b1, [3], name='a1')
print ns1
print b1.name
print w1.name
print a1.name
輸出:
ns/ns1/
ns/ns1/b1:0
w1:0
ns/ns1/a1:0
*********************************************************************
with tf.name_scope("ns") as ns:
with tf.variable_scope("vs1") as vs1:
b2 = tf.Variable(0, name='b2')
w2 = tf.get_variable("w2", shape=[2])
a2 = tf.add(b2, [3], name='a2')
print vs1
print vs1.name
print b2.name
print w2.name
print a2.name
輸出:
<tensorflow.python.ops.variable_scope.VariableScope object at 0x42fe790>
vs1
ns/vs1/b2:0
vs1/w2:0
ns/vs1/a2:0
*********************************************************************
with tf.name_scope("ns") as ns:
with tf.name_scope(None) as n1:
b3 = tf.Variable(2.0, name='b3')
w3 = tf.get_variable("w3", shape=[2])
a3 = tf.add(b3, [3], name='a3')
print n1
print b3.name
print w3.name
print a3.name
輸出:
b3:0
w3:0
a3:0
variable_scope
注意事項:
1. 在 variable_scope 里面的 variable_scope 會繼承上面的 reuse 值,即上面一層開啟了 reuse ,則下面的也跟着開啟。但是不能人為的設置 reuse 為 false ,只有退出 variable_scope 才能讓 reuse 變為 false:
2、當在某一 variable_scope 內使用別的 scope 的名字時,此時不再受這里的等級關系束縛,直接與使用的 scope 的名字一樣:
with tf.variable_scope("vs") as vs:
b = tf.Variable(1.0, name='b')
w = tf.get_variable("w", shape=[2, 10], dtype=tf.float32)
a = tf.add(b, [3], name='a')
print vs
print vs.name
print b.name
print w.name
print a.name
輸出:
<tensorflow.python.ops.variable_scope.VariableScope object at 0x46ee610>
vs
vs/b:0
vs/w:0
vs/a:0
*********************************************************************
with tf.variable_scope("vs") as vs:
with tf.name_scope("ns1") as ns1:
b1 = tf.Variable(0, name='b1')
w1 = tf.get_variable("w1", shape=[10], dtype=tf.float32)
a1 = tf.add(b1, [3], name='a1')
print ns1
print b1.name
print w1.name
print a1.name
輸出:
vs/ns1/
vs/ns1/b1:0
vs/w1:0
vs/ns1/a1:0
*********************************************************************
with tf.variable_scope("vs") as vs:
with tf.variable_scope("vs1") as vs1:
b2 = tf.Variable(0, name='b2')
w2 = tf.get_variable("w2", shape=[2])
a2 = tf.add(b2, [3], name='a2')
print vs1
print vs1.name
print b2.name
print w2.name
print a2.name
輸出:
<tensorflow.python.ops.variable_scope.VariableScope object at 0x4b1e310>
vs/vs1
vs/vs1/b2:0
vs/vs1/w2:0
vs/vs1/a2:0
*********************************************************************
with tf.variable_scope("vs") as vs:
with tf.name_scope(None) as n1:
b3 = tf.Variable(2.0, name='b3')
w3 = tf.get_variable("w3", shape=[2])
a3 = tf.add(b3, [3], name='a3')
print n1
print b3.name
print w3.name
print a3.name
輸出:
b3:0
vs/w3:0
a3:0
總結:
1、使用tf.Variable()的時候,tf.name_scope()和tf.variable_scope() 都會給 Variable 和 op 的 name屬性加上前綴。
2、使用tf.get_variable()的時候,tf.name_scope()就不會給 tf.get_variable()創建出來的Variable加前綴。
