最近笔者想要把网络层写成类,而不是函数,所以需要在各个位置都使用相同的name_scope。然后遇到如果仅仅使用with tf.name_scope
会在不同位置上生成不同的name_scope。稍微搜索了一下找到tensorflow中name_scope
使用的一些细节,记录在此。主要是转载https://stackoverflow.com/questions/45670224/why-the-tf-name-scope-with-same-name-is-different 和 https://github.com/tensorflow/tensorflow/issues/6007中的内容。
例如如下代码:
with tf.name_scope('hha'):
a = tf.zeros(1,name='a')
with tf.name_scope('hha'):
b = tf.zeros(1,name='b')
print(a.name)
print(b.name)
返回值为
hha/a:0
hha_1/b:0
因为tensorflow无法判断是有意在不同位置使用相同的name_scope,而不是两个协作者恰好使用了相同的名字命名不同的name_scope。那tensorflow的做法是对于任意一次调用with tf.name_scope
,都自动生成一个独一无二的name_scope以及其名字。所以上诉代码中的a
和b
所在的name_scope并不相同。
那如何强制使得同一个name_scope在不同位置得以应用,上诉网页中给出了方法:在name_scope后面加上’/’,就会使得tensorflow严格使用给定的name_scope作为名字命名当前片段。例如执行如下代码:
with tf.name_scope('hha'):
a = tf.zeros(1,name='a')
with tf.name_scope('hha/'):
b = tf.zeros(1,name='b')
print(a.name)
print(b.name)
返回值为
hha/a:0
hha/b:0
主要内容都在上诉部分,下面写一下笔者应用上诉方法的场景与结果。
比如说要写一个Dense层,就是一层前向网络,作为一个类,我在初始化的时候声明相应的
W
和__call__
函数里面,这就需要在两个位置使用相同的name_scope了。
进一步,因为Dense层可能会在不同位置上被使用,笔者又希望保留即使不命名,不同位置的Dense层自动使用不同的name_scope这一性质。比如若不对Dense层命名,其自动使用Dense默认值,对于第一层是Dense,而第二层会自动使用Dense_1,第三层会自动使用Dense_2。
为了保留上诉两个性质,笔者使用了tf.name_scope里面__enter__
函数的返回值。即使用如下代码的时候:with tf.name_scope(string) as scope:
,scope
实际上是__enter__
函数的返回值,为tensorflow根据string生成的name_scope的最终命名值。例如:
with tf.name_scope('hha') as s1:
a = tf.zeros(1,name='a')
with tf.name_scope('hha') as s2:
b = tf.zeros(1,name='b')
print(s1)
print(s2)
返回值为
hha/
hha_1/
具体地,在初始化函数__init__
中使用with tf.name_scope(name_scope) as self.name_scope:
新建一个整个类的name_scope。在其他位置上使用with tf.name_scope(self.name_scope):
,即可同时保留上诉两种性能。