TensorFlow學習記錄:variable_scope()和name_scope()函數的區別

1.variable_scope()

1.1 variable_scope() 對get_variable()的影響

首先,我們在相同的variable_scope內使用get_variable()函數創建一個name屬性爲a的變量a1

import tensorflow as tf
with tf.variable_scope("one"):
	a1=tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
print(a1.name)
#輸出:one/a:0

然後我們再在同一個variable_scope內內使用get_variable()函數創建一個name也屬性爲a的變量a2

import tensorflow as tf
with tf.variable_scope("one"):
	a2=tf.get_variable("a",[1])
print(a2.name)
#輸出:Variable one/a already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:

我們可以看到編譯器報錯了,這兩個代碼說明了variable_scope函數影響了get_variable函數的使用,在創建變量a2的時候由於變量空間one中已經存在一個name屬性爲a的變量a1了,所以編譯器會報錯,並且我們看到報錯提示了是否在本變量空間設置參數reuse=True。

reuse參數的默認值爲False,上面那個代碼報錯的原因就是variable_scope()函數中的reuse參數的默認值爲False,當variable_scope()函數的參數reuse=False時,上下文管理器內的所有get_variable()函數都只執行新建變量的操作而不執行獲取變量的操作;當variable_scope()函數的參數reuse=True時,這個上下文管理器內的所有get_variable()函數都只執行獲取變量的操作而不執行新建變量的操作。說明代碼如下:

import tensorflow as tf
with tf.variable_scope("one"):
    a1=tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
    
with tf.variable_scope("one",reuse=True):
    a2=tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
    
    print(a1.name,a2.name)
#輸出:one/a:0 one/a:0

在某個variable_scope中(不一定是上面所述的one,可以是任意的,例如two等),當variable_scope()函數使用reuse=True參數生成上下文管理器時,若果變量空間中並沒有創建過屬性爲a的變量,使用get_variable()函數時編譯器將會報錯。說明代碼如下:

import tensorflow as tf
with tf.variable_scope("two",reuse=True):
	a1=tf.get_variable("a",initializer=tf.constant_initializer(1.0))
	print(a1.name)
#輸出:Variable two/a does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?

此外,若果我們不知道當前變量空間的參數reuse是True還是False時,我們可以print(tf.get_variable_scope().reuse)來確定reuse的值。

with tf.variable_scope("two",reuse=True):
    print(tf.get_variable_scope().reuse)
#輸出:True

1.2 variable_scope() 對Variable()的影響

通過上面的說明我們可以知道當variable_scope()函數的參數reuse=False時,上下文管理器內的所有get_variable()函數都只執行新建變量的操作而不執行獲取變量的操作;當variable_scope()函數的參數reuse=True時,這個上下文管理器內的所有get_variable()函數都只執行獲取變量的操作而不執行新建變量的操作。

而對於Variable()函數來說,因爲這個函數的功能只是創建變量,不能像get_variable()函數既可以創建變量,又可以獲取變量,所以說variable_scope() 函數中的參數reuse是True還是False對Variable()函數來說沒影響,它的功能都只是創建變量。

import tensorflow as tf
with tf.variable_scope("one",reuse=True):
    a3=tf.Variable([1.0],name="a")

print(a3.name)

with tf.variable_scope("one",reuse=False):
    a4=tf.Variable([1.0],name="a")

print(a4.name)
#輸出:one/a:0
#     one_1/a:0

2.name_scope()

2.1 name_scope()對get_variable()函數的影響

先看代碼

with tf.name_scope("a"):
    a=tf.get_variable("b",[1])
    print(a.name)
#輸出:b:0

再來看另個一個代碼

with tf.name_scope("b"):
    c=tf.get_variable("b",[1])
    print(c.name)
#輸出:Variable b already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:

可以看到,name_scope()沒有對 tf.get_variable()創建的變量增加“範圍”,如第一個代碼所示,輸出的變量名稱面前沒有變量空間名,但是,如果想創建一個屬性name也爲b的變量c,即使不在同一個name_scope裏,編譯器仍然會報錯,這也恰好說明了name_scope()沒有對 tf.get_variable()創建的變量增加“範圍”

2.2 name_scope()對variable()函數的影響

看代碼

with tf.name_scope("a"):
	a=tf.Variable([1],name='a')
print(a.name)
#輸出:a/a:0

再創建一個變量a

with tf.name_scope("a"):
    a=tf.Variable([1],name='a')
print(a.name)
#輸出:a_1/a:0

在另一個name_scope()創建變量a

with tf.name_scope("b"):
    a=tf.Variable([1],name='a')
print(a.name)
#輸出:b/a:0

可以看到,name_scope()對 tf.Variable()創建的變量增加“範圍”,第一個代碼塊中變量a的name屬性爲a/a:0,第二個代碼塊a的name屬性爲a_1/a:0,第三個代碼塊中變量a的name屬性爲b/a:0,說明了在name_scope()中,tf.Variable()可以創建同名字且屬性name相同的變量,但每個變量都會被系統創建在不同的變量環境中。

參考書籍:《TensorFlow深度學習算法原理與編程實戰》 蔣子陽 著

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章