定义变量的两种方式:
tf.Variable()
tf.get_Variable()
import tensorflow as tf var1 = tf.Variable(1., name='first_var') print('I am var1: ', var1.name) var1 = tf.Variable(2., name='first_var') print('I am var1 too: ', var1.name) var2 = tf.Variable(3.) print('I am var2: ', var2.name) var2 = tf.Variable(4.) print('I am var2 too: ', var2.name) # I am var1: first_var:0 # I am var1 too: first_var_1:0 # I am var2: Variable:0 # I am var2 too: Variable_1:0
看到上面的测试代码,当使用 tf.Variable() 定义变量时,变量是可以重名的,只是会自动修改其名字,不指定名字时,系统自动分配。
tf.get_variable()中形参 name 必须指定
get_var1 = tf.get_variable(name='gv', shape=[])
print('I am get_var1: ', get_var1.name)
# get_var1 = tf.get_variable(name='gv', shape=[])
# print('I am get_var1 too, but I will cause a error: ', get_var1.name)
# I am get_var1: gv:0
# Traceback (most recent call last):
# ValueError: Variable gv already exists, disallowed. Did you mean to set reuse=True
# or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:
# get_var1 = tf.get_variable(name='gv', shape=[])
当使用 tf.get_Variable() 定义变量时,name 必须指定,而且不能重复,不然会报错
tf.name_scope() 和 tf.variable_scope() 之间的区别
既然 tf.get_variable() 不允许重名,那怎么办? 放心吧,总会有办法解决的。要解决这个问题,就要引入 tf.variable_scope() ,隔离开 tf.get_variable() 定义的同名变量就可以了
看个例子
with tf.variable_scope('vs1'): get_var1 = tf.get_variable(name='getVar', shape=[]) with tf.variable_scope('vs2'): get_var2 = tf.get_variable(name='getVar', shape=[]) with tf.variable_scope('vs3'): get_var3 = tf.get_variable(name='getVar', shape=[]) with tf.variable_scope('vs4'): get_var4 = tf.get_variable(name='getVar', shape=[]) print('get_var1', get_var1.name) # get_var1 vs1/getVar:0 print('get_var2', get_var2.name) # get_var2 vs2/getVar:0 print('get_var3', get_var3.name) # get_var3 vs3/getVar:0 print('get_var4', get_var4.name) # get_var4 vs3/vs4/getVar:0同名的变量在程序中共存,完美解决这个问题。
在看一些代码的时候, 经常会看到 tf.name_scope() 和 tf.variable_scope(), 那他们两个到底啥关系呢?
tf.name_scope() 主要是用来管理命名空间的,这样子让我们的整个模型更加有条理
tf.variable_scope() 的作用是为了实现变量共享,常和 tf.get_variable() 一起完成变量共享的功能。with tf.name_scope('ns'): var1 = tf.Variable(1., tf.float32) with tf.variable_scope('vs'): var2 = tf.Variable(2., tf.float32) get_var = tf.get_variable(name='gv', shape=[]) print('var1', var1.name) # var1 ns/Variable:0 print('var2', var2.name) # var2 ns/vs/Variable:0 print('get_var', get_var.name) # get_var vs/gv:0从上面的 get_var 的作用范围,可以看出 tf.get_variable() 不受 tf.name_scope() 的控制
下面就来看看共享变量怎么操作的。
tf.variable_scope() 中有一个 reuse 的参数,表示使用已经定义过的变量,当然如果使用的变量未定义,就会报错...with tf.variable_scope('vs5'): get_var5 = tf.get_variable(name='getVar_reuse', shape=[]) with tf.variable_scope('vs5', reuse=True): get_var6 = tf.get_variable(name='getVar_reuse', shape=[]) # get_var7 = tf.get_variable(name='getVar_unknown', shape=[]) print('get_var5', get_var5.name) # get_var5 vs5/getVar_reuse:0 print('get_var6', get_var6.name) # get_var6 vs5/getVar_reuse:0 # print('get_var7', get_var7.name) # 报错
tf.variable_scope() 和 tf.get_variable() 的初始化变量功能
with tf.variable_scope('vs6', initializer=tf.constant_initializer(1.)): get_var8 = tf.get_variable(name='getVar8', shape=[1]) with tf.variable_scope('vs7'): get_var9 = tf.get_variable(name='getVar9', shape=[1]) get_var10 = tf.get_variable(name='getVar10', shape=[1], initializer=tf.constant_initializer(2.)) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print('get_var8 = ', get_var8.eval()) print('get_var9 = ', get_var9.eval()) print('get_var10 = ', get_var10.eval()) # get_var8 = [1.] # get_var9 = [1.] # get_var10 = [2.]
从上面的测试代码中可以看出 tf.variable_scope() 和 tf.get_variable() 都有初始化变量的功能,而且如果后者初始化的话,会覆盖前者的初始化值。
看看下面的一个例子,怎么使内层变量使用另一个作用于的变量
with tf.variable_scope('vs8') as vs8: get_var11 = tf.get_variable(name='getVar11', shape=[]) print('vs8: ', vs8.name) # vs8: vs8 print('getVar11', get_var11.name) # getVar11 vs8/getVar11:0 with tf.variable_scope('vs9'): get_var12 = tf.get_variable(name='getVar12', shape=[]) with tf.variable_scope(vs8, reuse=True) as vs8_: get_var13 = tf.get_variable(name='getVar13', shape=[]) print('vs8_: ', vs8.name) # vs8_: vs8 print('getVar12', get_var12.name) # getVar12 vs9/getVar12:0 print('getVar13', get_var13.name) # getVar13 vs8/getVar13:0
这样 vs9 空间的就可以使用 vs8 中的变量了。
tf.name_scope() 使用空字符串将作用域返回到顶层
with tf.variable_scope('vs10'): get_var14 = tf.get_variable(name='getVar14', shape=[]) with tf.variable_scope('vs11'): get_var15 = tf.get_variable(name='getVar15', shape=[]) with tf.name_scope(''): get_var16 = tf.Variable(1., name='getVar16') with tf.variable_scope(''): get_var17 = tf.get_variable(name='getVar17', shape=[]) print('getVar14', get_var14.name) print('getVar15', get_var15.name) print('getVar16', get_var16.name) print('getVar17', get_var17.name) # getVar14 vs10/getVar14:0 # getVar15 vs10/vs11/getVar15:0 # getVar16 getVar16:0 # getVar17 vs10/vs11//getVar17:0 # 中间多个空层