【问题标题】:What is the difference between variable_scope and name_scope? [duplicate]variable_scope 和 name_scope 有什么区别? [复制]
【发布时间】:2016-03-16 21:45:12
【问题描述】:

variable_scopename_scope 有什么区别? variable scope tutorial 谈论 variable_scope 隐式打开 name_scope。我还注意到,在 name_scope 中创建变量会自动使用范围名称扩展其名称。那么,有什么区别呢?

【问题讨论】:

    标签: python scope tensorflow


    【解决方案1】:

    在我尝试通过创建一个简单示例来可视化所有内容之前,我无法理解 variable_scopename_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,您会看到类似的模式(如您所见,bscope_name 矩形之外):


    这会给你答案

    现在您看到tf.variable_scope() 为所有变量(无论您如何创建它们)、操作、常量的名称添加了前缀。另一方面,tf.name_scope() 会忽略使用tf.get_variable() 创建的变量,因为它假定您知道要使用哪个变量以及在哪个范围内。

    Sharing variables 上的一个很好的文档告诉你

    tf.variable_scope():管理传递给tf.get_variable()的名称的命名空间。

    相同的文档提供了变量范围如何工作以及何时有用的更多详细信息。

    【讨论】:

    • 我建议通过删除vals 参数来简化这个非常有用的示例
    • 我还建议将 'd' 的名称从 'res' 更改。我认为这与您作为 scope2 传入的“res”无关。
    【解决方案2】:

    当您使用tf.get_variable 而不是tf.Variable 创建变量时,Tensorflow 将开始检查使用相同方法创建的变量的名称,以查看它们是否发生冲突。如果他们这样做,将引发异常。如果您使用 tf.get_variable 创建了一个 var,并尝试使用 tf.name_scope 上下文管理器更改变量名称的前缀,这不会阻止 Tensorflow 引发异常。在这种情况下,只有 tf.variable_scope 上下文管理器会有效地更改您的 var 名称。或者,如果您想重用该变量,您应该在第二次创建 var 之前调用 scope.reuse_variables()。

    总而言之,tf.name_scope 只是为在该范围内创建的所有张量添加一个前缀(使用tf.get_variable 创建的变量除外),tf.variable_scope 为使用tf.get_variable 创建的变量添加一个前缀。

    【讨论】:

    • 您能否详细说明为什么需要两种范围机制?
    • 我不知道。也许您应该在 github 上创建一个问题,要求更好地记录这两种机制之间的区别。
    • 我可以推测。我认为存在两种创建变量的方法(tf.Variable 和 tf.get_variable)的原因是因为通常您不想共享变量。如果要共享,则需要使用 tf.get_variable 创建一个 var 并使用 tf.variable_scope 更改范围,以明确表明您正在处理可共享的 var。如果在这种情况下可以使用 tf.name_scope,也许这会降低代码的可读性。
    • 这是否使 variable_scope 成为匿名范围,而 name_scope 是命名范围?如果是这样,将“name_scope”重命名为“named_variable_scope”是否有意义?
    【解决方案3】:

    tf.variable_scopetf.name_scope 的演变,以处理 Variable 重用。正如您所注意到的,它的作用远不止tf.name_scope,因此没有真正的理由使用tf.name_scope:毫不奇怪,a TF developper advises to just use tf.variable_scope

    我对@9​​87654328@ 仍然存在的理解是,这两者的行为存在细微的不兼容,这使得tf.variable_scope 作为tf.name_scope 的替代品无效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-23
      • 2013-02-13
      • 2011-04-26
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多