在TensorFlow中,变量(Variable)的作用就是保存和更新神经网络中的参数,我们可以使用tf.Variable()函数来声明变量。
生成变量时,我们需要考虑变量的初始化,设置变量初始值的方法有以下三种:
-
使用随机数设置初始值:
在神经网络中,边的权重(weight)参数通常会使用随机数来设置初始值,TensorFlow支持以下四个随机数生成函数:
其中tf.random_normal()函数比较常用,如:weights = tf.Variable(tf.random_normal([2,3], stddev=2))
在上面的样例中,tf.random_normal([2,3], stddev=2)用于产生一个2 × 3的矩阵,矩阵中的元素服从一个平均值mean为0(没有指定时平均值默认为0),标准差stddev为2的正态分布。
-
使用常数设置初始值:
在神经网络中,偏置项(bias)参数通常会使用常数来设置初始值,TensorFlow支持以下四个常数生成函数:
-
使用其他变量的初始值设置初始值:
#w1的初始值与weights相同,w2的初始值是weights的两倍 w1 = tf.Variable(weights.initialized_value()) w2 = tf.Variable(weights.initialized_value() * 2.0)
在TensorFlow中,一个变量的值在使用之前,需要明确地调用变量的初始化过程,通常有下列两种方法:
- 第一种方法,直接调用每个变量的初始化过程,这种方法相对来说会比较麻烦:
sess.run(weights.initializer) sess.run(w1.initializer) sess.run(w2.initializer)
- 第二种方法,通过tf.initialize_all_variables()函数实现初始化所有变量的过程:
init_op = tf.initialize_all_variables() sess.run(init_op)
需注意的是,在以上三种设置变量初始值的方法当中,不管是使用哪种方法选定变量的初始值,它的本质都仍然是一个变量,都可以作为参数在神经网络中进行优化。
实际上,所有的变量都会被自动加入GraphKeys.VARIABLES这个集合,通过tf.all_variables函数可以拿到当前计算图上所有的变量,拿到计算图上所有的变量有助于持久化整个计算图的运行状态。
当构建机器学习模型时,比如神经网络,可以通过tf.Variable()变量声明函数中的trainable参数来区分模型当中需要优化的参数(比如神经网络中的参数)和其他参数(比如迭代的轮数)。
如果声明变量时trainable参数为True,那么这个变量将会被加入GraphKeys.TRAINABLE_VARIABLES集合(trainable参数默认为True,若不想变量被GraphKeys.TRAINABLE_VARIABLES集合收集,就设置为False)。
TensorFlow中提供的神经网络优化算法会将GraphKeys.TRAINABLE_VARIABLES集合中的变量作为默认的优化对象,在TensorFlow中可以通过tf.trainable_variables()函数得到所有需要优化的参数。
关于GraphKeys.VARIABLES和GraphKeys.TRAINABLE_VARIABLES这两个集合的一些基本信息请参照:TensorFlow计算模型——计算图。
维度(shape)和类型(type)是变量最重要的两个属性。其中,变量的类型是不可改变的,一个变量在构建之后,它的类型就不能再改变了;和类型不大一样的是,变量的维度在程序运行中是有可能改变的,但是需要通过设置参数validate_shape=False(默认为True),如:
w1 = tf.Variable(tf.random_normal([2,3], stddev=2), name="w1")
w2 = tf.Variable(tf.random_normal([2,2], stddev=2), name="w2")
#这一句会报维度不匹配的错误:ValueError: Shapes (2, 3) and (2, 2) are not compatible
tf.assign(w1, w2)
#这一句可以被成功执行
tf.assign(w1, w2, validate_shape=False)
最后,以一个前向传播算法示意图为示例编写一个简单的TensorFlow程序来做个总结:
import tensorflow as tf
with tf.Session() as sess:
#声明wl、W2两个变量,通过seed参数设定了随机种子,这样可以保证每次运行得到的结果是一样的
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
#暂时将输入的特征向量定义为一个常量,这里的x是一个1 × 2的矩阵
x = tf.constant([[0.7, 0.9]])
#注意,如果像下面这样写,会发生报错
#x = tf.constant([0.7,0.9])
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
#初始化变量
init_op = tf.global_variables_initializer()
sess.run(init_op)
#输出结果:[[3.957578]]
print(sess.run(y))