tensorflow-作用域


 

變量名字由兩部分組成: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加前綴。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM