tensorflow中的scope命名方法:name_scope, variavle_scope

轉自:知乎回答:tensorflow裏面name_scope, variable_scope等如何理解?

1

在訓練深度網絡時,爲了減少需要訓練參數的個數(比如具有simase結構的LSTM模型)、或是多機多卡並行化訓練大數據大模型(比如數據並行化)等情況時,往往需要共享變量。另外一方面是當一個深度學習模型變得非常複雜的時候,往往存在大量的變量和操作,如何避免這些變量名和操作名的唯一不重複,同時維護一個條理清晰的graph非常重要。因此,tensorflow中用tf.Variable(), tf.get_variable(), tf.Variable_scope(), tf.name_scope()幾個函數來實現:

1. tf.Variable(<variable_name>) 和 tf.get_variable(<variable_name>)的作用與區別: tf.Variable(<variable_name>)會自動檢測命名衝突並自行處理,但tf.get_variable(<variable_name>)則遇到重名的變量創建且變量名沒有設置爲共享變量時,則會報錯。 tf.Variable(<variable_name>)和tf.get_variable(<variable_name>)都是用於在一個name_scope下面獲取或創建一個變量的兩種方式,區別在於: tf.Variable(<variable_name>)用於創建一個新變量,在同一個name_scope下面,可以創建相同名字的變量,底層實現會自動引入別名機制,兩次調用產生了其實是兩個不同的變量。 tf.get_variable(<variable_name>)用於獲取一個變量,並且不受name_scope的約束。當這個變量已經存在時,則自動獲取;如果不存在,則自動創建一個變量

2. tf.name_scope(<scope_name>) 與 tf.variable_scope(<scope_name>):
tf.name_scope(<scope_name>):主要用於管理一個圖裏面的各種op,返回的是一個以scope_name命名的context manager。一個graph會維護一個name_space的
堆,每一個namespace下面可以定義各種op或者子namespace,實現一種層次化有條理的管理,避免各個op之間命名衝突。
tf.variable_scope(<scope_name>):一般與tf.name_scope()配合使用,用於管理一個graph中變量的名字,避免變量之間的命名衝突,tf.variable_scope(<scope_name>)允許在一個variable_scope下面共享變量。
需要注意的是:創建一個新的variable_scope時不需要把reuse屬性設置未False,只需要在使用的時候設置爲True就可以了。

with tf.variable_scope("image_filters1") as scope1:
result1 = my_image_filter(image1)
with tf.variable_scope(scope1, reuse = True)
result2 = my_image_filter(image2)

參考文獻:

TF Boys (TensorFlow Boys ) 養成記(三): TensorFlow 變量共享
https://www.tensorflow.org/versionsPython/tf/Graph#name_scope

2

在 tf.name_scope下時,tf.get_variable()創建的變量名不受 name_scope 的影響,而且在未指定共享變量時,如果重名會報錯,tf.Variable()會自動檢測有沒有變量重名,如果有則會自行處理。

import tensorflow as tf

with tf.name_scope(‘name_scope_x’):
    var1 = tf.get_variable(name=’var1’, shape=[1], dtype=tf.float32)
    var3 = tf.Variable(name=’var2’, initial_value=[2], dtype=tf.float32)
    var4 = tf.Variable(name=’var2’, initial_value=[2], dtype=tf.float32)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(var1.name, sess.run(var1))
    print(var3.name, sess.run(var3))
    print(var4.name, sess.run(var4))

\# 輸出結果:
\# var1:0 [-0.30036557]   可以看到前面不含有指定的’name_scope_x’
\# name_scope_x/var2:0 [ 2.]
\# name_scope_x/var2_1:0 [ 2.]  可以看到變量名自行變成了’var2_1’,避免了和’var2’衝突

如果使用tf.get_variable()創建變量,且沒有設置共享變量,重名時會報錯

import tensorflow as tf

with tf.name_scope('name_scope_1'):
    var1 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32)
    var2 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(var1.name, sess.run(var1))
    print(var2.name, sess.run(var2))

\# ValueError: Variable var1 already exists, disallowed. Did you mean 
\# to set reuse=True in VarScope? Originally defined at:
\# var1 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32)

所以要共享變量,需要使用tf.variable_scope()

import tensorflow as tf

with tf.variable_scope('variable_scope_y') as scope:
    var1 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32)
    scope.reuse_variables()  # 設置共享變量
    var1_reuse = tf.get_variable(name='var1')
    var2 = tf.Variable(initial_value=[2.], name='var2', dtype=tf.float32)
    var2_reuse = tf.Variable(initial_value=[2.], name='var2', dtype=tf.float32)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(var1.name, sess.run(var1))
    print(var1_reuse.name, sess.run(var1_reuse))
    print(var2.name, sess.run(var2))
    print(var2_reuse.name, sess.run(var2_reuse))
\# 輸出結果:
\# variable_scope_y/var1:0 [-1.59682846]
\# variable_scope_y/var1:0 [-1.59682846]   可以看到變量var1_reuse重複使用了var1
\# variable_scope_y/var2:0 [ 2.]
\# variable_scope_y/var2_1:0 [ 2.]

也可以這樣

with tf.variable_scope('foo') as foo_scope:
    v = tf.get_variable('v', [1])
with tf.variable_scope('foo', reuse=True):
    v1 = tf.get_variable('v')
assert v1 == v

或者這樣:

with tf.variable_scope('foo') as foo_scope:
    v = tf.get_variable('v', [1])
with tf.variable_scope(foo_scope, reuse=True):
    v1 = tf.get_variable('v')
assert v1 == v
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章