TensorFlow中的变量命名以及命名空间.

What:

在Tensorflow中, 为了区别不同的变量(例如TensorBoard显示中), 会需要命名空间对不同的变量进行命名. 其中常用的两个函数为: tf.variable_scope, tf.name_scope.

Why:

在自己的编写代码过程中, 用如下代码进行变量生成并进行卷积操作:

 1 import tensorflow as tf
 2 import numpy as np
 3 
 4 def my_conv2d(data, name, kh, kw, sh, sw, n_out):
 5     n_in = np.shape(data)[-1]
 6     with tf.name_scope(name):
 7         kernel = tf.get_variable(name="W", shape=[kh, kw, n_in, n_out], dtype=tf.float32, initializer=tf.contrib.layers.xavier_initializer())
 8         bias = tf.Variable(tf.constant(0.0, shape=[n_out], dtype=tf.float32), name="b")
 9         conv = tf.nn.conv2d(data, kernel, stride=[1, sh, sw, 1], padding='SAME', name="Conv")
10         result = tf.nn.relu(tf.nn.bias_add(conv, bias), name="Act")
11         return result.

运行时会报错:

ValueError: Variable bar already exists, disallowed. Did you mean to set reuse=True in VarScope? ...

How:

中国工信出版社的<TensorFlow 实战Google深度学习学习框架>P231, 对tf.name_scope和tf.variable_scope做了一个详细的解释, 转载在下面:

这两个函数在大部分情况下是等价的, 唯一的区别是在使用tf.get_variable函数时.

import tensorflow as tf

with tf.variable_scope("foo"):
    a = tf.get_variable("bar", [1])
    print a.name    # 输出 foo/bar: 0

with tf.variable_scope("bar"):
    b = tf.get_variable("bar", [1])
    print b.name     # 输出 bar/bar: 0

with tf.name_scope("a"):
    a = tf.Variable([1])
    print a.name     # 输出 a/Variable: 0

  a = tf.Variable("b", [1]):
  print a.name # 输出 b: 0


with tf.name_scope("b"):
    tf.get_variable("b", [1])        # Error

从上面的输出看出. 如果在使用tf.get_variable()生成变量, 这时的命名是不受tf.name_scope的影响, 而会收到tf.variable_scope的影响, 因此对于我自己的情况, 问题在于my_conv2d在多次调用时, 变量命名重复, 由此可见修改方案可以考虑改为用tf.variable_scope. 我在下面贴出另一种解决方案(每次调用都给予不同的变量名):

def my_conv2d(data, name, kh, kw, sh, sw, n_out):
    n_in = np.shape(data)[-1]
    with tf.name_scope(name) as scope:
    kernel = tf.get_variable(name=scope+"W", shape=[kh, kw, n_in, n_out], dtype=tf.float32, initializer=tf.contrib.layers.xavier_initializer())
    bias = tf.Variable(tf.constant(0.0, shape=[n_out], dtype=tf.float32), name=scope+"b")
    conv = tf.nn.conv2d(data, kernel, stride=[1, sh, sw, 1], padding='SAME', name=scope+"Conv")
    result = tf.nn.relu(tf.nn.bias_add(conv, bias), name=Scope+"Act")
    return result.