TensorFlow 变量共享,命名空间
前言: 本例子主要介绍 name_scope 和 variable_scope 的正确使用方式,学习并理解本例之后,你就能够真正读懂 TensorFlow 的很多代码并能够清晰地理解模型结构了
* 起因:在运行 RNN LSTM 实例代码的时候出现 ValueError。 *
在 TensorFlow 中,经常会看到这 name_scope 和 variable_scope 两个东东出现,这到底是什么鬼,到底系做咩噶!!! 在做 LSTM 的时候遇到了下面的错误:
ValueError: Variable rnn/basic_lstm_cell/weights already exists, disallowed.
然后谷歌百度都查了一遍,结果也不知是咋回事。我是在 jupyter notebook 运行的示例程序,第一次运行的时候没错,然后就总是出现上面的错误。后来才知道是 get_variable() 和 variable_scope() 搞的鬼。
=========================================================
1. 先说结论
![]() |
![]() |
fig1. 引入命名空间之前 | fig2. 引入命名空间之后 |
为了解决这个问题,我们引入了 name_scope 和 variable_scope, 二者又分别承担着不同的责任:
- * name_scope: * 为了更好地管理变量的命名空间而提出的。比如在 tensorboard 中,因为引入了 name_scope, 我们的 Graph 看起来才井然有序。
- * variable_scope: * 大大大部分情况下,跟 tf.get_variable() 配合使用,实现变量共享的功能。
2. (实验一)三种方式创建变量: tf.placeholder, tf.Variable, tf.get_variable
2.1 实验目的:探索三种方式定义的变量之间的区别
import tensorflow as tf
# 设置GPU按需增长
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
# 1.placeholder
v1 = tf.placeholder(tf.float32, shape=[2,3,4])
print v1.name
v1 = tf.placeholder(tf.float32, shape=[2,3,4], name='ph')
print v1.name
v1 = tf.placeholder(tf.float32, shape=[2,3,4], name='ph')
print v1.name
print type(v1)
print v1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Placeholder:0
ph:0
ph_1:0
<class 'tensorflow.python.framework.ops.Tensor'>
Tensor("ph_1:0", shape=(2, 3, 4), dtype=float32)
# 2. tf.Variable()
v2 = tf.Variable([1,2], dtype=tf.float32)
print v2.name
v2 = tf.Variable([1,2], dtype=tf.float32, name='V')
print v2.name
v2 = tf.Variable([1,2], dtype=tf.float32, name='V')
print v2.name
print type(v2)
print v2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Variable:0
V:0
V_1:0
<class 'tensorflow.python.ops.variables.Variable'>
Tensor("V_1/read:0", shape=(2,), dtype=float32)
# 3.tf.get_variable() 创建变量的时候必须要提供 name
v3 = tf.get_variable(name='gv', shape=[])
print v3.name
v4 = tf.get_variable(name='gv', shape=[2])
print v4.name
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
gv:0
---------------------------------------------------------------------------ValueError Traceback (most recent call last)<ipython-input-7-29efaac2d76c> in <module>()2 v3 = tf.get_variable(name='gv', shape=[])3 print v3.name
----> 4 v4 = tf.get_variable(name='gv', shape=[2])5 print v4.name
此处还有一堆错误信息。。。
ValueError: Variable gv already exists, disallowed. Did you mean to set reuse=True in VarScope? Originally defined at:
...
print type(v3)
print v3
- 1
- 2
- 1
- 2
<class 'tensorflow.python.ops.variables.Variable'>
Tensor("gv/read:0", shape=(), dtype=float32)
还记得有这么个函数吗? tf.trainable_variables(), 它能够将我们定义的所有的 trainable=True 的所有变量以一个list的形式返回。 very good, 现在要派上用场了。
vs = tf.trainable_variables()
print len(vs)
for v in vs:print v
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
4
Tensor("Variable/read:0", shape=(2,), dtype=float32)
Tensor("V/read:0", shape=(2,), dtype=float32)
Tensor("V_1/read:0", shape=(2,), dtype=float32)
Tensor("gv/read:0", shape=(), dtype=float32)
2.2 实验1结论
从上面的实验结果来看,这三种方式所定义的变量具有相同的类型。而且只有 tf.get_variable() 创建的变量之间会发生命名冲突。在实际使用中,三种创建变量方式的用途也是分工非常明确的。其中
- tf.placeholder() 占位符。* trainable==False *
- tf.Variable() 一般变量用这种方式定义。 * 可以选择 trainable 类型 *
- tf.get_variable() 一般都是和 tf.variable_scope() 配合使用,从而实现变量共享的功能。* trainable == True*
3. (实验二) 探索 name_scope 和 variable_scope
3.1 实验二目的:熟悉两种命名空间的应用情景。
import tensorflow as tf
# 设置GPU按需增长
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
with tf.name_scope('nsc1'):v1 = tf.Variable([1], name='v1')with tf.variable_scope('vsc1'):v2 = tf.Variable([1], name='v2')v3 = tf.get_variable(name='v3', shape=[])
print 'v1.name: ', v1.name
print 'v2.name: ', v2.name
print 'v3.name: ', v3.name
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
v1.name: nsc1/v1:0
v2.name: nsc1/vsc1/v2:0
v3.name: vsc1/v3:0
with tf.name_scope('nsc1'):v4 = tf.Variable([1], name='v4')
print 'v4.name: ', v4.name
- 1
- 2
- 3
- 1
- 2
- 3
v4.name: nsc1_1/v4:0
tf.name_scope() 并不会对 tf.get_variable() 创建的变量有任何影响。
tf.name_scope() 主要是用来管理命名空间的,这样子让我们的整个模型更加有条理。而 tf.variable_scope() 的作用是为了实现变量共享,它和 tf.get_variable() 来完成变量共享的功能。
1.第一组,用 tf.Variable() 的方式来定义。
import tensorflow as tf
# 设置GPU按需增长
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)# 拿官方的例子改动一下
def my_image_filter():conv1_weights = tf.Variable(tf.random_normal([5, 5, 32, 32]),name="conv1_weights")conv1_biases = tf.Variable(tf.zeros([32]), name="conv1_biases")conv2_weights = tf.Variable(tf.random_normal([5, 5, 32, 32]),name="conv2_weights")conv2_biases = tf.Variable(tf.zeros([32]), name="conv2_biases")return None# First call creates one set of 4 variables.
result1 = my_image_filter()
# Another set of 4 variables is created in the second call.
result2 = my_image_filter()
# 获取所有的可训练变量
vs = tf.trainable_variables()
print 'There are %d train_able_variables in the Graph: ' % len(vs)
for v in vs:print v
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
There are 8 train_able_variables in the Graph:
Tensor("conv1_weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv1_biases/read:0", shape=(32,), dtype=float32)
Tensor("conv2_weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv2_biases/read:0", shape=(32,), dtype=float32)
Tensor("conv1_weights_1/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv1_biases_1/read:0", shape=(32,), dtype=float32)
Tensor("conv2_weights_1/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("conv2_biases_1/read:0", shape=(32,), dtype=float32)
2.第二种方式,用 tf.get_variable() 的方式
import tensorflow as tf
# 设置GPU按需增长
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)# 下面是定义一个卷积层的通用方式
def conv_relu(kernel_shape, bias_shape):# Create variable named "weights".weights = tf.get_variable("weights", kernel_shape, initializer=tf.random_normal_initializer())# Create variable named "biases".biases = tf.get_variable("biases", bias_shape, initializer=tf.constant_initializer(0.0))return Nonedef my_image_filter():# 按照下面的方式定义卷积层,非常直观,而且富有层次感with tf.variable_scope("conv1"):# Variables created here will be named "conv1/weights", "conv1/biases".relu1 = conv_relu([5, 5, 32, 32], [32])with tf.variable_scope("conv2"):# Variables created here will be named "conv2/weights", "conv2/biases".return conv_relu( [5, 5, 32, 32], [32])with tf.variable_scope("image_filters") as scope:# 下面我们两次调用 my_image_filter 函数,但是由于引入了 变量共享机制# 可以看到我们只是创建了一遍网络结构。result1 = my_image_filter()scope.reuse_variables()result2 = my_image_filter()# 看看下面,完美地实现了变量共享!!!
vs = tf.trainable_variables()
print 'There are %d train_able_variables in the Graph: ' % len(vs)
for v in vs:print v
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
There are 4 train_able_variables in the Graph:
Tensor("image_filters/conv1/weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("image_filters/conv1/biases/read:0", shape=(32,), dtype=float32)
Tensor("image_filters/conv2/weights/read:0", shape=(5, 5, 32, 32), dtype=float32)
Tensor("image_filters/conv2/biases/read:0", shape=(32,), dtype=float32)
3.2 实验 2 结论
4. 优雅示例
在深度学习中,通常说到 变量共享 我们都会想到 RNN 。下面我找了两个源码中非常漂亮的例子,可以参考学习学习。
# 例1:MultiRNNCell(RNNCell) 中这样来创建 各层 Cell
# https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py
for i, cell in enumerate(self._cells):with vs.variable_scope("cell_%d" % i):if self._state_is_tuple:...
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
# 例2:tf.contrib.rnn.static_bidirectional_rnn 双端 LSTM
with vs.variable_scope(scope or "bidirectional_rnn"):# Forward directionwith vs.variable_scope("fw") as fw_scope:output_fw, output_state_fw = static_rnn(cell_fw, inputs, initial_state_fw, dtype,sequence_length, scope=fw_scope)# Backward directionwith vs.variable_scope("bw") as bw_scope:reversed_inputs = _reverse_seq(inputs, sequence_length)tmp, output_state_bw = static_rnn(cell_bw, reversed_inputs, initial_state_bw,dtype, sequence_length, scope=bw_scope)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
![](http://static.blog.csdn.net/images/save_snippets.png)
本文代码:https://github.com/yongyehuang/Tensorflow-Tutorial
TensorFlow 变量共享,命名空间相关推荐
- tensorflow变量共享——VariableScope的reuse模式、tf.get_variable()、tf.Variable() 探索
文章目录 一.VariableScope的reuse模式的设置 1.1节 1.2节 1.3节 1.4节 1.5节 二.reuse模式对tf.Variable() 的影响 三.reuse模式对tf.ge ...
- 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() ...
- 14、TensorFLow 变量命名空间
一.name_scope with tf.name_scope(name): name_scope: 为了更好地管理变量的命名空间而提出的.比如在 tensorboard 中,因为引入了 name_s ...
- Tensorflow 变量的共享
https://github.com/chenghuige/tensorflow-exp/blob/master/examples/sparse-tensor-classification/ tens ...
- 深度学习tensorflow变量op
#-*-coding:utf-8-*- import tensorflow as tf #创建变量op #初始化的值 intit_value_1=tf.random_normal(dtype=tf.f ...
- Tensorflow变量作用域及变量初始化
本文主要讲述Tensorflow中的变量作用域及变量初始化.先来区分几个概念: tf.name_scope():为了更好地管理变量的命名空间而提出的.比如在 tensorboard 中,因为引入了 n ...
- C++中 auto自动变量,命名空间,using作用以及作用域
1.auto关键字的用途 A:自动变量,可以自动获取类型,输出,类似泛型 B:自动变量,可以实现自动循环一维数组 C:自动循环的时候,对应的必须是常量 2.auto自动变量,自动匹配类型的案例如 ...
- Java多线程编程:变量共享分析(Thread)
Java多线程编程:变量共享分析(Thread) Java 创建线程的两种方法 此处只简单讲下自己对java多线程变量共享的理解: 按照进程和多线程的原理,同一进程内的多个线程之间的地址空间是共享的( ...
- java多线程安全解决方案_《Java多线程编程核心技术(第2版)》 —1.2.8 实例变量共享造成的非线程安全问题与解决方案...
1.2.8 实例变量共享造成的非线程安全问题与解决方案 自定义线程类中的实例变量针对其他线程可以有共享与不共享之分,这在多个线程之间交互时是很重要的技术点. 1.不共享数据的情况 不共享数据的情况如图 ...
最新文章
- 通过关闭swap来提高win7运行速度
- 密码错误Neo.ClientError.Security.Unauthorized: The client is unauthorized due to authentication failure
- LeetCode 106. 从中序与后序遍历序列构造二叉树(Construct Binary Tree from Inorder and Postorder Traversal)...
- Android菜鸟的成长笔记(11)——Android中的事件处理
- cmd 无法切换目录
- 瓦片经纬度及行列号转换_ArcGIS根据最大最小坐标换算瓦片行列号
- 无论发生了什么生活_无论如何,一个开放团队的经理会做什么?
- linux下spark的python编辑_Linux下搭建Spark 的 Python 编程环境的方法
- 33 关 Python 游戏,测试你的爬虫能力到底及格不?
- 3个重点,20个函数分析,浅析FFmpeg转码过程
- 游戏契合度提示音_产品/市场契合度
- android8.1录屏,超级录屏安卓版-超级录屏appv1.1.8 - 起点软件园
- k3 审核流程图_K3Cloud 业务流程图Sql
- 小信号谐振器电路仿真实验
- 如何查看Steam的17位Id
- error: incompatible types when assigning to type ‘const struct wiphy_wowlan_support‘
- APP的启动流程梳理
- Burp Suite之Scaner模块(三)
- BPF和Go:在Linux中内省的现代方式[译]
- 异次元个人发卡系统_开源发卡系统