【问题标题】:Tensorflow variable_scope: tf.placeholder and tf.get_variable within a functionTensorflow variable_scope:函数内的 tf.placeholder 和 tf.get_variable
【发布时间】:2018-12-01 03:30:16
【问题描述】:

我只是试图了解 TensorFlow 命名行为,但我仍然需要一些说明。 我在一个项目中遇到了张量命名的麻烦,因为它们是在一个函数中预定义的,稍后会调用它。

所以我这里有下面的例子:

import tensorflow as tf


    def foo():

        with tf.variable_scope("foo", reuse=True):

            a = tf.placeholder(tf.float32,name="a")
            b = tf.placeholder(tf.float32,name="b")

        return a,b
    ##

    a,b  = foo()

    print(a)
    print(b)

我得到输出:

Tensor("foo/a:0", dtype=float32)
Tensor("foo/b:0", dtype=float32)

当我再次调用它时,我得到了输出:

Tensor("foo_1/a:0", dtype=float32)
Tensor("foo_1/b:0", dtype=float32)

为什么会这样?我将重用设置为 true,因此我希望张量再次位于同一个 variable_scope“foo”中,或者程序会抛出类似“张量已定义”的错误。

所以,我尝试了使用 tf.get_variable 的解决方法:

    def foo():
    with tf.variable_scope("foo", reuse=True):

        a = tf.get_variable("v", [1])


    return a
##

a1 = foo()
print(a1)

graph = tf.get_default_graph()
#call tensors by name in tensorflow to avoid confusion with the naming
graph.get_tensor_by_name("foo/v:0")

在这里,我总是得到相同的输出:

<tf.Variable 'foo/v:0' shape=(1,) dtype=float32_ref>

很遗憾,我无法使用变量,因为您无法为它们定义动态形状。您需要占位符来定义可变形状。 有人可以解释一下为什么程序继续为占位符创建新的 variable_scopes 而不是在我调用 tf.get_variable() 时?

谢谢!

【问题讨论】:

    标签: python tensorflow naming


    【解决方案1】:

    如果您在 Jupyter 笔记本中运行了两次代码,请确保笔记本的内核没有重用变量。

    如果您改为在默认图形范围内多次调用函数foo(),您总是会得到相同的结果:

    def foo():
      with tf.variable_scope("foo", reuse=True):
        a = tf.placeholder(tf.float32,name="a")
        b = tf.placeholder(tf.float32,name="b")
      return a,b
    
    with tf.Graph().as_default():
      a,b  = foo()
    
      print(a) # gives variable name 'foo/a'
      print(b) # gives variable name 'foo/b'
    

    但这与用例不同,在用例中,函数被重复调用以创建更多占位符。

    c,d = foo()
    

    在这种情况下,f4 的上述答案是推荐的解决方案。

    【讨论】:

      【解决方案2】:

      您可以通过在名称后添加“/”来强制重用范围,即:tf.variable_scope("foo/", reuse=True):

      但这并不能解决您的问题。

      在变量的情况下,调用tf.Variable 将始终创建一个新变量,而调用tf.get_variable 将重用它,如果它已经存在。

      但是对于占位符,没有tf.get_placeholder

      您可以做的是在 foo 之外定义占位符,仅一次,然后使用 tf.get_default_graph().get_tensor_by_name(name) 按名称获取它们,或者在需要时直接使用 python 变量获取它们。

      get_tensor_by_name 示例:

      import tensorflow as tf
      
      with tf.name_scope("scope"):
          tf.placeholder(tf.float32,name="a")
          tf.placeholder(tf.float32,name="b")
      
      def foo():
          a = tf.get_default_graph().get_tensor_by_name("scope/a:0")
          b = tf.get_default_graph().get_tensor_by_name("scope/b:0")
      
          return a,b
      
      a,b = foo()
      
      print(a)
      print(b)
      

      请注意,与变量不同,占位符不保持可重用或不可重用的状态。它们只是指向稍后将被馈送的张量的“指针”。它们不应该是模型的一部分,而是模型的输入,因此无论如何您都不应该多次创建它们。

      【讨论】:

        猜你喜欢
        • 2021-05-13
        • 1970-01-01
        • 1970-01-01
        • 2018-01-10
        • 2019-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多