变量的定义和使用
变量的定义与初始化
TensorFlow中,变量是一种特殊的张量,其值可以是一个任意类型的形状的张量。
与其他张量不同,变量存在于单个回话调用的上下文之外,主要作用是保存和更新模型中的参数。
声明变量通常使用tf.Variable()函数,其语法格式如表所示
函数 | 说明 |
tf.Variable( initial_value, trainable=True, collections=None, validate_shape=True, name=None) | 主要作用是声明一个变量。 initial_value:必选,指定变量的初始值。所有可转换为张量的类型均可。 trainable:可选,设置是否可以训练,默认为True collections:可选,设置该图变量的类型,默认为GraphKeys.GLOBAL_VARIABLES. validate_shape:可选,默认为True。如果为False,则不进行类型和维度检查。 name:变量名称。如果未指定会自动分配一个唯一的值。 |
tf.Variable()的主要作用是构造一个变量并添加到计算图模型中。在运行其他操作之前,需要对所有变量进行初始化。
最简单的初始化方法是添加一个对所有变量进行初始化的操作,然后在使用模型前运行此操作。
最常见的方式是运行tf.global_variables_initializer()函数进行全局初始化,该函数会初始化计算图中所有的变量。
下面的代码演示了如何在模型中初始化变量
import tensorflow as tf
# tf.Variable()定义了一个1行3列的整型变量,该变量的初始值为1,2,3
v = tf.Variable([1,2,3],dtype=tf.int32)
# tf.global_variables_initializer()定义了一个全局初始化操作。
init_op = tf.global_variables_initializer()
with tf.Session() as sess:#在会话中运行sess.run()初始化模型中的所有变量sess.run(init_op)print(sess.run(v))
随机初始化变量
在声明变量时需要指定初始化,一般使用随机数给TensorFlow的变量初始化,常见的初始化方法如下:
函数 | 说明 |
tf.random_normal( shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None) | 产生一个符合正态分布的张量。 shape:必选,生成张量的形状。 mean:可选,正态分布的均值,默认为0 stddev:可选,正态分布的标准差,默认为1.0 dtype:可选,生成张量的类型,默认为tf.float32. seed:可选,随机数种子,是一个整数。当设置之后,每次生成的随机数都一样 |
tf.trunceated_normal( shape, mean=0, stddev=1.0) | 产生一个满足正态分布的张量,当如果随机数偏离平均值超过2个标准差以上,将会被重新分配一个随机数 shape:必选,生成张量的形状 mean:可选,正态分布的均值,默认为0. stddev:可选,正态分布的标准差,默认为1.0 |
tf.random_uniform( shape, minval=low, maxval=high, dtype=tf.float32) | 产生一个满足平均分布的张量 shape:必选,生成张量的形状 mean:必选,产生值的最小值 stddev:必选,产生值的最大值 dtype:可选,产生值的类型,默认为float32 |
下面代码分别用不用的方式产生变量
import tensorflow as tf #导入TensorFlow类库,别名为tf
#产生一个符合正态分布的2行3列张量,均值为0,方差为1,随机种子为1
w1 = tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
#产生一个截断的2行3列张量,均值为0,方差为1
w2 = tf.truncated_normal(shape=[2,3],mean=0,stddev=1)
#产生一个符合均匀分布的2行2列张量,最小值为1.0,最大值为2.0
w3 = tf.random_uniform((2,2),minval=1.0,maxval=2.0,dtype=tf.float32)
init_op = tf.global_variables_initializer()
#在会话中初始化计算图中的所有变量
with tf.Session() as sess:sess.run(init_op)print("w1:",sess.run(w1))print("w2:",sess.run(w2))print("w3:",sess.run(w3))
获取变量
除了可使用tf.Variable()创建变量,还可以使用tf.get_variable()函数创建或获取变量。
tf.get_variable()函数用于创建变量时,它和tf.Variable()的功能是等价的。
以下代码给出了通过两个函数创建变量的实例:
m = tf.Variable(tf.constant(1.0,shape=[1],name="m"))
n = tf.get_variable(shape=[1],name="n",initializer=tf.constant_initializer[1])
可以看出,tf.Variable()和tf.get_variable()创建变量的过程是一样的,两者最大的区别在于指定变量名称的参数不同。
tf.Variable()函数中,变量名称是可选参数;
tf.get_variable()函数中,变量名是必选参数,当变量名存在时,将直接获取变量。
tf.get_variable()函数的语法格式如表
函数 | 说明 |
tf.get_variable( name, shape, initializer ) | 用来初始化或获取变量 name:变量的名称,必填 shape:变量的形状,必填 initializer:变量初始化的方法,选填 |
tf.get_variable()函数拥有一个变量检查机制,会检测已经存在的变量是否设置为共享变量。
如果未设置为共享变量,Tensorflow运行到第二个拥有相同名字变量的时候,就会抛出异常错误。
共享变量
tf.variable_scope()函数用来指定变量的作用域。
不同作用域中的变量可以有相同的命名,包括使用tf.get_variable()函数得到的变量以及tf.Variable()函数创建的变量。
tf.get_variable()常常会配合tf.variable_scope()一起使用,以实现变量共享。tf.variable_scope()函数会生成上下文管理器,并指定变量的作用域。
tf.variable_scope()里还有一个reuse = True 属性,表示使用已经定义过的变量,这时tf.get_variable()不会创建新的变量,而是直接获取已经创建好的变量。如果变量不存在,则会报错。
下面代码使用了变量共享的功能:
import tensorflow as tf
with tf.variable_scope("V1"):a1 = tf.get_variable(name = 'a1',shape = [1],initializer = tf.constant_initializer(1))
with tf.variable_scope("V2"):a2 = tf.get_variable(name = 'a1',shape = [1],initializer = tf.constant_initializer(1))
with tf.variable_scope("V2",reuse = True):a3 = tf.get_variable('a1')
with tf.Session() as sess:sess.run(tf.global_variables_initializer())print(a1.name)print(a2.name)print(a3.name)
2-3行代码:在V1变量空间中定义变量a1
4-5行代码:在V2变量空间中定义变量a1。由于两个a1位于不同的变量空间,所以不会产生冲突
6-7行代码:重用V2命名空间的a1变量。调用tf.get_variable()时,会获取V2命名空间的a1变量的值