tf.variable_scope
标签(空格分隔): tensorflow深入理解
类初始化函数
def __init__(self,
name_or_scope,
default_name=None,
values=None,
initializer=None,
regularizer=None,
caching_device=None,
partitioner=None,
custom_getter=None,
reuse=None,
dtype=None,
use_resource=None,
constraint=None,
auxiliary_name_scope=True):
"""Initialize the context manager.
创建命名空间
with tf.variable_scope(...) as scope:
CODE
官方对于创建命名空间的解释:
If
name_or_scope
is not None, it is used as is. Ifname_or_scope
is None,
thendefault_name
is used. In that case, if the same name has been
previously used in the same scope, it will be made unique by appending_N
to it.
TensorFlow共享机制
在TensorFlow中,每一个变量(vaiable)和每一个操作(operation, Op)都是有名字的(string类型的)。有时候会共享训练网络和测试网络中的权值,通话过怎样的方式呢?
下面来说说,tf.variable_scope这样一个类。我们一个个举例说明。
作用一:区分命名空间
with tf.variable_scope("foo"):
v1 = tf.get_variable("v", [1])
with tf.variable_scope("bar"):
v2 = tf.get_variable("v", [1])
assert v2.name == "foo/bar/v:0"
从上面的例子来说,通过tf.variable_scope可以得到不同的命名空间:
v1变量的名字 : foo/v:0
v2变量的名字 : foo/bar/v:0
自动共享机制
def foo():
with tf.variable_scope("foo", reuse=tf.AUTO_REUSE):
v = tf.get_variable("v", [1])
return v
v1 = foo() # Creates v.
v2 = foo() # Gets the same, existing v.
assert v1 == v2
在foo()
函数中,我们创建了一个v
这样的变量,并在tf.variable_scope
中设置reuse=tf.AUTO_REUSE
就是我们再调用foo()
函数时,自动将创建的变量并将reuse = true
设置共享以及共享报错的机制
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"):
v = tf.get_variable("v", [1])
v1 = tf.get_variable("v", [1])
# Raises ValueError("... v already exists ...").
这个比较好理解,我们再同一个命名空间中,创建了名字(v)一样的两个变量而且当前命名空间reuse = None,所以,自然就报错。
with tf.variable_scope("foo", reuse=True):
v = tf.get_variable("v", [1])
# Raises ValueError("... v does not exists ...").
这个也是不对的,因为,当前的命名空间并没有被创建,所以,不能找到被共享的那个变量。
共享总结
TensorFlow我并没有看它的底层代码,caffe的看过,这部分具体在net.cpp的Init函数中体现。
个人猜想:当一个变量被创建的时候,TensorFlow会根据用户或者自己内部,为每个变量设置一个名字(string)类型的,然后创建一个字典或者一个map映射
就是当一个命名空间reuse = true, 就会在已经创建的名字中去查找,有没有名字已经相同的变量,如果找到了OK,咱们两指针指向同一个数据块!如果没有没有找到,不好意思,你还没有创建,你让我和谁共享,就会报错,提示变量没有生成!在Caffe源代码中,请看我之前的一篇博客 Caffe源码解读Net源文件
tf.variable_scope其他参数
tensorflow 这种命名空间机制,给复杂的网络搭建过程提供了极大的遍历,只需在各种命名做各种解释,比如,创建的变量怎么初始化的、convLayer的激活函数是啥,正则化参数是哈都可以在一个命名空间的一次性说明开头说明,后面就会变成默认值
def __init__(self,
name_or_scope, # 命名空间的名字
default_name=None, #默认名字
values=None, # 往该段命名空间,输入的参数
initializer=None, #变量初始化方式
regularizer=None, # 正则化
caching_device=None,
partitioner=None,
custom_getter=None,
reuse=None, # 是否共享
dtype=None, # 变量的默认类型
use_resource=None,
constraint=None,
auxiliary_name_scope=True):
"""Initialize the context manager.