tensorflow中的“tf.name_scope()”有什么用?

1. tf.name_scope()命名空间的实际作用

(1)在某个tf.name_scope()指定的区域中定义的所有对象及各种操作,他们的“name”属性上会增加该命名区的区域名,用以区别对象属于哪个区域;
(2)将不同的对象及操作放在由tf.name_scope()指定的区域中,便于在tensorboard中展示清晰的逻辑关系图,这点在复杂关系图中特别重要。

见下例:

import tensorflow as tf;  
tf.reset_default_graph()

# 无tf.name_scope()
a = tf.constant(1,name='my_a') #定义常量
b = tf.Variable(2,name='my_b') #定义变量
c = tf.add(a,b,name='my_add') #二者相加(操作)
print("a.name = "+a.name)
print("b.name = "+b.name)
print("c.name = "+c.name)

# 有tf.name_scope()
# with tf.name_scope('cgx_name_scope'): #定义一块名为cgx_name_scope的区域,并在其中工作
#     a = tf.constant(1,name='my_a')
#     b = tf.Variable(2,name='my_b')
#     c = tf.add(a,b,name='my_add')
# print("a.name = "+a.name)
# print("b.name = "+b.name)
# print("c.name = "+c.name)

# 保存graph用于tensorboard绘图
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    writer = tf.summary.FileWriter("./test",sess.graph)
    print(sess.run(c))
writer.close()
# 输出结果
# 无tf.name_scope()
a.name = my_a:0
b.name = my_b:0
c.name = my_add:0

# 有tf.name_scope()
a.name = cgx_name_scope/my_a:0
b.name = cgx_name_scope/my_b:0
c.name = cgx_name_scope/my_add:0

从输出结果可以看出,在tf.name_scope()下的所有对象和操作,其name属性前都加了cgx_name_scope,用以表示这些内容全在其范围下。
下图展示了两种情况的tensorboard差异,差别一目了然。


tensorflow中的“tf.name_scope()”有什么用?_第1张图片
namescope.jpg

2. name_scope()只决定“对象”属于哪个范围,并不会对“对象”的“作用域”产生任何影响。

tf.name_scope()只是规定了对象和操作属于哪个区域,但这并不意味着他们的作用域也只限于该区域(with的这种写法很容易让人产生这种误会),不要将其和“全局变量、局部变量”的概念搞混淆,两者完全不是一回事。在name_scope中定义的对象,从被定义的位置开始,直到后来某个地方对该对象重新定义,中间任何地方都可以使用该对象。本质上name_scope只对对象的name属性进行圈定,并不会对其作用域产生任何影响。这就好比甲、乙、丙、丁属于陈家,这里“陈家”就是一个name_scope划定的区域,虽然他们只属于陈家,但他们依然可以去全世界的任何地方,并不会只将他们限制在陈家范围。
见下例:
(1)程序首先指定了命名区域cgx_1,并在其中定义了变量a,紧接着case1直接在cgx_1中输出a.name = cgx_1/my_a:0,这很好理解,跟想象的一样;
(2)case2在cgx_1之外的公共区域也输出了相同的a.name,这就说明a的作用范围并没有被限制在cgx_1中
(3)接着程序又新指定了命名区域cgx_2,并在其中执行case3,输出a.name,结果还是和case1和case2完全相同,实际上还是最前面定义的那个a,这更进一步说明name_scope不会对对象的作用域产生影响
(4)★★接着在cgx_2中重新定义了变量“a”,紧接着就执行case4,输出a.name = cgx_2/my_a:0,可见此时的结果与前面三个case就不同了,说明这里新定义的a覆盖了前面的a,即使他们在两个完全独立的name_scope中
(5)case5输出的结果与case4结果相同,这已经无须解释了。

#name_scope 的影响范围
with tf.name_scope('cgx_1'): #指定cgx_1区域
    a = tf.Variable(tf.constant(4),name='my_a') #定义变量a
    print("case1: a.name="+a.name) #cgx_1区域内输出
print("case2: a.name="+a.name) #cgx_1区域外输出

# 保存graph用于tensorboard绘图
with tf.name_scope('cgx_2'): #新指定cgx_2区域
    print("case3: a.name="+a.name) #在cgx_2内输出cgx_1中定义a.name
    a = tf.Variable(tf.constant(4),name='my_a') #★★重新定义a这个变量
    print("case4: a.name="+a.name)
print("case5: a.name="+a.name)
# 输出结果:
case1: a.name = cgx_1/my_a:0
case2: a.name = cgx_1/my_a:0
case3: a.name = cgx_1/my_a:0
case4: a.name = cgx_2/my_a:0
case5: a.name = cgx_2/my_a:0

3. tf.name_scope('cgx_scope')语句重复执行几次,就会生成几个独立的命名空间,尽管表面上看起来都是“cgx_scope”,实际上tensorflow在每一次执行相同语句都会在后面加上“_序数”,加以区别。

见下例:
(1)指定了“cgx_scope”命名区域,并在其中定义变量a;
(2)又指定了相同名称的“cgx_scope”命名区域,并在其中定义变量b;
(3)输出a.name = cgx_scope/my_a:0和b.name = cgx_scope_1/my_b:0,可见b.name已经自动加了“_1”,这是tensorflow的特点,自动检测是否重复,有重复就自动增加数字作为标记

with tf.name_scope('cgx_scope'):
    a = tf.Variable(1,name='my_a')

with tf.name_scope('cgx_scope'):
    b = tf.Variable(2,name='my_b')

c = tf.add(a,b,name='my_add')

print("a.name = "+a.name)
print("b.name = "+b.name)

# 保存graph用于tensorboard绘图程序(同上)
# 输出结果
a.name = cgx_scope/my_a:0
b.name = cgx_scope_1/my_b:0 #自动增加了“_1”

下图进一步说明a和b不在同一个name_scope中


tensorflow中的“tf.name_scope()”有什么用?_第2张图片
相同name_scope.jpg

4. 如何在不同的地方将对象指定到相同的name_scope中?

方法:
with tf.name_scope('cgx_scope') as cgxscope:
……
with tf.name_scope(cgxscope) :
……
见下例:
将前一例程序做简单修改,输出结果a和b都在cgx_scope的命名范围内,后面的tensorboard也说明了这点。

with tf.name_scope('cgx_scope') as cgxscope:
    a = tf.Variable(1,name='my_a')

with tf.name_scope(cgxscope):
    b = tf.Variable(2,name='my_b')

c = tf.add(a,b,name='my_add')

print("a.name = "+a.name)
print("b.name = "+b.name)
# 输出结果
a.name = cgx_scope/my_a:0
b.name = cgx_scope/my_b:0

下图说明此例中a和b位于相同的name_scope中。


tensorflow中的“tf.name_scope()”有什么用?_第3张图片
相同name_scope.jpg

5. 多重name_scope命名空间

多个with tf.name_scope()重叠使用,如下例。

with tf.name_scope('cgx_scope_1'): #第一重命名空间
    with tf.name_scope('cgx_scope_2'): #第二重命名空间
        a = tf.Variable(1,name='my_a')

with tf.name_scope('cgx_scope_3'):
    b = tf.Variable(2,name='my_b')

c = tf.add(a,b,name='my_add')

print("a.name = "+a.name)
print("b.name = "+b.name)
# 输出结果
a.name = cgx_scope_1/cgx_scope_2/my_a:0
b.name = cgx_scope_3/my_b:0
tensorflow中的“tf.name_scope()”有什么用?_第4张图片
多重名命名空间.jpg

6. 常量tf.constant()即使在某个name_scope下被定义,在tensorboard中也不会被绘制到该name_scope下,主要考虑到图像的结构问题。

如下例:
常量a和变量b都定义在cgx_scope下,操作c定义在公共区域。从输出结果看,一切正常。但后面的tensorboard图跟想象的有点区别,按规律my_a和my_b都应该在cgx_scope内,但图中显然没有。猜测,tensorboard中常量通常在水平左侧,形式比较固定,而变量通常在下侧,形式也比较随意,因此把常量和变量画在同一name_scope下对图的逻辑有较大影响。

该例中如果把c = tf.add(a,b,name='my_add')同样写入cgx_scope下,那么在tensorboard中整个过程都会被放入cgx_scope下。

with tf.name_scope('cgx_scope'):
    a = tf.constant(1,name='my_a')
    b = tf.Variable(2,name='my_b')

c = tf.add(a,b,name='my_add')

print("a.name = "+a.name)
print("b.name = "+b.name)
print("c.name = "+c.name)
# 输出结果
a.name = cgx_scope/my_a:0
b.name = cgx_scope/my_b:0
c.name = my_add:0
tensorflow中的“tf.name_scope()”有什么用?_第5张图片
常量一般不显示在name_scope内.jpg

7. tf.name_scope()对由tf.get_variable()产生的变量没有影响

如下例:
在cgx_scope命名空间下,a是由tf.get_variable()生成的变量,b是由tf.Variable()生成的变量,按规律a.name和b.name的前缀都是cgx_scope,但从输出结果可看出,a.name的前缀没出现,说明a不在该命名空间。后面的tensorboard图也说明了这点。出现这种情况是由tf.get_variable()的特性决定的,详见其他文章。

with tf.name_scope('cgx_scope'):
    a = tf.get_variable('my_a',initializer=4)
    b = tf.Variable(2,name='my_b')

c = tf.add(a,b,name='my_add')

print("a.name = "+a.name)
print("b.name = "+b.name)
# 输出结果
a.name = my_a:0
b.name = cgx_scope/my_b:0
tensorflow中的“tf.name_scope()”有什么用?_第6张图片
get_valuable()不受name_scope影响.jpg

你可能感兴趣的:(tensorflow中的“tf.name_scope()”有什么用?)