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深度学习算法原理与编程实战》 蒋子阳 著