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.