神经网络参数与TensorFlow变量

在TensorFlow中,变量(tf.Variable)的作用就是保存和更新网络中的参数。与其它编程语言相似,TensorFlow中的变量也需要指定初始值。在神经网络中,给参数赋予随机初始值最为常见,所以也一般使用随机数给TensorFlow中的变量初始化。下面一段代码给出了一种在TensorFlow中声明一个2×3的矩阵变量的方法:

weights=tf.Variable(tf.random_normal([2,3],stddev=2))

这段代码调用了TensorFlow变量声明函数tf.Variable。在变量声明函数中给出了初始化这个变量的方法。TensorFlow中的变量可以设置成随机数、常数或者通过其他变量的初始值计算得到。在上面样例中,tf.random_normal([2,3],stddev=2)会生成一个2×3的矩阵,矩阵中元素是均值为0,标准差为2的随机数。tf.random_normal函数可以通过参数mean来指定平均值,在没有指定时默认值为0.通过满足正太分布的随机数来初始化神经网络中的参数是一个非常常用的方法。除了正太分布的随机数,TensorFlow还提供了一些其它的随机数生成器,下表列出了TensorFlow目前支持的所有随机数生成器:

函数名称随机数分布主要参数
tf.random_normal正太分布平均值、标准差、取值类型
tf.truncated_normal正太分布,但是如果随机出来的值偏离平均值超过2个标准差,那么这个数将会被重新随机平均值、标准差、取值类型
tf.random_uniform平均分布最小、最大取值,取值类型
tf.random_gammaGamma分布形状参数alpha、尺度参数beta、取值类型

TensorFlow中也支持通过常数来初始化一个变量,下表给出了TensorFlow中常用的常量声明方法。

函数名称功能
tf.zeros产生全0的数组
tf.ones产生全1的数组
tf.fill产生一个全部为给定数字的数组
tf.constant产生一个给定值的常量

在神经网络中,偏置项(bias)通常会使用常数来设置初始值。以下代码给出一个样例:

bias=tf.Variable(tf.zeros([3]))

这段代码将会生成一个初始值全部为0且长度为3的变量。除了使用随机数或者常数,TensorFlow也支持通过其他变量的初始值来初始化新的变量。以下代码给出了具体的方法:

w2=tf.Variable(weights.initialized_value())
w3=tf.Variable(weights.initialized_value()*2.0)

以上代码中,w2的初始值被设置成与weights变量相同,w3的初始值则是weights初始值的两倍。在TensorFlow中,一个变量的值在被使用之前,这个变量的初始化过程需要被明确地调用。以下样例介绍了如何通过变量实现神经网络的参数并实现前向传播的过程。

#coding=utf-8
import tensorflow as tf 

#声明w1、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]])

#通过前向传播算法获得神经网络的输出
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

sess=tf.Session()
#这里不能直接通过sess.run(y)来获取y的值,
#因为w1和w2都还没有运行初始化过程。下面的两行分别初始化了w1和w2两个变量。
sess.run(w1.initializer)  #初始化w1
sess.run(w2.initializer)  #初始化w2
print(sess.run(y))
sess.close()
'''
输出:
[[ 3.95757794]]
'''

上面这段代码实现了神经网络的前向传播过程。定义w1、w2、a和y的过程对应了TensorFlow程序的第一步,这一步定义了TensorFlow计算图中所有的计算,但这些被定义的计算在这一步中并不真正运行。当需要运行这些计算并得到具体数字时,需要进入TensorFlow程序的第二步。
在TensorFlow程序第二步会生成一个会话(session),并通过会话计算结果。虽然在变量定义时给出了变量初始化的方法,但是这个方法并没有被真正运行。所以在计算y之前,需要通过运行w1.initializer和w2.initializer来给变量赋值。虽然直接调用每个变量的初始化过程是一个可行的方案,但是当变量数目变多,或者变量之间存在依赖关系时,单个调用的方案就比较麻烦了。为解决这个问题,TensorFlow提供了一种更加便捷的方式来完成变量初始化的过程。下面程序展示了通过tf.initialize_all_variables函数实现初始化所有变量的过程。

init_op=tf.initialize_all_variables()
sess.run(init_op)

通过tf.initialize_all_variables函数,就不需要将变量一个一个初始化了。这个函数也会自动处理变量之间存在的依赖关系。
TensorFlow的核心概念是张量(tensor),所有数据都是通过张量形式来组织的,在TensorFlow中,变量的声明函数tf.Variable是一个运算,这个运算的输出是一个张量,这个张量就是这里介绍的变量。所以变量是一种特殊的张量。
下面进一步介绍tf.Variable操作在TensorFlow中底层是如何实现的。图示给出了神经网络前向传播样例程序的TensorFlow计算图的一部分,这个部分显示了和变量w1相关的操作。
在这里插入图片描述
图中黑色椭圆代表了变量w1,可以看到w1是一个Variable运算。在这张图的下方可以看到w1通过一个read操作将值提供给了一个乘法运算,这个乘法操作就是tf.matmul(x,w1)。初始化变量w1的操作是通过Assign操作完成的。在图中可以看到Assign这个节点的输入wie随机数生成函数的输出,而且输出赋给了变量w1。这样就完成了变量初始化的过程。
之前博文介绍过TensorFlow中集合(collection)的概念,所有变量都会别自动加入GraphKeys.VARIABLES这个集合。通过tf.all_variable函数可以拿到当前计算图上所有的变量。拿到计算图上所有的变量有助于持久化整个计算图的运行状态。当构建机器学习模型是,比如神经网络,可以通过变量声明函数中的trainable参数来区分需要优化的参数(比如神经网络中的参数)和其它参数(比如迭代的轮数)。如果声明变量时参数trainable为True,那么这个变量将会被加入GraphKeys.TRAINBLE_VARIABLES集合。在TensorFlow中可以通过tf.trainable_variables函数得到所有需要优化的参数。TensorFlow中提供的神经网络优化算法会将Graph。TRAINABLE_VARIABLES集合中的变量作为默认的优化对象。
类似张量,维度(shape)和类型(type)也是变量最重要的两个属性。和大部分程序语言相似,变量的类型是不可改变的。一个变量在构建之后,它的类型就不能再改变了。比如上面给出的前向传播样例中,w1的类型为random_normal结果的默认类型tf.float32,那么它将不能被赋予其它类型的值。以下代码将会报出类型不匹配的错误。

w1=tf.Variable(tf.random_normal([2,3],stddev=1),name="w1") 
w2=tf.Variable(tf.random_normal([2,3],dtype=tf.float64,stddev=1),name="w2")
w1.assign(w2)

维度是变量的另一个重要属性。和类型不太一样的是,维度在程序运行中是有可能改变的,但是需要通过设置参数calidate_shape=False。下面给出一段示范代码。

w1=tf.Variable(tf.random_normal([2,3],stddev=1),name="w1") 
w2=tf.Variable(tf.random_normal([2,2],stddev=1),name="w2")
#下面这句会报维度不匹配的错误
tf.assign(w1,w2)
#这一句可以被成功执行
tf.assign(w1,w2,variable_shape=False)

虽然TensorFlow支持更改变量的维度,但是这种用法在实践中比较罕见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值