本文翻译自: 《Scopes and when to use them》, 如有侵权请联系删除, 仅限于学术交流, 请勿商用。 如有谬误, 请联系指出。
在 TensorFlow 中, 变量(Variables)和张量(tensors)有一个名字(name)属性, 用于在符号图中标识它们。 如果在创建变量或张量时未指定名称, TensorFlow 会自动为您指定名称:
a = tf.constant(1)
print(a.name) # prints "Const:0"
b = tf.Variable(1)
print(b.name) # prints "Variable:0"
您可以通过显式指定来覆盖默认名称:
a = tf.constant(1, name = "a")
print(a.name)# prints "a:0"
b = tf.Variable(1, name = "b")
print(b.name)# prints "b:0"
TensorFlow 引入了两个不同的上下文管理器来改变张量和变量的名称。 第一个是 tf.name_scope
:
with tf.name_scope("scope"):
a = tf.constant(1, name="a")
print(a.name) # prints "scope/a:0"
b = tf.Variable(1, name="b")
print(b.name) # prints "scope/b:0"
c = tf.get_variable(name="c", shape=[])
print(c.name) # prints "c:0"
请注意, 有两种方法可以在 TensorFlow 中定义新变量, 一是创建 tf.Variable
对象或是调用 tf.get_variable
方法。 使用新名称调用 tf.get_variable
会导致创建新变量, 但如果存在具有相同名称的变量, 则会引发 ValueError 异常, 告诉我们不允许重新声明变量。
tf.name_scope
影响使用 tf.Variable
创建的张量和变量的名称, 但不影响使用 tf.get_variable
创建的变量。
与 tf.name_scope
不同, tf.variable_scope
也修改了使用 tf.get_variable
创建的变量的名称:
with tf.variable_scope("scope"):
a = tf.constant(1, name="a")
print(a.name) # prints "scope/a:0"
b = tf.Variable(1, name="b")
print(b.name) # prints "scope/b:0"
c = tf.get_variable(name="c", shape=[])
print(c.name) # prints "scope/c:0"
with tf.variable_scope("scope"):
a1 = tf.get_variable(name="a", shape=[])
a2 = tf.get_variable(name="a", shape=[]) # Disallowed
但是, 如果我们真的想要复用先前声明的变量呢? 变量范围还提供了执行此操作的功能:
with tf.variable_scope("scope"):
a1 = tf.get_variable(name="a", shape=[])
with tf.variable_scope("scope", reuse=True):
a2 = tf.get_variable(name="a", shape=[]) # OK
这在使用内置神经网络层时变得很方便:
with tf.variable_scope('my_scope'):
features1 = tf.layers.conv2d(image1, filters=32, kernel_size=3)
# Use the same convolution weights to process the second image:
with tf.variable_scope('my_scope', reuse=True):
features2 = tf.layers.conv2d(image2, filters=32, kernel_size=3)
或者, 您可以将 reuse
属性设置为 tf.AUTO_REUSE
, 这种操作告诉 TensorFlow 如果不存在具有相同名称的变量, 就创建新变量, 否则就复用:
with tf.variable_scope("scope", reuse=tf.AUTO_REUSE):
features1 = tf.layers.conv2d(image1, filters=32, kernel_size=3)
with tf.variable_scope("scope", reuse=tf.AUTO_REUSE):
features2 = tf.layers.conv2d(image2, filters=32, kernel_size=3)
如果你想共享很多变量, 跟踪定义新变量以及复用这些变量的时候可能很麻烦且容易出错。 tf.AUTO_REUSE
则简化了此任务, 但增加了共享不应共享的变量的风险。 TensorFlow 模板是解决这一问题的另一种方法, 它没有这种风险:
conv3x32 = tf.make_template("conv3x32", lambda x: tf.layers.conv2d(x, 32, 3))
features1 = conv3x32(image1)
features2 = conv3x32(image2) # Will reuse the convolution weights.
您可以将任何功能转换为 TensorFlow 模板。 在第一次调用模板时, 在函数内部定义的变量会被声明, 并且在连续调用中, 它们将被自动复用。