tf.name_scope:用于定义Python op的上下文管理器。
tf.name_scope(
name
)
此上下文管理器将推送名称范围,这将使在其中添加的所有操作的名称带有前缀。
例如,定义一个新的Python op my_op
:
def my_op(a, b, c, name=None):
with tf.name_scope("MyOp") as scope:
a = tf.convert_to_tensor(a, name="a")
b = tf.convert_to_tensor(b, name="b")
c = tf.convert_to_tensor(c, name="c")
# Define some computation that uses `a`, `b`, and `c`.
return foo_op(..., name=scope)
在执行时,张量a
,b
,c
,将有名字MyOp/a
,MyOp/b
和MyOp/c
。
在tf.function
范围内,如果范围(scope)名称已经存在,则通过追加_n
将名称唯一。例如,my_op
第二次调用将生成MyOp_1/a
,等等。
Args:
name:在名称范围内创建的所有名称上使用的前缀。
Raises:
ValueError:如果name不是字符串。
Attributes:
name:在名称范围内创建的所有名称上使用的前缀。
注意:
tf.variable_scope可以让变量有相同的命名方式,包括tf.get_variable变量和tf.Variable变量
tf.name_scope可以让变量有相同的命名方式,只限于tf.Variable变量
import tensorflow as tf
with tf.variable_scope('V1'):
a1 = tf.get_variable(name='a11', shape=[1], initializer=tf.constant_initializer(1))
a2 = tf.Variable(tf.random_normal(shape=[2, 3], mean=0, stddev=1), name='a21')
with tf.variable_scope('V2'):
a3 = tf.get_variable(name='a12', shape=[1], initializer=tf.constant_initializer(1))
a4 = tf.Variable(tf.random_normal(shape=[2, 3], mean=0, stddev=1), name='a22')
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
print(a1.name)
print(a2.name)
print(a3.name)
print(a4.name)
# 输出结果:
# V1/a11:0
# V1/a21:0
# V2/a12:0
# V2/a22:0
import tensorflow as tf
with tf.name_scope('V1'):
a1 = tf.get_variable(name='a11', shape=[1], initializer=tf.constant_initializer(1))
a2 = tf.Variable(tf.random_normal(shape=[2, 3], mean=0, stddev=1), name='a21')
with tf.name_scope('V2'):
a3 = tf.get_variable(name='a12', shape=[1], initializer=tf.constant_initializer(1))
a4 = tf.Variable(tf.random_normal(shape=[2, 3], mean=0, stddev=1), name='a22')
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
print(a1.name)
print(a2.name)
print(a3.name)
print(a4.name)
# 输出结果:
# a11:0
# V1/a21:0
# a12:0
# V2/a22:0
TF框架本身设计了比较完善的变量管理机制。变量作用域能够更好的管理模块的变量(特别是将来会重用到的变量)。
tf常用的变量作用域有两种:tf.name_scope和tf.variable_scope,
tf本身的变量管理有如下接口:tf.get_variables 和 tf.Variable
tf.name_scope
主要与tf.Variable搭配使用,调用方式为:
tf.name_scope('scope_name')
#or
tf.name_scope(named_scope)
以上两种方式均可。当传入字符串时,用以给变量名添加前缀,类似于目录,如下述代码所示:
import tensorflow as tf
# case 1:
with tf.name_scope('s1'):
with tf.name_scope('s2'):
w1 = tf.Variable([1, 2, 3], name='w')
bias1 = tf.Variable([0.1], name='biases')
bias2 = tf.Variable([0.1], name='biases')
print(w1.name, bias1.name, bias2.name)
# s1/s2/w:0 s1/s2/biases:0 s1/s2/biases_1:0
# case 2:
with tf.name_scope('s1'):
with tf.name_scope('s2'):
w1 = tf.Variable([1, 2, 3], name='w')
bias1 = tf.Variable([0.1], name='biases')
bias2 = tf.Variable([0.1], name='biases')
print(w1.name, bias1.name, bias2.name)
# s1_1/s2/w:0 s1_1/s2/biases:0 s1_1/s2/biases_1:0
# case 3:
with tf.name_scope('s1'):
with tf.name_scope('s2'):
w1 = tf.Variable([1, 2, 3], name='w')
bias1 = tf.Variable([0.1], name='biases')
bias2 = tf.Variable([0.1], name='biases')
print(w1.name, bias1.name, bias2.name)
# s1_2/s2/w:0 s1_2/s2/biases:0 s1_2/s2/biases_1:0
import tensorflow as tf
# case 1:
with tf.name_scope('s1'):
with tf.name_scope('s2'):
w1 = tf.Variable([1, 2, 3], name='w')
bias1 = tf.Variable([0.1], name='biases')
bias2 = tf.Variable([0.1], name='biases')
print(w1.name, bias1.name, bias2.name)
# s1/s2/w:0 s1/s2/biases:0 s1/s2/biases_1:0
# case 2:
with tf.name_scope('s1') as scope_1:
w2 = tf.Variable([1, 2, 3], name='w')
bias2 = tf.Variable([0.1], name='biases')
bias3 = tf.Variable([0.1], name='biases')
with tf.name_scope('s2'):
w3 = tf.Variable([1, 2, 3], name='w')
bias4 = tf.Variable([0.1], name='biases')
bias5 = tf.Variable([0.1], name='biases')
with tf.name_scope(scope_1):
w4 = tf.Variable([1, 2, 3], name='w')
bias6 = tf.Variable([0.1], name='biases')
bias7 = tf.Variable([0.1], name='biases')
print(w2.name, bias2.name, bias3.name, w3.name, bias4.name, bias5.name, w4.name, bias6.name, bias7.name)
# s1_1/w:0 s1_1/biases:0 s1_1/biases_1:0 s1_1/s2/w:0 s1_1/s2/biases:0 s1_1/s2/biases_1:0 s1_1/w_1:0 s1_1/biases_2:0
# s1_1/biases_3:0
当传入已存在的name_scope对象时,则其范围内变量的前缀只与当前传入的对象有关,与其上层的name_scope无关,如case2所示。
注意:当name_scope重名时,会自动加入后缀,variable也是如此。
tf.variable_scope
常与get_variable搭配使用,多用于变量共享,调用方式为:
tf.variable_scope('scope_name', reuse=None)
#or
tf.variable_scope(named_scope)
其中 reuse 参数可设为 None、tf.AUTO_REUSE、True、False;
与name_scope一样:当传入字符串时,用以给变量名添加前缀,类似于目录;
当传入已存在的variable_scope对象时,则其范围内变量的前缀只与当前传入的对象有关,与其上层的variable_scope无关。
resue作用域:
当 reuse=None(默认情况)时,与上层variable_scope的reuse参数一样。
当 reuse=tf.AUTO_REUSE 时,自动复用,如果变量存在则复用,不存在则创建。这是最安全的用法。相当于python字典的get方法。
import tensorflow as tf
with tf.variable_scope('s1'):
with tf.variable_scope('s2'):
init = tf.constant_initializer(0.1)
w1 = tf.get_variable('w', [2, 2])
bias1 = tf.get_variable('biases', [2, 2])
print(w1.name, bias1.name)
# s1/s2/w:0 s1/s2/biases:0
with tf.variable_scope('s1', reuse=tf.AUTO_REUSE):
with tf.variable_scope('s2'):
init = tf.constant_initializer(0.1)
w2 = tf.get_variable('w', [2, 2])
bias2 = tf.get_variable('biases', [2, 2])
bias3 = tf.get_variable('biases', [2, 2])
print(w2.name, bias2.name, bias3.name)
# s1/s2/w:0 s1/s2/biases:0 s1/s2/biases:0
当 reuse=True 时,tf.get_variable会查找该命名变量,如果没有找到,则会报错;所以设置reuse=True之前,要保证该命名变量已存在。
下述代码如为第一次运行,当变量未定义,则会报错
import tensorflow as tf
with tf.variable_scope('s1', reuse=True):
with tf.variable_scope('s2'):
init = tf.constant_initializer(0.1)
w1 = tf.get_variable('w', [2, 2])
bias1 = tf.get_variable('biases', [2, 2])
bias2 = tf.get_variable('biases', [2, 2])
print(w1.name, bias1.name, bias2.name)
# ValueError: Variable s1/s2/w does not exist, or was not created with tf.get_variable(). Did you mean to set
# reuse=tf.AUTO_REUSE in VarScope?
import tensorflow as tf
with tf.variable_scope('s1'):
with tf.variable_scope('s2'):
init = tf.constant_initializer(0.1)
w1 = tf.get_variable('w', [2, 2])
bias1 = tf.get_variable('biases', [2, 2])
print(w1.name, bias1.name)
# s1/s2/w:0 s1/s2/biases:0
with tf.variable_scope('s1', reuse=True):
with tf.variable_scope('s2'):
init = tf.constant_initializer(0.1)
w1 = tf.get_variable('w', [2, 2])
bias2 = tf.get_variable('biases', [2, 2])
bias3 = tf.get_variable('biases', [2, 2])
print(w1.name, bias2.name, bias3.name)
# s1/s2/w:0 s1/s2/biases:0 s1/s2/biases:0
当 reuse=False 时,tf.get_variable会调用tf.Variable来创建变量,并检查创建的变量是否已存在,如果已存在,则报错。
import tensorflow as tf
with tf.variable_scope('s1'):
with tf.variable_scope('s2'):
init = tf.constant_initializer(0.1)
w1 = tf.get_variable('w', [2, 2])
bias1 = tf.get_variable('biases', [2, 2])
print(w1.name, bias1.name)
# s1/s2/w:0 s1/s2/biases:0
with tf.variable_scope('s1', reuse=False):
with tf.variable_scope('s2'):
init = tf.constant_initializer(0.1)
w1 = tf.get_variable('w', [2, 2])
bias2 = tf.get_variable('biases', [2, 2])
bias3 = tf.get_variable('biases', [2, 2])
print(w1.name, bias2.name, bias3.name)
# ValueError: Variable s1/s2/w already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in
# VarScope? Originally defined at: w1 = tf.get_variable('w', [2, 2])