通俗理解tf.name_scope()、tf.variable_scope()

前言:最近做一个实验,遇到TensorFlow变量作用域问题,对tf.name_scope()、tf.variable_scope()等进行了较为深刻的比较,记录相关笔记:

tf.name_scope()、tf.variable_scope()是两个作用域函数,一般与两个创建/调用变量的函数tf.variable() 和tf.get_variable()搭配使用。常用于:

1)变量共享;2)tensorboard画流程图进行可视化封装变量。

通俗理解就是:tf.name_scope()、tf.variable_scope()会在模型中开辟各自的空间,而其中的变量均在这个空间内进行管理,但是之所以有两个,主要还是有着各自的区别。

1.name_scope 和 variable_scope:

name_scope 和 variable_scope主要用于变量共享。其中,变量共享主要涉及两个函数:tf.variable() 和tf.get_variable();即就是必须要在tf.variable_scope的作用域下使用tf.get_variable()函数。这里用tf.get_variable( ) 而不用tf.Variable( ),是因为前者拥有一个变量检查机制,会检测已经存在的变量是否设置为共享变量,如果已经存在的变量没有设置为共享变量,TensorFlow 运行到第二个拥有相同名字的变量的时候,就会报错。

注意,tf.variable() 和tf.get_variable()有不同的创建变量的方式:tf.Variable() 每次都会新建变量。如果希望重用共享)一些变量,就需要用到了get_variable(),它会去搜索变量名,有就直接用,没有再新建。此外,为了对不同位置或者范围的共享进行区分,就引入名字域。既然用到变量名了,就涉及到了名字域的概念。这就是为什么会有scope 的概念。name_scope 作用域操作,variable_scope 可以通过设置reuse 标志以及初始化方式来影响域下的变量,因为想要达到变量共享的效果, 就要在 tf.variable_scope()的作用域下使用 tf.get_variable() 这种方式产生和提取变量. 不像 tf.Variable() 每次都会产生新的变量, tf.get_variable() 如果遇到了已经存在名字的变量时, 它会单纯的提取这个同样名字的变量,如果不存在名字的变量再创建.

例如:

with tf.variable_scope('V1',reuse=False):  
    a1 = tf.get_variable(name='a1', shape=[1], initializer=tf.constant_initializer(1))  
    a2 = tf.Variable(tf.random_normal(shape=[2,3], mean=0, stddev=1), name='a2')  
with tf.variable_scope('V2',reuse=True):  
    a3 = tf.get_variable(name='a1', shape=[1],initializer=tf.constant_initializer(1))  
    a4 = tf.Variable(tf.random_normal(shape=[2,3], mean=0, stddev=1), name='a2')  
    
with tf.Session() as sess:  
    sess.run(tf.initialize_all_variables())  
    print (a1.name)  
    print (a2.name)   
    print (a3.name)   
    print (a4.name)

输出:

V1/a1:0
V1_14/a2:0
V2/a1:0
V2_2/a2:0  在tf.name_scope()中则没有resuse这个参数,无法实现这种操作。

2.name scope和variable scope区别

TF中有两种作用域类型:命名域 (name scope),通过tf.name_scope 或 tf.op_scope创建;
变量域 (variable scope),通过tf.variable_scope 或 tf.variable_op_scope创建;
这两种作用域,对于使用tf.Variable()方式创建的变量,具有相同的效果,都会在变量名称前面,加上域名称。对于通过tf.get_variable()方式创建的变量,只有variable scope名称会加到变量名称前面,而name scope不会作为前缀。

举例1:

with tf.name_scope("my_name_scope"):
    v1 = tf.get_variable("var1", [1], dtype=tf.float32) 
    v2 = tf.Variable(1, name="var2", dtype=tf.float32)
    a = tf.add(v1, v2)
    print(v1.name)
    print(v2.name) 
    print(a.name)

输出:

var1:0
my_name_scope/var2:0
my_name_scope/Add:0

举例2:

with tf.variable_scope("my_variable_scope"):
    v1 = tf.get_variable("var1", [1], dtype=tf.float32)
    v2 = tf.Variable(1, name="var2", dtype=tf.float32)
    a = tf.add(v1, v2)
    print(v1.name) 
    print(v2.name)
    print(a.name)

输出:

my_variable_scope/var1:0
my_variable_scope/var2:0
my_variable_scope/Add:0

总结:

1、name_scope不会作为tf.get_variable变量的前缀,但是会作为tf.Variable的前缀。(举例1)

2、在variable_scope的作用域下,tf.get_variable()和tf.Variable()都加了scope_name前缀。因此,在tf.variable_scope的作用域下,通过get_variable()可以使用已经创建的变量,实现了变量的共享,即可以通过get_variable()在tf.variable_scope设定的作用域范围内进行变量共享。(举例2)

3、在重复使用的时候, 一定要在代码中强调 scope.reuse_variables()

 

参考链接:

[1] scope 命名方法 - Tensorflow | 莫烦Python

[2] tf.name_scope()和tf.variable_scope() - AI-FUTURE - CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值