前言
最近学习TensorFlow,看源码,其中有一些代码就在with tf.name_scope(‘nameScope’):
下书写,定义变量,还有一些就在with tf.variable_scope(‘varScope’):
下面,就很奇怪,想知道是怎么回事为什么要用这两个东西,写下这篇博客。
TensorFlow生成变量
首先要将的是TensorFlow生成变量,这主要有两种方式:
tf.get_variable()
tf.Variable()
tf.get_variable()
我们先了解一下tf.get_variable() ,代码如下:
var_0 = tf.get_variable(name='test2002000', shape=[1, ]) # name 必须填写, var_01 = tf.get_variable(name='test2002001', shape=[1, ]) var_1 = tf.get_variable(shape=[1, ], name='var_122') # 这里已经生成了name=var_122 的变量 var_2 = tf.get_variable(shape=[1, ], name='var_122') # 报错,有重复的变量名称 print(var_0.name) # test22002000:0 print(var_01.name) # test22002001:0 print(var_1.name) print(var_2.name)
运行可以知道,会以name值作为该变量在TF中的名称,而且用get_variable 不能name名存在,存在就会报错,报错信息:
ValueError: Variable var_122 already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:
报错信息很直接,就是name值重复了,你把name值改成不一样就不会有问题。
tf.Variable()的测试代码
var_0 = tf.Variable(initial_value=[0]) var_01 = tf.Variable(initial_value=[0]) var_1 = tf.Variable(initial_value=[0], name='var_1') var_2 = tf.Variable(initial_value=[0], name='var_1') var_3 = tf.Variable(initial_value=[0], name='var_1') print(var_0.name) # Variable_1:0 print(var_01.name) # Variable_2:0 print(var_1.name) # var_1_1:0 print(var_2.name) # var_1_2:0 print(var_3.name) # var_1_3:0
tf.Variable 可以name值一样,如果不给name就会默认
Variable_
开头,后面接1、2、3等数字,这样还不会报错。
那这样就涉及到一个问题,我定义了一个变量,给这个变量一个name
了,这个变量我后面还想利用,从变成语言的角度来看,我是不是可以把这个变量定义为全局变量,这样,我就可以直接拿变量,但在TF中,特别是定义的网路中,好像不是这样的,重点就是为什么要给变量一个name
属性?我猜测在TF中定义网络用name来区分变量,同样用name作为一个变量来赋值,用name来获取变量值,不知道是不是这样,暂时自己的一个猜测,我们来验证一下。tf.variable_scope(‘variableScope’)
先看一段代码:
varScope_Var_1 = tf.Variable(initial_value=[0], name='var_11') print("varScope_Var_1 = ",varScope_Var_1) var_1 = tf.get_variable(shape=[1, ],name='var_33') # print("var_1 = ",var_1) with tf.variable_scope('varScope'): test_var_1 = tf.get_variable(name='var_11', shape=[1, ]) print("test_var_1=",test_var_1) test_var_2 = tf.get_variable(name='var_33', shape=[1, ]) print("test_var_2=",test_var_2) varScope_Var_2 = tf.Variable(initial_value=[0], name='var_44') print(varScope_Var_1.name) print(varScope_Var_2.name)
代码结果为:
varScope_Var_1 = <tf.Variable 'var_11:0' shape=(1,) dtype=int32_ref> var_1 = <tf.Variable 'var_33:0' shape=(1,) dtype=float32_ref> test_var_1= <tf.Variable 'varScope/var_11:0' shape=(1,) dtype=float32_ref> test_var_2= <tf.Variable 'varScope/var_33:0' shape=(1,) dtype=float32_ref> var_11:0 varScope/var_44:0
我们可以看到 tf.variable_scope 会影响tf.get_variable和tf.Variable 的变量值,这个变量值都会有一个前缀
varScope
。如果我们要取出这个变量该如何操作:with tf.variable_scope('varScope', reuse=True): # reuse=True 表示 可以允许你复用变量 test_var_3 = tf.get_variable(name='var_11', shape=[1, ]) print("test_var_3=",test_var_3.name) test_var_4 = tf.get_variable(name='var_44', shape=[1, ]) # 报错,不存在 print("test_var_4=",test_var_4.name) with tf.variable_scope('varScope111', reuse=True): test_var_5 = tf.get_variable(name='var_11', shape=[1, ]) # 报错,不存在 print("test_var_5=",test_var_5.name)
结果输出:
test_var_3= varScope/var_11:0 报错:ValueError: Variable varScope111/var_11 does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?
也就说如果tf.variable_scope 命名空间中有这变量name值,就可以获取到,这样的情况就有一个更加专业的名词
共享
,如果没有这个name值, tf.get_variable 就会报错。
如果reuse=False
,情况就不一样了:with tf.variable_scope('varScope111', reuse=False): test_var_5 = tf.get_variable(name='var_11', shape=[1, ]) # 报错 print("test_var_5=",test_var_5.name)
结果输出:
test_var_5= varScope111/var_11:0
没有就生成一个新的变量,这个变量还可以用来共享,我们从上边的情况中可以得出,get_variable 可以variable_scope下共享变量,并且会加前缀命名空间,tf.Variable 就不能共享变量,但是加前缀命名空间。
tf.name_scope(‘nameScope’)
var_0 = tf.Variable(initial_value=[0],name="test1") print(var_0.name) test_var_1 = tf.get_variable(name='test1', shape=[1, ]) print("test_var_1.name=",test_var_1.name) with tf.name_scope('nameScope'): test_var_2 = tf.get_variable(name='test2', shape=[1, ]) print("test_var_2.name=",test_var_2.name) nameScope_Var_1 = tf.Variable(initial_value=[0], name='var_1') nameScope_Var_2 = tf.Variable(initial_value=[0], name='var_1') nameScope_Var_3 = tf.Variable(initial_value=[0], name='var_1') print(nameScope_Var_1.name) print(nameScope_Var_2.name)
运行结果:
test1:0 test_var_1.name= test1_1:0 test_var_2.name= test2:0 nameScope/var_1:0 nameScope/var_1_1:0
发现tf.name_scope 对 tf.get_variable 的变量名 不起作用, 对tf.Variable 会产生一个前缀,这个前缀类似文件路径。
总结
- tf.variable_scope 对tf.get_variable 和tf.Variable 的变量名都有影响,会加上命名空间前缀,如果要实现变量共享,就必须将tf.variable_scope的
reuse=True
,而且命名空间必须一样,否则就获取不到变量,报错z。 - tf.name_scope 对tf.Variable 的变量名有影响,对tf.get_variable没有影响。 后面再继续总结,有可能前面一些内容没有总结到位。