通过TensorFlow训练神经网络模型

监督学习最重要的思想就是,在已知答案的标注数据集上,模型给出的预测结果要尽量接近真实的答案。通过调整神经网络中的参数对训练数据进行拟合,可以使得模型对未知的样本提供预测的能力。
在神经网络优化算法中,最常用的方法是反向传播算法(backpropagation)。反向传播算法的具体工作原理将在之后博文中详述,本文将主要介绍训练神经网络的整体流程及TensorFlow对于这个流程的支持。下图展示了使用反向传播算法训练神经网络的流程图。
在这里插入图片描述
反向传播算法实现了一个迭代过程。在每次迭代的开始,首先需要选取一小部分训练数据,这一小部分数据叫做一个batch。然后这个batch的样例会通过前向传播算法得到神经网络模型的预测结果。因为训练数据都是有正确答案标注的,所以可以计算出当前神经网络模型的预测答案与正确答案之间的差距。最后,基于预测值和真实值之间的差距,反向传播算法会相应地更新神经网络参数的取值,使得在这个batch上神经网络模型的预测结果和真实答案更加接近。
通过TensorFlow实现反向传播算法的第一步是使用TensorFlow表达一个batch的数据。可以如下样例一样使用常量来表达:

x=tf.constant([0.7,0.9])

但如果每轮迭代中选取的数据都要通过常量来表示,那么TensorFlow的计算图将会太大。因为每生成一个常量,TensorFlow都会在计算图中增加一个节点。一般来说,一个神经网络的训练过程中会需要经过几百万轮甚至几亿轮的迭代,这样计算图就会非常大,而且利用率很低。为避免这个问题,TensorFlow提供了placeholder机制用于提供输入数据。placeholder相当于定义了一个位置,这个位置中的数据在程序运行时在指定。这样在程序中就不需要声场大量常量来提供输入数据,而只需要将数据通过placeholder传入TensorFlow计算图。在placeholder定义时,这个位置上的数据类型是需要指定的。和其它张量一样,placeholder的类型也是不可改变的。placeholder中数据的维度信息可以根据提供的数据推导得出,所以不一定要给出。下面给出了通过placeholder实现前向传播算法的代码。

#coding=utf-8
import tensorflow as tf 

w1=tf.Variable(tf.random_normal([2,3],stddev=1)) 
w2=tf.Variable(tf.random_normal([3,1],stddev=1))

#定义placeholder作为存放数据的地方。这里维度也不一定要定义
#但如果维度是确定的那么给出维度可以降低出错的概率
x=tf.placeholder(tf.float32, shape=(1,2), name="input")
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

sess=tf.Session()
init_op=tf.initialize_all_variables()
sess.run(init_op)
#下面一行将报错:InvalidArgumentError (see above for traceback):
# You must feed a value for placeholder tensor 'input' with dtype float and shape [1,2]
#print(sess.run(y))

print(sess.run(y,feed_dict={x:[[0.7,0.9]]}))

在这段程序中替换了原来通过常量定义的输入x。在新的程序中计算前向传播结果时,需要提供一个feed_dict来指定x的取值。feed_dict是一个字典(map),在字典中需要给出每个用到的placeholder的取值。如果某个需要的placeholder没有被指定取值,那么程序再运行时将会报错。
上面的程序只计算了一个样例的前向传播结果,但是在训练神经网络时需要每次提供一个batch的训练样例。对于这样的需求,placeholder也可以很好地支持。在上面的样例程序中,如果将输入的1x2矩阵改为nx2矩阵,就可以得到n个样例的前向传播结果了。其中nx2的矩阵的每一行为一个样例数据。这样前向传播的结果为nx1的矩阵,这个矩阵的每一行就代表了一个样例的前向传播结果。下面程序给出来一个示例:

x=tf.placeholder(tf.float32, shape=(3,2), name="input")
...#中间部分和上面的样例程序一样

#因为x在定义时指定了n为3,所以在运行前向传播过程时需要提供3个样例数据
print(sess.run(y,feed_dict={x:[[0.7,0.9],[0.1,0.4],[0.5,0.8]]}))

上面样例展示了一次性计算多个样例的前向传播结果。在运行时,需要3个样例[0.7,0.9]、[0.1,0.4]、[0.5,0.8]组成一个3x2的矩阵传入placeholder。计算得到的结果为3x1的矩阵。其中计算结果第一行为样例[0.7,0.9]的前向传播结果;第二行为[0.1,0.4]的前向传播结果;第三行为样例[0.5,0.8]的前向传播结果。
在得到一个batch的前向传播结果之后,需要定义一个损失函数来刻画当前的预测值和真实答案之间的差距。然后通过反响传播算法来调整神经网络参数的取值使得差距可以被缩小。以下代码定义了一个简单的损失函数,并通过TensorFlow定义了反响传播的算法。

#定义损失函数来刻画预测值与真实值之间的差距
cross_entropy=-tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0)))
#定义学习率
learning_rate=0.001
#定义反向传播算法来优化神经网络中的参数
train_step=tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)

在上面的代码中,cross_entropy定义了真实值和预测值之间的交叉熵(cross entropy),这是分类问题中常用的一个损失函数。第二行train_step定义了反向传播的优化方法。目前TensorFlow支持7种不同的优化器,比较常用的优化方法有三种:tf.trin.GradientDescentOptimizer、tf.train.AdamOptimizer和tf.train.MomentumOptimizer。在定义了反向传播算法后,通过运行sess.run(train_step)就可以对所有在GraphKeys.TRAINABLE_VARIABLES集合中的变量进行优化,使得在当前batch下损失函数更小。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值