“with tf.variable_scope("scope_name") as vs:”
上面这句是我们最常用的语句之一,用来定义一个域,以方便对变量进行操作,tf.variable_scope("scope_name") 会得到一个variable_scope的类。
但是,如果我们用函数tf.get_variable_scope() 来获取当前域。会得到一个VariableScope类
yyy = tf.variable_scope('scope_name')
print(yyy)
sss = tf.get_variable_scope()
print(sss)
结果:
<tensorflow.python.ops.variable_scope.variable_scope object at 0x7f92b96cb780>
<tensorflow.python.ops.variable_scope.VariableScope object at 0x7f92b96cbdd8>
这2个明显不是一个同一种类。那么他们的关系是什么呢?
这要从最一开始的“with tf.variable_scope("scope_name") as vs: ”说起
我们知道with的用法是调用with后面的对象的__enter__()方法,如果有as语句,则将__enter__()的返回结果赋予as后面的变量,即vs。
我们打印出vs就会发现,vs的类型恰恰是<tensorflow.python.ops.variable_scope.VariableScope object at 0x7f92b96cbdd8>
with tf.variable_scope("scope_name") as vs:
print(vs)
结果:
<tensorflow.python.ops.variable_scope.VariableScope object at 0x7f92b96cbdd8>
因此我们可以得到结论:
variable_scope.__enter__() == VariableScope
再进一步引申,我们平时所用到的域,其实是VariableScope。VariableScope对象中包含了这个域中的所有variable,collection等等各种属性和方法,详见https://www.tensorflow.org/api_docs/python/tf/compat/v1/VariableScope。VariableScope有一个属性name,如果我们想要切换进某个VariableScope,通过tf.variable_scope("scope_name") 可以找到这个VariableScope,然后通过__enter__()方法切换进这个scope。所以tf.variable_scope可以理解成通过VariableScope的name值寻找VariableScope的反射。
我们再进一步引申:
scope的结构是什么样的呢?
我们都知道如果用:
with tf.variable_scope("scope_name1") as vs1:
with tf.variable_scope("scope_name2") as vs2:
会创建一个scope_name1/scope_name2 的域,即我们可以把域看作一个集合,父域的属性会影响到子域。例如我们对父域使用tf.get_variable_scope().reuse_variables()。则会使得子域也全都处于reuse的状态。
而所有域的父域全都是一个无名域,这个无名域的name=''。是在创建graph的时候生成的。因此,如果我们在最外层写了tf.get_variable_scope().reuse_variables(),则对所有的域都会生效