【转载】 TensorFlow之name_scope/variable_scope
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013745804/article/details/80428618
————————————————
引子
前面写过一篇博文《TensorFlow学习笔记(六)》,其内容主要介绍的就是name_scope/variable_scope的使用,不过并没有明确地对这二者的使用场景进行区分,所以本文将清晰地给出name_scope / variable_scope的应用场景。
文章比较长,如果时间不够的话,那就直接看总结啦~
主要用法
我们知道,在TensorFlow中,常常会定义一堆节点,如果我们不能对此进行有效地管理,那么这些节点很可能会使我们心如乱麻,并且再也不想看这些杂乱的代码。
name_scope / variable_scope 正是为了更有效地管理节点而产生的两个操作(op)。
- name_scope:用于对变量设置命名域,从而让变量按照其关系组成一个个scope,并不会对tf.get_variable()创建的变量名字产生影响;
- variable_scope:绝大部分情形下,与tf.get_variable()配合使用,实现变量共享。
示例
我们下面举几个简单的例子:
a)利用name_scope对tf.Variable创建的变量加上命名域:
with tf.name_scope("scope_1"):
v1 = tf.Variable([1], name="v1", dtype=tf.float32)
v2 = tf.get_variable("v2", [1])
print v1
print v2
此时输出结果为:
<tf.Variable 'scope_1/v1:0' shape=(1,), dtype=float32_ref>
<tf.Variable 'v2:0' shape=(1,) dtype=float32_ref>
从这里我们可以得出下列结论:
- name_scope并不会对 tf.get_variable() 创建的变量添加命名域;
- name_scope并不能用于实现变量共享。
b)结合使用variable_scope与tf.get_variable()实现变量共享:
实验一
with tf.variable_scope("scope_1"):
v1 = tf.Variable([1], name="v1", dtype=tf.float32)
with tf.variable_scope("scope_1"):
v2 = tf.Variable([1], name="v1", dtype=tf.float32)
此时的输出结果为:
<tf.Variable 'scope_1/v1:0' shape=(1,), dtype=float32_ref>
<tf.Variable 'scope_1_1/v1:0' shape=(1,), dtype=float32_ref>
这个实验说明了tf.Variable()遇到重名变量时,将自动重命名,而不会发生冲突。在这个实验中,我们是在同一个scope中定义的同名变量,可是为什么不是修改最内层的变量名呢?也即为什么输出结果不是下面这样呢?
<tf.Variable 'scope_1/v1:0' shape=(1,), dtype=float32_ref>
<tf.Variable 'scope_1/v1_1:0' shape=(1,), dtype=float32_ref>
这是TensorFlow的一种很巧妙的手段,因为tf.Variable()被设计为提供给库编写者使用的一个接口,所以我们修改scope的话更加有利。为什么这么说?比如,我们运行下面的代码:
net = fully_connected(input_tensor, shape)
net = fully_connected(net, shape)
这个时候我们对fully_connected()函数的两次调用均没有给出scope,那这个时候我们的全连接层中的变量应该如何命名呢?这就与上面的实验情形类似了,TFLearn的fully_connected()函数是使用tf.Variable()实现的,所以一般情况下,将会使用默认的“FullyConnected”这一scope作为命名域,当我们第二次调用fully_connected()函数时,自动改变命名域为“FullyConnected_1”,而不是修改命名域内部的变量名,是不是比直接改最内层的变量名要合理许多?
那如果我们改变最内层的变量名,假设我们的函数fn()在scope中定义了“scope/v1, scope/v2”,那么,我们接下来将重命名为“scope/v1_1, scope/v2_1”,这样的话,那不是都在同一个scope中了么?到时候在TensorBoard中将显得乱七八糟~
对了,tf.Variable()在解决冲突时,总是重命名最外层的scope哟~验证如下:
with tf.variable_scope("scope_top"):
with tf.variable_scope("scope_bot"):
v1 = tf.Variable([1], name="v1", dtype=tf.float32)
with tf.variable_scope("scope_top"):
with tf.variable_scope("scope_bot"):
v2 = tf.Variable([1], name="v1", dtype=tf.float32)
vs=tf.trainable_variables()
for v in vs:
print v
此时,我们的输出为:
<tf.Variable 'scope_top/scope_bot/v1:0' shape=(1,), dtype=float32_ref>
<tf.Variable 'scope_top_1/scope_bot/v1:0' shape=(1,), dtype=float32_ref>
这样的话,如果我们调用一些基本的Layers来定义自己的Layer,比如说叫做layer_udef,且默认命名域为“Layer_Udef”,那么重复使用layer_udef时,得到的是“Layer_Udef”、“Layer_Udef_1”…这就很符合我们的预期咯。
实验二
在实验一中,我们发现使用tf.Variable()并不能获取已经定义变量,换句话说,不能达到共享变量的目的,那我们能否用tf.get_variable()函数获取tf.Variable()定义的变量呢?
with tf.variable_scope("scope_1"):
v1 = tf.Variable([1], name="v1", dtype=tf.float32)
print v1
with tf.variable_scope("scope_1", reuse=True):
v2 = tf.get_variable("v1", [1])
输出为:
<tf.Variable 'scope_1/v1:0' shape=(1,) dtype=float32_ref>
...
ValueError: Variable scope_1/v1 does not exist, or was not created with tf.get_variable().
相信大家都有疑惑,不是已经有了scope_1/v1变量么?为什么说它不存在呢?因为tf.Variable()所定义的变量并不是用于共享的,虽然它对于tf.get_variable()是可见的:
with tf.variable_scope("scope_1"):
v1 = tf.Variable([1], name="v1", dtype=tf.float32)
with tf.variable_scope("scope_1"):
v2 = tf.get_variable("v1", [1])
此时输出为:
<tf.Variable 'scope_1/v1:0' shape=(1,) dtype=float32_ref>
<tf.Variable 'scope_1/v1_1:0' shape=(1,) dtype=float32_ref>
那到底为什么tf.Variable()定义的变量不能共享呢?
这就涉及到tf.Variable()和tf.get_variable()的设计理念了:个人认为,tf.Variable()主要是为库的编写者设计,或者,我们可以用它来编写自己的需要重复定义的Layers,这样就不用操心变量之间的冲突了,这一点我们在实验一中已经说明过了。所以,当我们想要从最底层开始定义自己的层时,使用tf.Variable()吧~
实验三
说了这么多,那到底怎样才能成功地共享变量呢?
with tf.variable_scope("scope_1"):
v1 = tf.get_variable("v1", [1])
with tf.variable_scope("scope_1", reuse=True):
v2 = tf.get_variable("v1", [1])
vs = tf.trainable_variables()
for v in vs:
print v
此时我们的输出为:
<tf.Variable 'scope_1/v1:0' shape=(1,) dtype=float32_ref>
也就是说,变量“scope_1/v1”被共享咯~
总结
现将本文总结如下:
name_scope并不会对tf.get_variable()定义的变量的命名产生影响;
如果要从底层变量开始定义库函数的话,使用tf.Variable()是一种较好的选择;
tf.Variable()定义的变量并不能被共享;
如果想要实现变量共享,那就同时使用variable_scope和tf.get_variable()吧~
【转载】 TensorFlow之name_scope/variable_scope的更多相关文章
- tensorflow里面共享变量、name_scope, variable_scope等如何理解
tensorflow里面共享变量.name_scope, variable_scope等如何理解 name_scope, variable_scope目的:1 减少训练参数的个数. 2 区别同名变量 ...
- Tensorflow函数——tf.variable_scope()
Tensorflow函数——tf.variable_scope()详解 https://blog.csdn.net/yuan0061/article/details/80576703 2018年06月 ...
- tensorflow中的name_scope, variable_scope
在训练深度网络时,为了减少需要训练参数的个数(比如LSTM模型),或者是多机多卡并行化训练大数据.大模型等情况时,往往就需要共享变量.另外一方面是当一个深度学习模型变得非常复杂的时候,往往存在大量的变 ...
- tensorflow 中 name_scope 及 variable_scope 的异同
Let's begin by a short introduction to variable sharing. It is a mechanism in TensorFlow that allows ...
- tensorflow 中 name_scope和variable_scope
import tensorflow as tf with tf.name_scope("hello") as name_scope: arr1 = tf.get_variable( ...
- Tensorflow 之 name/variable_scope 变量管理
name/variable_scope 的作用 充分理解 name / variable_scope TensorFlow 入门笔记 当一个神经网络比较复杂.参数比较多时,就比较需要一个比较好的方式来 ...
- [转载]Tensorflow 的reduce_sum()函数的axis,keep_dim这些参数到底是什么意思?
转载链接:https://www.zhihu.com/question/51325408/answer/125426642来源:知乎 这个问题无外乎有三个难点: 什么是sum 什么是reduce 什么 ...
- [图解tensorflow源码] [转载] tensorflow设备内存分配算法解析 (BFC算法)
转载自 http://weibo.com/p/1001603980563068394770 @ICT_吴林阳 tensorflow设备内存管理模块实现了一个best-fit with coales ...
- [转载]tensorflow中使用tf.ConfigProto()配置Session运行参数&&GPU设备指定
tf.ConfigProto()函数用在创建session的时候,用来对session进行参数配置: config = tf.ConfigProto(allow_soft_placement=True ...
- [转载]Tensorflow中reduction_indices 的用法
Tensorflow中reduction_indices 的用法 默认时None 压缩成一维
随机推荐
- The solution of ABC144F
都不知道什么时候做的题了 problem & blog 一开始很容易想到枚举断边然后 DP 算代价. 于是很容易想到 DP 状态定义:设 \(dp_u\) 为从 \(u\) 出发到 \(n\) ...
- LidarView工程搭建指南
前言 笔者做过一段时间的车载LiDAR开发,对LidarView开源项目进行过深度定制,摸索了一套LidarView软件的开发和调试方法 1 软件安装 1.1 安装准备 以Windows10系统平台为 ...
- 在线RSA签名工具
在线RSA签名工具支持多种RSA签名算法,包括RSA-MD5.RSA-SHA1.RSA-SHA224.RSA-SHA256.RSA-SHA384和RSA-SHA512.用户只需上传需要签名的数据和私钥 ...
- java堆和栈有哪些区别
java堆和栈有哪些区别 Java堆和栈是Java虚拟机(JVM)中的两个重要概念,它们在内存管理.存储对象和执行线程等方面有明显的区别. 1.内存分配和管理Java堆是动态分配的内存区域,主要用来存 ...
- CentOS7学习笔记(三) 用户和用户组管理
用户管理 Linux中root用户是权限最大的用户,一般情况下只有服务器管理员拥有root用户的使用权,而我们会使用其他用户来连接Linux 创建用户的命令 创建用户的命令是useradd name, ...
- python + pytest多进程、多线程执行用例生成报告总结
背景: 使用多进程.多线程执行测试用例,生成测试报告:不使用多进程.多线程,以下两种方式都可生成报告 两种生成报告的形式 1. pytestreport(pytest_session_finish时生 ...
- C#中关于 object,dynamic 一点使用心得
首先说一下使用场景 WebAPI接口入参使用 object和 dynamic 后续解析和处理 1.object和dynamic 区别 在.NET中,object和dynamic也有一些区别: obj ...
- day01小程序快速入门
这几天正式开始微信小程序的修炼了,就目前而言来看简直就是vue和react的结合体,所以在学小程序前,先把框架熟悉还是挺有用的. 一.简介 1.1与普通网页区别 二.第一个小程序 需要注册小程序开发账 ...
- 基于SSD202D芯片的最小嵌入式Linux开发板来了 仅需99元 入门嵌入式Linux必选
- HTTP常见的状态码?
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息 200 OK 正常返回信息 201 Created 请求 ...