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差异,差别一目了然。


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中


相同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中。


相同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
多重名命名空间.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
常量一般不显示在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
get_valuable()不受name_scope影响.jpg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容