tensorflow框架学习 (六)—— tensorflow命名空间
一、tensorflow命名空间
1、什么是命名空间
命名空间可以看成是一个集合,我们可以在里面创建变量,里面存放着的变量就是它的元素。例如我们定义一个命名空间命名为space,然后定义变量V1、V2,则我们就创建了一个有变量V1、V2的命名空间。不同命名空间的变量互不影响。
2、命名空间的作用:
在训练深度网络时,为了减少需要训练参数的个数(比如LSTM模型),或者是多机多卡并行化训练大数据、大模型等情况时,往往就需要共享变量。另外一方面是当一个深度学习模型变得非常复杂的时候,往往存在大量的变量和操作,如何避免这些变量名和操作名的唯一不重复,同时维护一个条理清晰的graph非常重要。
3、如何创建命名空间
利用tf.Variable_scope(name,reuse=False), tf.name_scope(name) 创建上下文处理器的方式来创建,然后可以在上下文处理器中用tf.Variable或者tf.get_variable来创建变量,如:
import tensorflow as tf
#创建命名空间并创建变量
with tf.variable_scope(name_or_scope='s1'):
v1=tf.get_variable(name='v1',initializer=tf.ones([1,1]))
with tf.name_scope(name='s2'):
v2=tf.Variable(tf.ones([1,1]),name='v2')
v3=tf.get_variable(name='v3',initializer=tf.ones([1,1]))
#输出变量名
print(v1.name)
print(v2.name)
print(v3.name)
输出结果为:
s1/v1:0
s2/v2:0
v3:0
可以发现在print在命名空间中的变量的时候会有对应的命名空间的前缀“s1/”,如果不在命名空间中则没有前缀。
4、在命名空间创建变量时的问题
(一)、tf.Variable_scope(name,reuse=False)、 tf.name_scope(name) 创建的上下文管理器用tf.Variable与tf.get_variable创建变量的时候如下区别:
- tf.Variable_scope可以同时作用于tf.Variable与tf.get_variable,为其创建的变量归属到tf.Variable_scope指定名称的命名空间;而tf.name_scope只能作用于tf.Variable,对tf.get_variable不起作用。
- tf.Variable_scope(name,reuse=False)可以创建新的命名空间也可以调用之前创建的命名空间;而tf.name_scope只能创建新的命名空间,因为它之作用与tf.Variable,而tf.Variable会对命名空间的重名做处理。
import tensorflow as tf
#创建命名空间并创建变量
with tf.variable_scope(name_or_scope='s1',reuse=False):
v1 = tf.Variable(initial_value=tf.zeros([1,1]),name='v1')
v2 = tf.get_variable(name='v2', shape=[1,1])
with tf.name_scope(name='s2'):
v3 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v3')
v4=tf.get_variable(name='v4',shape=[1,1])
#用同名的命名空间创建新的变量
with tf.variable_scope(name_or_scope='s1',reuse=False):
v5 = tf.get_variable(name='v5', shape=[1,1])
v6 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v6')
with tf.name_scope(name='s2'):
v7 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v7')
#输出变量名
print('不同点1:')
print('tf.variable_scope创建的命名空间s1')
print(v1.name)
print(v2.name)
print('tf.name_scope创建的命名空间s2')
print(v3.name)
print(v4.name)
print('=============================================')
print('不同点2:')
print('tf.variable_scope创建的重名命名空间s1')
print(v5.name)
print(v6.name,' #这里是s1_1二不是s1是由于tf.Variable处理命名空间重名造成的')
print('tf.name_scope创建的重名命名空间s2')
print(v7.name)
输出结果为:
不同点1:
tf.variable_scope创建的命名空间s1
s1/v1:0
s1/v2:0
tf.name_scope创建的命名空间s2
s2/v3:0
v4:0
=============================================
不同点2:
tf.variable_scope创建的重名命名空间s1
s1/v5:0
s1_1/v6:0 #这里是s1_1二不是s1是由于tf.Variable处理命名空间重名造成的
tf.name_scope创建的重名命名空间s2
s2_1/v7:0
(二)、tf.Variable与tf.get_variable创建变量的时候如下区别:
- tf.Variable每次都是新建一个变量,无论是在什么情况下;而tf.get_variable当tf.Variable_scope的参数reuse=Flase时只能创建新变量,否则报错,当reuse=True的时候只能调用原来的变量,否则报错。
- tf.Variable创建的变量如果和之前的变量重名,会自动处理避免重名,包括命名空间重名和变量重名;而tf.get_variable创建变量不会自动处理重名,若创建新变量的时候重名会报错,原因参考上一条。
- 在tf.Variable_scope创建的双下文管理器中,即使tf.Variable_scope调用的是曾经创建的命名空间,tf.Variable的命名空间的前缀也会做重名处理,而tf.get_variable则会与上一次创建的命名空间前缀保持一致,这样说比较难懂,一会看代码。
import tensorflow as tf
#不同点1:
# 创建命名空间并创建变量
with tf.variable_scope(name_or_scope='s1', reuse=False):
v1 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v1')
v2 = tf.get_variable(name='v2', shape=[1, 1])
try:
v2_ = tf.get_variable(name='v2', shape=[1, 1])
except:
print('reuse=False,tf.get_variable创建新变量时命名不能重复')
with tf.variable_scope(name_or_scope='s1', reuse=True):
v4 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v4')
try:
v_new = tf.get_variable(name='v_new', shape=[1, 1])
except:
print('reuse=True,tf.get_variable不能创建新变量')
print('不同点1:')
print(v1.name)
print(v2.name)
print(v4.name, ' #由于前后命名空间重名,所以tf.Variable自动处理了命名空间重名')
#不同点2与3:
# 创建命名空间并用tf.Variable创建同名变量
with tf.name_scope('s2'):
v5 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v5')
v5_1 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v5')
# 创建同名命名空间并用tf.Variable创建同名变量
with tf.name_scope('s2'):
v5_2 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v5')
# 创建同名命名空间并用tf.Variable创建同名变量
with tf.name_scope('s3'):
v5_3 = tf.Variable(initial_value=tf.zeros([1, 1]), name='v5')
print('==========================================================================')
print('不同点2与3:')
print(v5.name)
print(v5_1.name,' #同一上下文处理器创建的同名空间同名变量只处理变量重名')
print(v5_2.name,' #不同上下文处理器创建的同名空间同名变量只处理命名空间重名')
print(v5_3.name,' #不同命名空间同名变量互不影响')
输出结果:
reuse=False,tf.get_variable创建新变量时命名不能重复
reuse=True,tf.get_variable不能创建新变量
不同点1:
s1/v1:0
s1/v2:0
s1_1/v4:0 #由于前后命名空间重名,所以tf.Variable自动处理了命名空间重名
==========================================================================
不同点2:
s2/v5:0
s2/v5_1:0 #同一上下文处理器创建的同名空间同名变量只处理变量重名
s2_1/v5:0 #不同上下文处理器创建的同名空间同名变量只处理命名空间重名
s3/v5:0 #不同命名空间同名变量互不影响