tf.name_scope() 和 tf.variable_scope() 的用法和玄机
2019独角兽企业重金招聘Python工程师标准>>>
一. name_scope 和 variable_scope的用途
用途1: 共享变量
TensorFlow (TF) 中,name_scope 和 variable_scope 主要是因为 变量共享 的需求。为什么要共享变量?举个简单的例子:例如,当我们研究生成对抗网络GAN的时候,判别器的任务是如果接收到的是生成器生成的图像,判别器就尝试优化自己的网络结构来使自己输出0,如果接收到的是来自真实数据的图像,那么就尝试优化自己的网络结构来使自己输出1。也就是说,生成图像和真实图像经过判别器的时候,要共享同一套变量,所以TensorFlow引入了变量共享机制。
变量共享主要涉及两个函数:
- tf.get_variable(<name>, <shape>, <initializer>)
- tf.variable_scope(<scope_name>)
即就是必须要在tf.variable_scope的作用域下使用tf.get_variable()函数。这里用tf.get_variable( ) 而不用tf.Variable( ),是因为前者拥有一个变量检查机制,会检测已经存在的变量是否设置为共享变量,如果已经存在的变量没有设置为共享变量,TensorFlow 运行到第二个拥有相同名字的变量的时候,就会报错(详见本文的RNN应用例子章节)。
- 两个创建变量的方式。如果使用tf.Variable() 的话每次都会新建变量。但是大多数时候我们是希望重用一些变量,所以就用到了get_variable(),它会去搜索变量名,有就直接用,没有再新建。
- 名字域。既然用到变量名了,就涉及到了名字域的概念。通过不同的域来区别变量名,毕竟让我们给所有变量都取不同名字还是很辛苦。
- 这就是为什么会有scope 的概念。name_scope 作用于操作,variable_scope 可以通过设置reuse 标志以及初始化方式来影响域下的变量。
“共享变量” 的应用场景: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 的好时机.
例子:首先定义train 和 test 的不同参数.
class TrainConfig:batch_size = 20time_steps = 20input_size = 10output_size = 2cell_size = 11learning_rate = 0.01class TestConfig(TrainConfig):time_steps = 1train_config = TrainConfig()
test_config = TestConfig()
然后让 train_rnn
和 test_rnn
在同一个 tf.variable_scope('rnn')
之下.
并且定义 scope.reuse_variables()
, 使我们能把 train_rnn
的所有 weights, biases 参数全部绑定到 test_rnn
中.
这样, 不管两者的 time_steps
有多不同, 结构有多不同, train_rnn
W, b 参数更新成什么样, test_rnn
的参数也更新成什么样.
with tf.variable_scope('rnn') as scope:sess = tf.Session()train_rnn = RNN(train_config)scope.reuse_variables()test_rnn = RNN(test_config)sess.run(tf.global_variables_initializer())
RNN 例子的完整代码可以看这里.
因为想要达到变量共享的效果, 就要在 tf.variable_scope()
的作用域下使用 tf.get_variable()
这种方式产生和提取变量. 不像 tf.Variable()
每次都会产生新的变量, tf.get_variable()
如果遇到了已经存在名字的变量时, 它会单纯的提取这个同样名字的变量,如果不存在名字的变量再创建.
但在重复使用的时候, 一定要在代码中强调 scope.reuse_variables()
,如下面代码所示,否则系统将会报错, 以为你是不小心重复使用到了一个变量.
with tf.variable_scope("a_variable_scope") as scope:initializer = tf.constant_initializer(value=3)var3 = tf.get_variable(name='var3', shape=[1], dtype=tf.float32, initializer=initializer)scope.reuse_variables()var3_reuse = tf.get_variable(name='var3',) # var3_reusevar4 = tf.Variable(name='var4', initial_value=[4], dtype=tf.float32)var4_reuse = tf.Variable(name='var4', initial_value=[4], dtype=tf.float32) # var4_reusewith tf.Session() as sess:sess.run(tf.global_variables_initializer())print(var3.name) # a_variable_scope/var3:0print(sess.run(var3)) # [ 3.]print(var3_reuse.name) # a_variable_scope/var3:0print(sess.run(var3_reuse)) # [ 3.]print(var4.name) # a_variable_scope/var4:0print(sess.run(var4)) # [ 4.]print(var4_reuse.name) # a_variable_scope/var4_1:0print(sess.run(var4_reuse)) # [ 4.]
不强调reuse_variables()而报错的例子:
如果把 tf.Variable 改成 tf.get_variable,直接调用两次,就会报错:
result1 = my_image_filter(image1) result2 = my_image_filter(image2) # Raises ValueError(... conv1/weights already exists ...)
为了解决这个问题,TF提出了 tf.variable_scope 函数:它的主要作用是,在一个 variable_scope 作用域下内共享一些变量。实现方式可以有如下几种用法:
1)
with tf.variable_scope("image_filters") as scope:result1 = my_image_filter(image1)scope.reuse_variables() # or #tf.get_variable_scope().reuse_variables()result2 = my_image_filter(image2)
2)
with tf.variable_scope("image_filters1") as scope1:result1 = my_image_filter(image1) with tf.variable_scope(scope1, reuse = True)result2 = my_image_filter(image2)
注意最好不要采用的方式:设置 reuse 标识为 False,然后在需要的时候设置 reuse 标识为 True。
可视化用途:画tensorboard流程图时封装
当然对我们而言name_scope还有个更直观的用处就是:在tensorboard 里可视化的时候用name_scope进行封装后会更清晰. 通常情况下,tf.variable_scope 和 tf.name_scope 配合,能画出非常漂亮的tensorboard流程图,但是他们两个之间又有着细微的差别,那就是 name_scope 只能管住操作 Ops 的名字,而管不住变量 Variables 的名字,看下例:
with tf.variable_scope("foo"):with tf.name_scope("bar"):v = tf.get_variable("v", [1])x = 1.0 + v assert v.name == "foo/v:0" assert x.op.name == "foo/bar/add"
参考:https://www.zhihu.com/question/54513728/answer/177901159
Tensorflow变量共享,参考:http://www.cnblogs.com/Charles-Wan/p/6200446.html
参考:http://sentiment-mining.blogspot.com/2016/12/tensorflow-name-scope-variable-scope.html
参考:https://morvanzhou.github.io/tutorials/machine-learning/tensorflow/5-12-scope/
二. TensorFlow中name scope和variable scope区别
为了在代码的任何部分可以使用某一个已经创建的变量,TF引入了变量共享机制共享变量,而不是传一个变量的引用。
I. TF中创建变量的方式有两种:tf.get_variable()和tf.Variable()
- tf.get_variable(“vname”)方法,在创建变量时,如果这个变量vname已经存在,直接使用这个变量,如果不存在,则重新创建;
- tf.Variable()在创建变量时,一律创建新的变量,如果这个变量已存在,则后缀会增加0、1、2等数字编号予以区别。
例子:在 tf.name_scope()
的框架下使用这两种方式, 结果如下.
import tensorflow as tfwith tf.name_scope("a_name_scope"):initializer = tf.constant_initializer(value=1)var1 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32, initializer=initializer)var2 = tf.Variable(name='var2', initial_value=[2], dtype=tf.float32)var21 = tf.Variable(name='var2', initial_value=[2.1], dtype=tf.float32)var22 = tf.Variable(name='var2', initial_value=[2.2], dtype=tf.float32)with tf.Session() as sess:sess.run(tf.initialize_all_variables())print(var1.name) # var1:0print(sess.run(var1)) # [ 1.]print(var2.name) # a_name_scope/var2:0print(sess.run(var2)) # [ 2.]print(var21.name) # a_name_scope/var2_1:0print(sess.run(var21)) # [ 2.0999999]print(var22.name) # a_name_scope/var2_2:0print(sess.run(var22)) # [ 2.20000005]
可以看出使用 tf.Variable()
定义变量的时候, 虽然var2, var21, var22的 name
一样, 但是为了不重复变量名, Tensorflow 为它们做了附加的区分,因为输出的变量名是不一样的. 所以, 本质上tensorflow令 var2
, var21
, var22
成为不一样的变量.
这样做的目的是,搭配上不同的作用域类型,可以实现变量共享机制。
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()可以使用已经创建的变量,实现了变量的共享。
转载于:https://my.oschina.net/liusicong/blog/1593467
tf.name_scope() 和 tf.variable_scope() 的用法和玄机相关推荐
- 通俗理解tf.name_scope()、tf.variable_scope()
前言:最近做一个实验,遇到TensorFlow变量作用域问题,对tf.name_scope().tf.variable_scope()等进行了较为深刻的比较,记录相关笔记: tf.name_scope ...
- tf.variable和tf.get_Variable以及tf.name_scope和tf.variable_scope的区别
在训练深度网络时,为了减少需要训练参数的个数(比如具有simase结构的LSTM模型).或是多机多卡并行化训练大数据大模型(比如数据并行化)等情况时,往往需要共享变量.另外一方面是当一个深度学习模型变 ...
- tf.name_scope()与tf.variable_scope()
TensorFlow的tf.name_scope().tf.variable_scope()是两个作用域函数,一般与两个创建/调用变量的函数tf.variable() 和tf.get_variable ...
- tf.name_scope与tf.variable_scope用法区别
转自:https://blog.csdn.net/daizongxue/article/details/84284007 本文由网络上一些回答和博文汇总而成. 要将这个问题解释清楚,得结合tensor ...
- tf.Variable() 和 tf.get_variable(),tf.name_scope() 和 tf.variable_scope()
在gpu并行训练网络时,往往需要共享已创建的变量,tensorflow中为了使这些变量名和操作名唯一并且不重复,用了几个函数来应对这种情况.于是就有了tf.Variable(), tf.get_var ...
- tensorflow 变量及命名空间 tf.Variable() vs tf.get_variable() tf.name_scope() vs tf.variable_scope()
tf.Variable() vs tf.get_variable() tf.name_scope() vs tf.variable_scope() 1. 基础功能 1.1 tf.Variable() ...
- tf.name_scope与tf.variable_scope
1.scope(作用域) 在TensorFlow中有两个作用域 (scope),一个是variable_scope,另一个是name_scope.它们究竟有什么区别呢?简而言之,variable_ ...
- TensorFlow 学习(一)—— tf.get_variable() vs tf.Variable(),tf.name_scope() vs tf.variable_scope()
scope 命名方法 对于一个复杂的 tensorflow 模型会有很多个变量, tf.variable_scope() :提供了简单的命名空间技术以避免冲突: tf.get_variable():从 ...
- tf.name_scope()和tf.variable_scope()
https://blog.csdn.net/gqixf/article/details/80191918 https://blog.csdn.net/uestc_c2_403/article/deta ...
最新文章
- python导入csv文件-jupyter 导入csv文件方式
- 若格式化都无效 如何清除”不可杀“病毒?
- unity 实现调用Windows窗口/对话框交互
- oracle可以在liux上装_【Oracle】手把手教你做之Linux上安装Oracle11g
- JAVA虚拟机运行数据区
- jenkins的历史
- linux5 vnc,CentOS 5 下安装配置VNC
- SpringBoot | 第十章:Swagger2的集成和使用
- bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集
- 计算机机房需求调查表,机房建设需求调查表机房建设需求调查表.doc
- 【数学模型】基于Matlab实现洪水调度运算
- COMSOL案例内容,有需要的了解下!
- NewWebPick 11下載
- c++ 取模和求余运算
- ogg是什么文件?ogg怎么转mp3格式?
- 解决uni-app uniCloud小程序预览没有数据
- 支持向量机 SVM 算法推导优缺点 代码实现 in Python
- 端到端OCR-ABCNet论文笔记
- SII9136 调试出来, 欣喜若狂!(需要 SII9136 资料的请联系我!)
- 2022-2027年中国紫苏行业市场全景评估及发展战略规划报告
热门文章
- 数据驱动的未来城市八大趋势
- 她取代马斯克成特斯拉新董事长 究竟什么来头?
- 五问智能教育未来发展:重点解决什么问题?
- 互联网如何“升级”制造业?《“人工智能+制造”产业发展研究报告》发布
- 为什么我们总认为开源不挣钱?
- 隐藏十年竟无人发现!Sudo 漏洞被曝出:无需密码就能获取 root 权限
- 我给 Apache 顶级项目提了个 Bug
- 科技股疯狂造富的背后,“泡沫”离我们到底有多远?
- @程序员,什么键盘最耐用?| 每日趣闻
- volatile关键字的作用、原理