1. 程式人生 > >【tensorflow 學習】 name_scope和variable_scope的區別

【tensorflow 學習】 name_scope和variable_scope的區別

在tensorflow中,有兩個scope, 一個是name_scope一個是variable_scope,這兩個scope到底有什麼區別呢? 

三個例子

先看第一個程式:

with tf.name_scope("hello") as name_scope:
    arr1 = tf.get_variable("arr1", shape=[2,10],dtype=tf.float32)
    arr2 = tf.Variable(1, name="arr2", dtype=tf.float32)
    print(name_scope)                           #hello/
    print(arr1.name)                            #arr1:0
    print(arr2.name)                            #hello/arr2:0
    print("scope_name:%s " % tf.get_variable_scope().original_name_scope)   #空

#輸出
hello/
arr1:0
hello/arr2:0
scope_name: 

可以看出:

  • tf.name_scope() 返回的是 一個string,”hello/”
  • 在name_scope使用 get_variable() 中定義的 variable 的 name 並沒有字首
  • 在name_scope使用variable()定義的variable的名字是有 “hello/”字首的
  • tf.get_variable_scope().original_name_scope 是空

第二個程式:

import tensorflow as tf
with tf.variable_scope("hello") as variable_scope:
    arr1 = tf.get_variable("arr1", shape=[2, 10], dtype=tf.float32)
    arr2 = tf.Variable(1, name="arr2", dtype=tf.float32)
    
    print(variable_scope)#<tensorflow.python.ops.variable_scope.VariableScope object at 0x7fbc09959210>
    print(variable_scope.name) #打印出變數空間名字                     #hello
    print(arr1.name)                                                 #hello/arr1:0 
    print(arr2.name)                                                 #hello/arr2:0
    print(tf.get_variable_scope().original_name_scope)               #hello/
    #tf.get_variable_scope() 獲取的就是variable_scope

    with tf.variable_scope("xixi") as v_scope2:
        print(tf.get_variable_scope().original_name_scope)           #hello/xixi/


#輸出
<tensorflow.python.ops.variable_scope.VariableScope object at 0x0000020B2AAF9390>
hello
hello/arr1:0
hello/arr2:0
hello/
hello/xixi/

可以看出:

  • tf.variable_scope() 返回的是一個 VariableScope 物件
  • variable_scope使用 get_variable 定義的variable 的name加上了”hello/”字首
  • tf.get_variable_scope().original_name_scope 是 巢狀後的scope name

第三個程式:

with tf.name_scope("name1"):
    with tf.variable_scope("var1"):
        w = tf.get_variable("w",shape=[2])
        res = tf.add(w,[3])
print(w.name)
print(res.name)

# 輸出
var1/w:0
name1/var1/Add:0

可以看出:

  • variable_scopename_scope都會給opname加上字首 
  • 這實際上是因為建立 variable_scope 時內部會建立一個同名的 name_scope

對比三個個程式可以看出:

  • name_scope 返回的是 string, 而 variable_scope 返回的是物件. 這也可以感覺到, variable_scope 能幹的事情比 name_scope 要多.
  • name_scope對 get_variable()建立的變數 的名字不會有任何影響,而建立的op會被加上字首.
  • tf.get_variable_scope() 返回的只是 variable_scope,不管 name_scope. 所以以後我們在使用tf.get_variable_scope().reuse_variables() 時可以無視name_scope

其他:

with tf.name_scope("scope1") as scope1:
    with tf.name_scope("scope2") as scope2:
        print(scope2)
#輸出:
scope1/scope2/     最後有斜槓
with tf.variable_scope("scope1") as scope1:
    with tf.variable_scope("scope2") as scope2:
        print(scope2)
        print(scope2.name)

#輸出:
<tensorflow.python.ops.variable_scope.VariableScope object at 0x00000194F95C81D0>
scope1/scope2

tf.name_scope()可以用來幹什麼

tf.get_variable不起作用,只對tf.Variable起作用

典型的 TensorFlow 可以有數以千計的節點,如此多而難以一下全部看到,甚至無法使用標準圖表工具來展示。為簡單起見,我們為op/tensor名劃定範圍,並且視覺化把該資訊用於在圖表中的節點上定義一個層級。預設情況下, 只有頂層節點會顯示。下面這個例子使用tf.name_scope在hidden命名域下定義了三個操作: 

import tensorflow as tf

with tf.name_scope('hidden') as scope:
  a = tf.constant(5, name='alpha')
  W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0), name='weights')
  b = tf.Variable(tf.zeros([1]), name='biases')

  print(a.name)                          #hidden/alpha 
  print(W.name)                          #hidden/weights 
  print(b.name)                          #hidden/biases 


#輸出
hidden/alpha 
hidden/weights 
hidden/biases 

name_scope 是給op_name加字首, variable_scope是給get_variable()建立的變數的名字加字首。

tf.variable_scope有時也會處理命名衝突

import tensorflow as tf
def test(name=None):
    with tf.variable_scope(name, default_name="scope") as scope:
        w = tf.get_variable("w", shape=[2, 10])

test()
test()
ws = tf.trainable_variables()
for w in ws:
    print(w.name)

#scope/w:0
#scope_1/w:0
#可以看出,如果只是使用default_name這個屬性來建立variable_scope的時候,會處理命名衝突

其它

  • tf.name_scope(None) 有清除name scope的作用
import tensorflow as tf
with tf.name_scope("hehe"):
    w1 = tf.Variable(1.0)
    with tf.name_scope(None):
        w2 = tf.Variable(2.0)
print(w1.name)
print(w2.name)

#hehe/Variable:0
#Variable:0

tf.variable_scope()可以用來幹什麼

tf.get_variabletf.Variable都起作用

 variable_scope 用來管理 variable 詳見variable_scope

with tf.variable_scope("my_scope"):
    v1 = tf.get_variable("var1", [1], dtype=tf.float32)
    v2 = tf.Variable(1, name="var2", dtype=tf.float32)
    a = tf.add(v1, v2)

print(v1.name)  # my_scope/var1:0
print(v2.name)  # my_scope/var2:0
print(a.name)   # my_scope/Add:0

這種機制允許在不用的name_scope中使用tf.get_variable來share變數,但是需要注意的是,一定要宣告reuse:

with tf.name_scope("foo"):
    with tf.variable_scope("var_scope"):
        v = tf.get_variable("var", [1])
with tf.name_scope("bar"):
    with tf.variable_scope("var_scope", reuse=True):
        v1 = tf.get_variable("var", [1])
assert v1 == v
print(v.name)   # var_scope/var:0
print(v1.name)  # var_scope/var:0

輸出:
var_scope/var:0
var_scope/var:0

總結

簡單來看
1. 使用tf.Variable()的時候,tf.name_scope()tf.variable_scope() 都會給 Variableopname屬性加上字首。
2. 使用tf.get_variable()的時候,tf.name_scope()就不會給 tf.get_variable()創建出來的Variable加字首。但是 tf.Variable() 創建出來的就會受到 name_scope 的影響.

相關推薦

no