tf.variable_scope中的重用选项如何工作?

时间:2017-08-23 03:16:50

标签: python tensorflow with-statement

from __future__ import print_function
import tensorflow as tf

def _var_init(name, shape, initializer=tf.contrib.layers.xavier_initializer(),
              trainable=True):
  with tf.device('/cpu:0'):
    var = tf.get_variable(
      name=name,
      shape=shape,
      initializer=initializer,
      trainable=trainable
    )
    return var

def main():
  sess = tf.Session()

  # 1th case, it works
  with tf.variable_scope('test1', reuse=False) as test1:
    with tf.variable_scope('test2', reuse=False) as test2:
      w1 = _var_init('w1', [1, 2])
      sess.run(tf.global_variables_initializer())
      print(sess.run(w1), w1)

  # 2th case, it works
  with tf.variable_scope('test1', reuse=True):
    with tf.variable_scope('test2', reuse=False):
      w2 = _var_init('w1', [1, 2])
      print(sess.run(w2), w2)

  # 3th case, it works
  with tf.variable_scope(test1, reuse=False):
    with tf.variable_scope(test2, reuse=True):
      w3 = _var_init('w1', [1, 2])
      print(sess.run(w3), w3)

  # 4th case, ValueError: Variable test1/test2/w1 already exists.
  with tf.variable_scope(test1, reuse=True):
    with tf.variable_scope(test2, reuse=False):
      w4 = _var_init('w1', [1, 2])
      print(sess.run(w4), w4)

  # 5th case, ValueError: Variable test1/test2/w1 already exists.
  with tf.variable_scope('test1', reuse=False):
    with tf.variable_scope('test2', reuse=False):
      w5 = _var_init('w1', [1, 2])
      print(sess.run(w5), w5)


if __name__ == '__main__':
    main()

第1至第3案例输出:

[[ 0.34345531 -0.84748644]] <tf.Variable 'test1/test2/w1:0' shape=(1, 2) dtype=float32_ref>
[[ 0.34345531 -0.84748644]] <tf.Variable 'test1/test2/w1:0' shape=(1, 2) dtype=float32_ref>
[[ 0.34345531 -0.84748644]] <tf.Variable 'test1/test2/w1:0' shape=(1, 2) dtype=float32_ref>

问题:

我很困惑为什么第二个案例有效但第四个案例失败了。 Tensorflow是否通过scope_name搜索variable_scope?第2例和第4例之间的区别是什么? (即with tf.variable_scope('test1', reuse=True):with tf.variable_scope(test1, reuse=False):之间的区别是什么?)

我认为他们之前是一样的。但现在他们看起来不同了。 tf.variable_scope中的重用选项如何工作?

类似但不重复的问题:

  1. How does the reuse option in tf.variable_scope work? ;

  2. How do I force tf.variable_scope to reuse name_scope?

1 个答案:

答案 0 :(得分:1)

从Tensorflow的官方文档中可以解释重用选项:

这是共享变量的基本示例:

with tf.variable_scope("foo"):
     v = tf.get_variable("v", [1])
with tf.variable_scope("foo", reuse=True):
     v1 = tf.get_variable("v", [1])
assert v1 == v

通过捕获范围和设置重用来共享变量:

with tf.variable_scope("foo") as scope:
    v = tf.get_variable("v", [1])
    scope.reuse_variables()
    v1 = tf.get_variable("v", [1])
assert v1 == v

类似地,我们在尝试获取在重用模式中不存在的变量时引发异常。

with tf.variable_scope("foo", reuse=True):
    v = tf.get_variable("v", [1])
    #  Raises ValueError("... v does not exists ...").

请注意,重用标志是继承的:如果我们打开一个重用范围,那么它的所有子范围也会重用。

关于名称范围的说明:设置重用不会影响其他操作(如mult)的命名。请参阅github上的相关讨论#6189

请注意,直到并包括版本1.0,允许(尽管明确不鼓励)将False传递给重用参数,从而产生与None略有不同的未记录行为。从1.1.0开始传递None和False,因为重用具有完全相同的效果。