使用默认作用域名称时不会重用variable_scope

时间:2018-11-14 12:32:23

标签: python tensorflow

在重用变量时,我对子范围有疑问。这个

import tensorflow as tf

def make_bar():
  with tf.variable_scope('bar'):
    tf.get_variable('baz', ()) 

with tf.variable_scope('foo') as scope:
  make_bar()
  scope.reuse_variables()
  make_bar()

工作正常,只创建了一个变量foo/bar/baz

但是,如果我将make_bar更改为

def make_bar(scope=None):
  with tf.variable_scope(scope, 'bar'):
    tf.get_variable('baz', ()) 

代码现在失败,并显示

ValueError: Variable foo/bar_1/baz does not exist

问题:为什么在使用default name时变量范围重用失败?如果是有目的的,那么此选择的依据是什么?

编辑

default_name的{​​{1}}参数上有一些精度。 From the documentation,

  
      
  • tf.variable_scope:如果default_name参数为name_or_scope时使用的默认名称,该名称将是唯一的。如果提供了None,则不会使用它,因此它不是必需的,可以是name_or_scope
  •   

因此,作为其名称的基础,这是提供默认作用域名称的一种方式。

None的第一个版本中,作用域名称被强制为make_bar -函数没有参数可以对其进行更改。

bar的第二版中,我增强了此功能以使其可参数化。因此,make_bar仍然是默认作用域名称(这次提供为bar的{​​{1}}参数),但是这次调用者可以通过设置默认参数{{ default_name中的1}}到tf.variable_scope以外的任何其他位置。

我认为第二个版本的scope不带参数时,我认为应该回到第一个版本的行为,而没有。

请注意,在我的示例中,make_barNone的子范围。要重用的变量为 meant make_bar

2 个答案:

答案 0 :(得分:4)

在示例中,您实际上并没有使用范围'foo'。您需要将参数传递给tf.variable_scope('foo', 'bar')tf.variable_scope(scope, 'bar')。 您在任何一种情况下都调用不带参数的方法make_bar,这意味着在第一个示例name_or_scope='bar',第二个示例name_or_scope=scope(值None)和{ {1}}。

这可能是您想要的:

default_name='bar'

实际上,我建议不要使用默认参数,因为它们会像您的示例那样降低可读性。 import tensorflow as tf def make_bar(scope=None): with tf.variable_scope(scope, 'bar'): tf.get_variable('baz', ()) with tf.variable_scope('foo') as scope: make_bar(scope) scope.reuse_variables() make_bar(scope) 范围什么时候才是您想要的答案?如果您进行测试,可能会更有意义?

None

但是这会使代码的可读性降低,并且更有可能导致错误

答案 1 :(得分:2)

摘自文档https://www.tensorflow.org/api_docs/python/tf/variable_scope

  

如果name_or_scope不为None,则照原样使用。如果name_or_scope   为无,则使用default_name。在这种情况下,如果同名   已在同一范围内使用过,它将变为唯一   通过向其附加_N

...

  

为防止意外共享变量,我们在   在非重用范围内获取现有变量。

...

  

类似地,当我们尝试获取一个   在重用模式下不存在。

通过使用None范围,您将强制每次对get_variable的调用来生成唯一的范围/变量,但是通过调用reuse_variables,您将迫使后续的调用仅返回现有变量。没有要返回的变量,因此引发了ValueError。这是预期的行为。