【TensorFlow】神经网络模型训练及完整程序实例(五)

来源:互联网 发布:网络女歌手伤感情歌 编辑:程序博客网 时间:2024/06/04 23:32

首先,看一下神经网络反向传播优化流程图:
这里写图片描述
反向传播算法实现了一个迭代的过程。每次迭代的开始,都选取一部分训练数据batch。然后,这个batch的样例会通过前向传播算法得到神经网络模型的预测结果。因为训练数据都是有正确答案标注的,所以可以计算出当前神经网络模型的预测答案与正确答案之间的差距。最后,基于这个差距,通过反向传播算法会更新神经网络参数的取值,使得在这个batch上神经网络的预测结果与真实答案更加接近。

TensorFlow提供一个placeholder的机制用于提供数据输入,避免大量常量生成造成的计算量大带来的效率低下。以下是placeholder实现前向传播算法的代码:

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))#定义placeholder作为数据存放的点,给定维度可以降低出错的概率。x = tf.placeholder(tf.float32,shape = (1,2),name = 'input')#输入N*m维数组,N大于1。xx = tf.placeholder(tf.float32,shape = (3,2),name = 'input')#暂时将输入的特征向量定义为一个常量。X是一个1*2的矩阵#x = tf.constant([[0.7,0.9]])a = tf.matmul(x,w1)y = tf.matmul(a,w2)aa = tf.matmul(xx,w1)yy = tf.matmul(aa,w2)sess = tf.Session()init = tf.global_variables_initializer()sess.run(init)#print(sess.run(y))#会报错,需要提供一个feed_dict来指定x的取值。print(sess.run(y,feed_dict={x:[[0.9,0.7]]}))#当多维数组N*m输入时,输出N*1个结果print(sess.run(yy,feed_dict={xx:[[0.9,0.7],[1.0,1.9],[2.1,2.3]]}))sess.close()

在得到一个batch的前向传播结果后,需要定义一个损失函数来刻画当前预测值与真实答案之间的差距。然后通过反向传播算法来调整神经网络参数的取值使得差距可以被缩小。

#定义损失函数来刻画预测值与真实值之间的差距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)

TensorFlow目前有7中优化器,比较常用的优化方法有三种:
tf.train.GradientDescentOptimizer,tf.train.AdamOptimizer,tf.train.MomentumOptimizer。在定义反向传播算法之后,通过运行sess.run(train_step)就可以对所在集合中的变量进行优化,使得当前batch的损失函数最小。

完整的神经网络训练模型:

import tensorflow as tffrom numpy.random import RandomState#定义训练数据batch的大小batch_size = 8#声明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))#定义placeholder作为数据存放的点,给定维度可以降低出错的概率。#在shape的一个维度上使用None可以方便使用不同的batch大小。#在训练时需要把数据分成较小的batch,但是在测试时,可以一次性使用全部的数据。#当数据集比较小的时候这样可以方便测试,但是数据集比较大时,将大量数据放入一个batch会导致数据溢出。x = tf.placeholder(tf.float32,shape = (None,2),name = 'x-input')#输入N*m维数组,N大于1。y_ = tf.placeholder(tf.float32,shape = (None,1),name = 'y-input')#暂时将输入的特征向量定义为一个常量。X是一个1*2的矩阵#x = tf.constant([[0.7,0.9]])#定义神经网络前向传播的过程a = tf.matmul(x,w1)y = tf.matmul(a,w2)#定义损失函数和反向传播的算法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)#通过随机数生成一个模拟数据集rdm = RandomState(1)dataset_size = 128X = rdm.rand(dataset_size,2)#print(X.shape)#print(X[0:8])#定义规则给出样本的标签。在这x1+x2<1的样例认为是正样本Y = [[int(x1+x2<1) for (x1,x2) in X ]]Y = np.array(Y).reshape(-1,1)#print(Y)#创建会话sess= tf.Session()init = tf.global_variables_initializer()sess.run(init)print(sess.run(w1))print(sess.run(w2))#设定训练次数Steps = 5000for i in range(Steps):    #每次选择batch_size个样本进行训练    start = (i*batch_size)%dataset_size    #print(start)    end = min(start+batch_size,dataset_size)    #通过选取的样本训练神经网络并更新参数    sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})    if i%1000==0:        #每隔一段时间计算所有数据的交叉熵并输出        total_cross_entropy = sess.run(cross_entropy,feed_dict={x:X,y_:Y})        print('循环:%d,交叉熵:%g'%(i,total_cross_entropy))print(sess.run(w1))print(sess.run(w2))
阅读全文
0 0
原创粉丝点击