前言
探索一下variable_scope
和name_scope
相关的作用域,为下一章节tensorboard
的学习做准备
其实关于variable_scope
与get_variable
实现变量共享,在最开始的博客有介绍过:
【TensorFlow-windows】学习笔记二——低级API
当然还是国际惯例,参考博客:
tensorflow: name_scope 和 variable_scope区别及理解
tensorflow学习笔记(十七):name&variable scope
tensorflow
官方文档name_scope
tensorflow
官方文档get_varialbe
tensorflow
官方文档variable_scope
variable_scope相关
先引入对应包:
import tensorflow as tf
import numpy as np
Variable定义的变量是否共享
a1 = tf.Variable(1,name='aaa')
a2 = tf.Variable(2,name='aaa')
init=tf.initialize_all_variables()
with tf.Session() as sess:sess.run(init)print(a1.eval())#1print(a2.eval())#2
print(a1) #<tf.Variable 'aaa:0' shape=() dtype=int32_ref>
print(a2) #<tf.Variable 'aaa_1:0' shape=() dtype=int32_ref>
结论:Variable
定义的权重不共享,会自动给变量按照定义顺序加后缀_索引
,比如第2此定义的aaa
得到的名字是aaa_1
,所以他们是完全不同的两个变量,名称也不同。
Variable定义与get_variable定义有什么区别
#variable创建方式
tf.Variable(<initial-value>, name=<optional-name>)
#get_variable创建方式
tf.get_variable(name,shape=None,dtype=None,initializer=None,regularizer=None,trainable=True,collections=None,caching_device=None,partitioner=None,validate_shape=True,use_resource=None,custom_getter=None,constraint=None
)
结论:Variable
定义不实现共享,所以只需要初始值就行了,名字无所谓。get_variable
要通过名字实现共享,所以必须给变量一个名字,其余无所谓。
直接定义两个同名的get_variable
变量
b1 = tf.get_variable(name='b',initializer=10)
init = tf.initialize_all_variables()
with tf.Session() as sess:sess.run(init)print(b1.eval())#10
b2 = tf.get_variable(name='b',initializer=20)
'''
Variable b already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:
'''
结论:不能直接定义两个同名get_variable
变量,必须通过特定方法实现共享
第一种共享方法
在variable_scope
内部使用reuse_variables
函数:
with tf.variable_scope('dd') as scope:d1=tf.get_variable(name='d',initializer=10.0,dtype=tf.float32)scope.reuse_variables()d2=tf.get_variable(name='d',initializer=20.0,dtype=tf.float32)
上述在同一个变量空间中,定义两个同名变量,通过reuse_variable
实现共享,输出结果如下:
print(d1,d2)
init=tf.initialize_all_variables()
with tf.Session() as sess:sess.run(init)print(d1.eval(),d2.eval())
'''
<tf.Variable 'dd/d:0' shape=() dtype=float32_ref> <tf.Variable 'dd/d:0' shape=() dtype=float32_ref>
10.0 10.0
'''
结论:可以通过reuse_variable
实现共享,但是第二次初始化的值是无法覆盖第一次初始化的值的
第二种共享方法
在使用variable_scope
建立变量空间的时候,如果是复用一个已定义的变量空间中的变量,直接将reuse
设置为True
with tf.variable_scope('ff') as scope:f1=tf.get_variable(name='f',initializer=10.0,dtype=tf.float32)
with tf.variable_scope('ff',reuse=True) as scope:f2=tf.get_variable(name='f',initializer=20.0,dtype=tf.float32)
with tf.variable_scope('gg') as scope:g=tf.get_variable(name='f',initializer=20.0,dtype=tf.float32)
输出看看
print(f1,f2,g)
init=tf.initialize_all_variables()
with tf.Session() as sess:sess.run(init)print(f1.eval(),f2.eval(),g.eval())
'''
<tf.Variable 'ff/f:0' shape=() dtype=float32_ref> <tf.Variable 'ff/f:0' shape=() dtype=float32_ref> <tf.Variable 'gg/f:0' shape=() dtype=float32_ref>
10.0 10.0 20.0
'''
结论:可以通过函数参数reuse
实现变量共享
不同变量空间中的相同名称变量是否共享
结论:无法共享,比如上例中f1
和g
无法共享,虽然名称都是f
,但是所在变量空间不同。
第三种共享方法
调用函数的时候,自动检测是否需要reuse
with tf.variable_scope('ee',reuse=tf.AUTO_REUSE) as scope:e2=tf.get_variable(name='e',initializer=10.0,dtype=tf.float32)e3=tf.get_variable(name='e',initializer=20.0,dtype=tf.float32)
with tf.variable_scope('ee',reuse=tf.AUTO_REUSE) as scope:e4=tf.get_variable(name='e',initializer=30.0,dtype=tf.float32)
init = tf.initialize_all_variables()
with tf.Session() as sess:sess.run(init)print(e2,e3,e4)print(e2.eval(),e3.eval(),e4.eval())
'''
<tf.Variable 'ee/e:0' shape=() dtype=float32_ref> <tf.Variable 'ee/e:0' shape=() dtype=float32_ref> <tf.Variable 'ee/e:0' shape=() dtype=float32_ref>
10.0 10.0 10.0
'''
如果之前没创建过共享变量,不适用自动检测,而直接reuse
会报错
with tf.variable_scope('ee',reuse=True) as scope:e2=tf.get_variable(name='e',initializer=10.0,dtype=tf.float32)
'''Variable ee/e does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?
'''
结论:如果不确定之前是否创建过共享变量,最好是使用AUTO_REUSE
自动检测
name_scope相关
直接用namescope是否能隔绝共享变量
with tf.name_scope('f') as nscope:f1 = tf.get_variable('f',initializer=10.0,dtype=tf.float32)
with tf.name_scope('g') as nscope:g = tf.get_variable('f',initializer=20.0,dtype=tf.float32)
'''
Variable f already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:
'''
结论:无法直接用name_scope
隔绝共享变量
在不同namesope中是否可以共享变量
创建两个命名空间,但是两个命名空间包含相同的变量空间,设置共享变量h
with tf.name_scope('test1') as scope:with tf.variable_scope('h',reuse=tf.AUTO_REUSE):h1 = tf.get_variable('hh',initializer=10.0,dtype=tf.float32)
with tf.name_scope('test2') as scope:with tf.variable_scope('h',reuse=tf.AUTO_REUSE):h2 = tf.get_variable('hh',initializer=10.0,dtype=tf.float32)
测试是否能实现变量共享
init = tf.initialize_all_variables()
with tf.Session() as sess:sess.run(init)print(h1,h2)print(h1.eval(),h2.eval())op=tf.assign(h1,30.0)sess.run(op)print(h1.eval(),h2.eval())
'''
<tf.Variable 'h/hh:0' shape=() dtype=float32_ref> <tf.Variable 'h/hh:0' shape=() dtype=float32_ref>
10.0 10.0
30.0 30.0
'''
结论:命名空间不能控制是否共享,但是变量空间可以控制变量共享。
总结
get_variable
与variable_scope
配合可以实现变量共享。
name_scope
无法实现变量共享,但是如果看过之前的博客可以发现,它的一个作用是将一系列操作封装在一起,这样画图的时候网络结构比较清晰。
其它作用以后遇到再补充,主要是为了下一章节学习tensorboard
做准备。