Tensorflow:name_scope和variable_scope的区别

tf.name_scope()和tf.variable_scope()是两个作用域,一般与两个创建/调用变量的函数tf.variable() 和tf.get_variable()搭配使用。它们搭配在一起的两个常见用途:1)变量共享
为什么要共享变量?举个简单的例子:例如,当我们研究生成对抗网络GAN的时候,判别器的任务是如果接收到的是生成器生成的图像,判别器就尝试优化自己的网络结构来使自己输出0,如果接收到的是来自真实数据的图像,那么就尝试优化自己的网络结构来使自己输出1。也就是说,生成图像和真实图像经过判别器的时候,要共享同一套变量,所以TensorFlow引入了变量共享机制。

“共享变量” 的应用场景:RNN应用例子
在tf.variable_scope的作用域下,通过get_variable()使用已经创建的变量,实现了变量的共享。在 train RNN 和 test RNN 的时候, RNN 的 time_steps 会有不同的取值, 这将会影响到整个 RNN 的结构, 所以导致在 test 的时候, 不能单纯地使用 train 时建立的那个 RNN. 但是 train RNN 和 test RNN 又必须是有同样的 weights biases 的参数. 所以, 这时, 就是使用 reuse variable 的好时机.
 

 

首先介绍两个创建variable的方法

tf.Variable(initial_value, name, dtype, trainable, collection)
tf.get_variable(name, shape, dtype, initializer, trainable, collection)

其中,tf.Variable每次调用都会创建一个新的变量,如果变量名字相同,就在后面加N:

first_a = tf.Variable(name='a', initial_value=1, dtype=tf.int32)
second_a = tf.Variable(name='a', initial_value=1, dtype=tf.int32)
sess = tf.Session()
sess.run(tf.global_variables_initializer())

print(first_a.name)  # a_1:0
print(second_a.name)  # a_2:0

而,tf.get_variable的做法是,如果这个变量名字已经存在了,就拿这个变量,不再创建新的变量。
但是需要注意的是,一定要在scope中,使用reuse这个选项,如下是错误的

first_a = tf.get_variable(name='a', shape=(1), initializer=tf.zeros_initializer, dtype=tf.int32)

 

不使用reuse是不能get_variable相同名字的变量的;而使用resue又只能在variable_scope中:

with tf.variable_scope('var_scope') as scope:
    v = tf.get_variable(name='v', shape=[1], initializer=tf.zeros_initializer)
with tf.variable_scope(scope, reuse=True):
    v1 = tf.get_variable(name='v', shape=[1], initializer=tf.zeros_initializer)
sess = tf.Session()
sess.run(tf.global_variables_initializer())

assert v == v1
print(v.name)   #var_scope/v:0
print(v1.name)  #var_scope/v:0

tf.name_scope中

tf.get_variable不起作用,只对tf.Variable起作用

with tf.name_scope("my_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)  # var1:0
print(v2.name)  # my_scope/var2:0
print(a.name)   # my_scope/Add:0

tf.variable_scope中

tf.get_variabletf.Variable都起作用

with tf.variable_scope("my_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)  # my_scope/var1:0
print(v2.name)  # my_scope/var2:0
print(a.name)   # my_scope/Add:0

这种机制允许在不用的name_scope中使用tf.get_variable来share变量,但是需要注意的是,一定要声明reuse:

with tf.name_scope("foo"):
    with tf.variable_scope("var_scope"):
        v = tf.get_variable("var", [1])
with tf.name_scope("bar"):
    with tf.variable_scope("var_scope", reuse=True):
        v1 = tf.get_variable("var", [1])
assert v1 == v
print(v.name)   # var_scope/var:0
print(v1.name)  # var_scope/var:0****

II. 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不会作为前缀。例如 print(v1.name) # var1:0
例子:

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) # var1:0

print(v2.name) # my_name_scope/var2:0

print(a.name) # my_name_scope/Add:0

小结:name_scope不会作为tf.get_variable变量的前缀,但是会作为tf.Variable的前缀。

例子:

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) # my_variable_scope/var1:0

print(v2.name) # my_variable_scope/var2:0

print(a.name) # my_variable_scope/Add:0

小结:在variable_scope的作用域下,tf.get_variable()和tf.Variable()都加了scope_name前缀。因此,在tf.variable_scope的作用域下,通过get_variable()可以使用已经创建的变量,实现了变量的共享。


作者:刘小米92
链接:https://www.imooc.com/article/22966
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作

作者:kelseyh
链接:https://www.jianshu.com/p/ce44b403c468
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值