上上篇博文也写了这个话题,这次自己又敲了一下代码,再次研究了一下关于tf.Variable() 和 tf.get_variable() 的区别, 我就先不说太多,先直接看看代码,再来总结分析,下面代码中注释部分为输出结果。
with tf.variable_scope('aa') as scope:
w = tf.get_variable("a1", [1, 2])
var = tf.Variable([0], name='var1', dtype=tf.float32)
va = tf.Variable([0], name='var1', dtype=tf.float32)
print(w.name) # aa/a1:0
print(var.name) # aa/var1:0
print(va.name) # aa/var1_1:0
with tf.variable_scope('aa', reuse=True): # 如果 reuse=False则会报错
b = tf.get_variable('a1')
print(w.name) # aa/a1:0
不难看出这就是我们常说的 作用域共享变量,在同一个 variable_scope下,如果存在同名变量,tf.Variable()会自动处理,使之不重名,从而不会报错;tf.get_variable() 则必须声明 reuse = True 。如果在开启reuse=True的一个变量作用域里面,使用一个之前定义好的变量作用域,则会跳过当前变量的作用域,保持预先存在的作用域不变。 tf.variable_scope 对op_name 以及 variable_name 都会被加上域名前缀,eg. w.name == aa/a1,我们再来看下一段代码:
with tf.variable_scope('foo'):
with tf.name_scope('bar'):
v = tf.get_variable('v', [1])
b = tf.Variable([2], name='b')
w = 1.0 + v
print(w.name)
assert v.name == 'foo/v:0'
assert b.name == 'foo/bar/b:0'
assert w.name == 'foo/bar/add:0'
这段代码什么都不会输出(当然没有输出,hh)也不会报错, 说明assert 语句都通过了。这时你对 tf.variable_scope 对op_name 以及 variable_name 都会被加上域名前缀 这句话是不是就懂了?另外你应该还会发现 name_scope 影响 tf.Variable 以及 op_name,不影响tf.get_variable(所谓影响是指是否加上域名前缀)。需要指出的是 name_scope 的作用是为变量划分范围,在可视化中,这表示为一个层级。下次有时间说说 tensorboard 的时候我们可以细细说来。