一 get_variable() 函数
get_variable() 函数用于创建或获取变量。 在实现创建变量的功能时,其使用方法和 Variable () 函数基本相同。
import tensorflow as tf
# 通过一个常量来初始化一个变量
# a = tf.Variable(tf.constant(1.0,shape=[1],name='a'))
# 使用一个 get_variable()创建一个变量
# 原型 : get_variable(name,shape,dtype,initializer,regularizer,trainable,...)
a = tf.get_variable("a",shape=[1],initializer=tf.constant_initializer(1.0))
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init_op)
print(sess.run(a))
print(a)
从上面的代码中看出,get_variable() 函数调用时提供的形状信息(shape)和 Variable() 函数类似。
get_variable() 函数通过 initializer 参数提供初始化方法 , 下表为一些初始化函数 :
初始化函数
| 功能
|
constant_initializer()
| 将变量初始化为给定的常量
|
random_normal_initializer()
| 将变量初始化为满足正态分布的随机值
|
truncated_normal_initializer()
| 将变量初始化为满足正态分布的随机值,但如果随机出来的偏离平均值超过2个标准差,那么这个数将重新随机
|
random_uniform_initializer()
| 将变量初始化为满足平均分布的随机数值
|
uniform_uint_scaling_initializer()
| 将变量初始化为满足平均分布但不影响输出数量级的随机值
|
zeros_initializer()
| 将变量初始化全为0
|
ones_initializer()
| 将变量初始化全为1
|
|
|
在 get_variable() 中 name 是一个必选的参数 。
二 variable_scope()
在使用 get_variable() 函数之前,我们要使用函数 variable_scope() 结合上下文管理器(with) 生成一个变量空间。
在相同的变量空间中使用 get_variable() 函数创建name 属性相同的两个变量会导致错位的发生。
import tensorflow as tf
# 在名为 one 的变量空间内创建名字 为 a 的变量
with tf.variable_scope("one") :
a = tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init_op)
print(a)
#下面会出错
with tf.variable_scope("one") :
a2 = tf.get_variable("a",[1])
上面的程序简单的说明了variable_scope() 函数影响了get_variable() 函数的使用。在执行创建变量 a2的代码时会由于"one" 这个变量空间中已经存在 name属性为 a 的变量二产生报错信息,提示是否在 variable_scope() 函数中使用reuse= True 参数。
reuse 参数的默认值为 False , 当variable_scope() 函数使用 reuse = True 参数生成上下文管理器时,这个上下文管理器内所有的get_variable() 函数会直接获取 name 属性相同的已经创建的变量。如果变量不存在,则 get_variable() 函数会报错.
import tensorflow as tf
# 在名为 one 的变量空间内创建名字 为 a 的变量
with tf.variable_scope("one") :
a = tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
with tf.variable_scope("one",reuse=True) :
a2 = tf.get_variable("a",[1])
print(a.name,a2.name)
输出 : one/a:0 one/a:0
如果 使用默认的 resue = False ,创建变量空间,那么 get_variable() 函数将创建新的变量; 如果name属性相同的变量已经存在,get_variable() 函数将会报错。
使用 variable_scope() 函数创建变量空间时,在变量空间内创建的变量名称都会带上这个变量空间名称作为前缀。上面代码中
输出 one/a:0 one 就是变量空间。下面展示的是变量空间的嵌套 :
import tensorflow as tf
a = tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
print(a.name)
with tf.variable_scope("one"):
a2 = tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
print(a2.name)
with tf.variable_scope("one") :
with tf.variable_scope("two"):
a4 = tf.get_variable("a",[1])
print(a4.name)
# 输出 one/two/a ,变量空间嵌套之后,
# 变量的名称会加入所有变量的名称作为前缀
b = tf.get_variable("b",[1])
print(b.name)
with tf.variable_scope("",reuse=True) :
# 也可以直接通过变量空间名的前缀的变量名来获取相应的变量
a5 = tf.get_variable("one/two/a",[1])
print(a5 == a4)
#输出 True
下面展示如何确定 reuse 参数的取值 :
import tensorflow as tf
with tf.variable_scope("one") :
# 使用get_variable_scope() 函数可以获取当前的变量空间
print(tf.get_variable_scope().reuse)
#输出 False
with tf.variable_scope("two",reuse=True):
print(tf.get_variable_scope().reuse)
# 在一个嵌套变量空间中如果不指定 reuse 参数,
# 那么会默认和外面最近的一层保持一致
with tf.variable_scope("three"):
print(tf.get_variable_scope().reuse)
# 输出 True
#回到 reuse 值为默认 False 的最外层变量空间
print(tf.get_variable_scope().reuse)
三 name_scope()
name_scope() 函数提供了类似于 variable_scope() 函数的变量空间管理功能,但是在搭配 get_variable() 函数使用时二者会有所差别 。
import tensorflow as tf
with tf.variable_scope("one") :
a = tf.get_variable("var1",[1])
print(a.name)
with tf.variable_scope("two"):
b = tf.get_variable("var2",[1])
print(b.name)
with tf.name_scope("a") :
#使用 Variable() 函数生成变量会受到 name_scope() 的影响
a = tf.Variable([1],name='a')
print(a.name)
a = tf.get_variable("b",[1])
print(a.name)
'''
with tf.name_scope("b") :
#企图创建 name 属性为 b 的变量c ,然而这个变量已经被声明了
c = tf.get_variable("b",[1])
'''
从上面的代码中可以看出, 在 name_scope() 内部使用 get_variable() 函数时,生成的变量名称不会被添加变量空间名称前缀;
而 Variable() 函数在 name_scope() 内部会被添加变量空间名称前缀.使用 variable_scope() 变量空间时 ,无论是 get_variable()
还是 Variable() 都会在生成的变量名称前面添加变量空间名称前缀。