变量作用域 variable_scope
和名称作用域 name_scope
有什么区别?变量作用域教程 隐含地讲述了 variable_scope
打开 name_scope
. 我还注意到在 name_scope
中创建一个变量会自动使用作用域名称扩展变量名。那么,两者的区别是什么呢?
变量作用域 variable_scope
和名称作用域 name_scope
有什么区别?变量作用域教程 隐含地讲述了 variable_scope
打开 name_scope
. 我还注意到在 name_scope
中创建一个变量会自动使用作用域名称扩展变量名。那么,两者的区别是什么呢?
在我尝试通过创建一个简单的示例来可视化一切之前,我很难理解variable_scope和name_scope之间的区别(它们看起来几乎相同):
import tensorflow as tf
def scoping(fn, scope1, scope2, vals):
with fn(scope1):
a = tf.Variable(vals[0], name='a')
b = tf.get_variable('b', initializer=vals[1])
c = tf.constant(vals[2], name='c')
with fn(scope2):
d = tf.add(a * b, c, name='res')
print '\n '.join([scope1, a.name, b.name, c.name, d.name]), '\n'
return d
d1 = scoping(tf.variable_scope, 'scope_vars', 'res', [1, 2, 3])
d2 = scoping(tf.name_scope, 'scope_name', 'res', [1, 2, 3])
with tf.Session() as sess:
writer = tf.summary.FileWriter('logs', sess.graph)
sess.run(tf.global_variables_initializer())
print sess.run([d1, d2])
writer.close()
在这里,我创建了一个函数,它创建一些变量和常量,并将它们根据提供的类型分组到作用域中。在这个函数中,我还打印了所有变量的名称。之后,我执行图形以获取结果值的值并保存事件文件以在tensorboard中进行调查。如果您运行此代码,您会得到以下结果:
scope_vars
scope_vars/a:0
scope_vars/b:0
scope_vars/c:0
scope_vars/res/res:0
scope_name
scope_name/a:0
b:0
scope_name/c:0
scope_name/res/res:0
如果您打开TB(如下图所示,b
在scope_name
矩形框之外),将看到类似的模式:
这就给出了答案:
现在您可以看到,tf.variable_scope()
会为所有变量、操作和常量的名称添加前缀(无论您如何创建它们)。另一方面,tf.name_scope()
会忽略使用tf.get_variable()
创建的变量,因为它假定您知道要使用哪个变量以及在哪个作用域中使用。
共享变量的良好文档告诉您:
tf.variable_scope()
: 管理传递给tf.get_variable()
的名称的命名空间。
同一份文件提供了更详细的Variable Scope工作方式以及何时使用它的说明。
tf.get_variable
创建变量时,Tensorflow将开始检查使用相同方法创建的变量名称是否冲突。如果发生冲突,将引发异常。如果你使用tf.name_scope
上下文管理器尝试更改变量名称的前缀,这不会防止Tensorflow抛出异常。只有tf.variable_scope
上下文管理器才能有效地更改此情况下变量的名称。或者,如果想要重用变量,则应该在第二次创建变量之前调用scope.reuse_variables()。tf.name_scope
仅为该作用域中创建的所有张量添加前缀(除了使用tf.get_variable
创建的变量),而tf.variable_scope
则为使用tf.get_variable
创建的变量添加前缀。tf.variable_scope
是tf.name_scope
的演进,用于处理Variable
的重用。正如您所注意到的,它比tf.name_scope
做得更多,因此没有真正的理由使用tf.name_scope
:毫不奇怪,一个TF开发者建议只使用tf.variable_scope
。
我理解为什么还保留了tf.name_scope
是因为这两者的行为存在微妙的不兼容性,这使得tf.variable_scope
无法作为tf.name_scope
的替代品。
vals
参数。 - Mr_and_Mrs_D