Tensorflow variable_scope:函数内的 tf.placeholder 和 tf.get_variable

Tensorflow variable_scope: tf.placeholder and tf.get_variable within a function

我只是想了解一下 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)

为什么会这样?我将 reuse 设置为 true,所以我希望张量再次处于相同的 variable_scope "foo" 中,或者程序会抛出类似 "tensors already defined" 的错误。

所以,我尝试了 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() 时吗?

谢谢!

您可以通过在名称后添加“/”来强制重复使用范围,即: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)

请注意,与变量不同,占位符不维护可重复使用或不可重复使用的状态。它们只是张量的 "pointer" ,稍后将被提供。它们不应该是您模型的一部分,而是模型的输入,因此无论如何您都不应该多次创建它们。

仅针对您 运行 Jupyter notebook 中的代码两次的情况,确保 notebook 的内核没有重复使用变量。

如果您在默认图表的范围内多次调用函数 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 的答案是推荐的解决方案。