Tensorflow基础知识梳理(一)

一、知识框架

Tensorflow基础知识梳理(一)_第1张图片

二、实战应用 

MNIST手写识别代码总结

        Description:深度学习实战的第一个练手例子,取60000张图片作为训练集,5w张作为训练集,1w张作为测试集

构建一个三层神经网络,输入层有784个结点,每一个结点代表一张图片的一个像素点,隐藏层含有2000个结点,输出层有         10个结点,维护一个一位列表代表输出的数字值。该模型主要运用应用前向传播以及反向传播算法,通过综合梯度下降法            对网络中的权重(参数)进行调整,同时利用平均模型法,指数衰减法对模型实现优化。

import tensorflow as  tf 
from tensorflow.examples.tutorials.mnist import input_data

#载入MNIST数据集,如果指定地址/path/to/MNIST_data 下没有已经下好的数据,
#那么Tensorflow会自动从表5-1的地址下载数据
# mnist = input_data.read_data_sets("/path/to/MNIST_data/",one_hot=True)

#打印Training data size:55000
# print("Training data size:",mnist.train.num_examples)

# #打印Validation data siz:5000
# print("Validation data size:",mnist.validation.num_examples)

# #打印Testing data size. 10000
# print("Testing data size:",mnist.test.num_examples)

# #打印Example training data:
# print("Example training data:\n",mnist.train.images[0])

# #打印Example Training data label:
# print("Example training data label:\n", mnist.train.labels[0])

# batch_size = 100
# xs,ys = mnist.train.next_batch(batch_size)
#从train集合中选取batch_size个数据
# print("X shape:",xs.shape)
# print("Y shape:",ys.shape)
#其中X为测试数据集,Y为标签集

#MNIST数据集相关常数
INPUT_NODE = 784    #输入层的节点数。对于MNIST数据集,这个就等于图片的像素
OUTPUT_NODE = 10   #输出层的节点数。这个等于类别的数目,因为MNIST数据集中需要区分0~9这十个数字,所以这里输出层的节点数为10.

#配置神经网络的参数
LAYER1_NODE = 2000   #隐藏层的节点数。这里使用只有一个隐藏层的网络作为样例,这个隐藏层有500个结点

BATCH_SIZE = 10000    #一个训练batch中的训练数据个数。数字越小时,训练过程越接近随机梯度下降;数字越大,训练越接近梯度下降

LEARNING_RATE_BASE = 0.8    #基础的学习率
LEARNING_RATE_DECAY =0.99   #学习率的衰减率
REGULARIZATION_RATE =0.0001 #描述模型复杂度的正则化项在损失函数中的系数
TRAINING_STEPS =50000       #训练的轮数
MOVING_AVERAGE_DECAY = 0.99 #滑动平均衰减率

#一个辅助函数,给定神经网络的输入和所有参数,计算神经网络的前向传播结果。在这里
#定义了一个使用ReLU激活函数的三层全连接神经网络。通过加入隐藏层实现了多层网络的结构
#通过ReLU激活函数实现了去线性化。在这个函数中也支持传入用于计算参数平均值的类,
#这样方便在测试时使用滑动平均模型
def  inference(input_tensor,avg_class,weights1,biases1,weights2,biases2):
	#当没有提供滑动平均类时,直接使用参数当前的取值
	if avg_class == None:
		#计算隐藏层的前向传播结果
		layer1 = tf.nn.relu(tf.matmul(input_tensor,weights1)+biases1)

		#计算输出层的前向传播结果。因为在计算损失时会一并计算softmax函数
		#所以这里不需要加入激活函数。而且不加入softmax不影响预测结果。
		#因为预测时使用的是不同类别对应结点输出值的不相对同大小,有没有softmax层
		#对最后分类结果的计算没有影响。于是在计算整个神经网络的前向传播时可以
		#不加入最后的softmax层。
		return tf.matmul(layer1,weights2)+biases2

	else:
		#首先使用avg_class.average函数来计算得出变量的滑动平均值,
		#然后在计算相应的神经网络前向传播结果
		layer1 = tf.nn.relu(tf.matmul(input_tensor,avg_class.average(weights1)) + 
			avg_class.average(biases1))
		return tf.matmul(layer1,avg_class.average(weights2)) +avg_class.average(biases2)


#训练模型的过程
def train(mnist):
	x = tf.placeholder(tf.float32,[None,INPUT_NODE],name = 'x-input')
	y_ = tf.placeholder(tf.float32,[None,OUTPUT_NODE],name = 'y-input')

	#生成隐藏层的参数
	weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE,LAYER1_NODE],stddev=0.1))
	biases1 = tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE]))
	#生成输出层的参数
	weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE,OUTPUT_NODE],stddev = 0.1))
	biases2 = tf.Variable(tf.constant(0.1,shape=[OUTPUT_NODE]))

	#计算在当前参数下神经网络前向传播的结果,这里给出的用于计算滑动平均的类为None,所以函数不会使用参数的滑动平均值

	y = inference(x,None,weights1,biases1,weights2,biases2)

	#定义存储训练轮数的变量。这个变量不需要计算滑动平均值,所以这里指定这个变量为不可训练的变量(trainable=False)
	#Tensorflow训练神经网络时,一般会将代表训轮数的变脸指定为不可训练的参数。

	#将代表训练轮数的变量为不可变的参数
	global_step = tf.Variable(0,trainable=False)

	#给定滑动_平均衰减率_和_训练轮数_的变量,初始化滑动平均类(见第4章)
	#给定训练轮数的变量可以训练早期变量的更新速度

	variable_averages = tf.train.ExponentialMovingAverage(
		MOVING_AVERAGE_DECAY,global_step)

	#在所有代表神经网络参数的变量上使用滑动平均,其他辅助变量就不需要了。tf.trainable.variable返回的就是图上集合

	variables_averages_op = variable_averages.apply(
		tf.trainable_variables())


	#计算使用滑动平均之后前向传播的结果。滑动平均不会改变变量本身的取值,而会维护一个影子变量来记录
	#其滑动平均值。所以当需要使用这个滑动平均值时,需要明确调用average()函数。
	average_y = inference(x,variable_averages,weights1,biases1,weights2,biases2)

	#计算交叉熵作为刻画预测值和真实值之间差距的损失函数,这里使用Tensorflow中提供的
	#sparse_softmax_cross_entropy_with_logits函数来计算交叉熵。当分类问题只有一个正确答案时,
	#可以使用这个函数来加速交叉熵的计算。MNIST问题的图片中只包含了0~9中的一个数字,所以可以
	#使用这一个函数来计算交叉损失。这个函数的第一个参数是神经网络不包括softmax的前向传播结果
	#第二个是训练数据的正确答案。因为标准答案是一个长度为10的一维数组,而该函数需要提供的是
	#一个正确答案的数字,所以需要使用tf.argmax(y_,1)函数来得到正确答案的编号
	cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=tf.argmax(y_,1))
	 
	#计算在当前batch中所有样例的交叉熵平均值。
	cross_entropy_mean = tf.reduce_mean(cross_entropy)

	#定义计算L2正则化损失函数,REGULARIZATION_RATE表示模型复杂损失在总损失中的比例
	#正则化的思想,在损失函数中加入刻画模型复杂程度的指标
	regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)


	#计算模型的正则化损失一般只计算神经网路权上的正则化损失,而不需要计算偏置顶
	regularization = regularizer(weights1) + regularizer(weights2)

	#总损失等于交叉熵损失和正则化损失之和
	loss = cross_entropy_mean + regularization

	#设置指数衰减的学习率
	learning_rate = tf.train.exponential_decay(
		LEARNING_RATE_BASE,                      #基础的学习率,随着迭代的进行,更新变量时使用的学习率在这个基础上递减
		global_step,						     #当前迭代的轮数
		mnist.train.num_examples/BATCH_SIZE,	 #过完所有训练数据需要迭代的次数
		LEARNING_RATE_DECAY					     #学习率的衰减速度
		)

	#使用tf.train.GradientDescentOptimizer()函数优化算法来优化损失函数。
	#这里的损失函数包含了交叉熵损失和L2正则化损失
	train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)

	#在训练神经网络模型时,每过一遍数据既需要通过反向传播来更新神经网络中的参数,
	#又要更新每一个参数的滑动平均值。为了一次完成多个操作,Tensorflow提供了
	#tf.control_dependencies和tf.group两种机制,下面两行代码和
	#tf.control_dependencies([train_step,variable_averages_op])是等价的
	#tf.control_dependencies()控制计算流图的,给图中的某些计算指定顺序
	with tf.control_dependencies([train_step,variables_averages_op]):
		train_op = tf.no_op(name='train')

	#检测使用了滑动平静模型的神经网络前向传播是否正确。tf.argmax(average_y,1)
	#计算每一个样例的预测答案。其中average_y是一个batch_size*10的二维数组,每
	#一行表示案例向前传播的结果。tf.argmax的第二个参数为1,表示选取最大值的
	#操作只在第一个维度上进行(x轴上),也就是说只在每一行选取最大值对应的下标
	#于是得到的结果是一个长度为batch的一维数组,这个一维数组中的值就表示了每
	#一个数字对应的样例识别的结果.tf.equal()判断每个Tensor的每一维度是否相同
	#如果相等返回True,否则返回False.
	correct_prrediction = tf.equal(tf.argmax(average_y,1),tf.argmax(y_,1))

	#这个运算首先将一个布尔型的值转换为实数型,然后计算平均值。这一个平均值
	#就代表模型在这一组数据上的正确率
	accuracy = tf.reduce_mean(tf.cast(correct_prrediction,tf.float32))

	#初始化会话,并开始训练过程
	with tf.Session() as sess:
		tf.initialize_all_variables().run()

		#准备验证数据。一般在神经网络的训练过程中会通过验证数据
		#大致判断停止的条件和训练的结果
		validate_feed = {x:mnist.validation.images,y_:mnist.validation.labels}


		#准备测试数据。在真实应用中,这部分数据在训练时是不可见的,这部分数据只是作为
		#模型优劣的最后评价标准
		test_feed = {x:mnist.test.images,y_:mnist.test.labels}

		#迭代训练神经网络
		for i in range(TRAINING_STEPS):
			#每1000轮输出一次在训练集上的测试结果
			if i % 1000 == 0:
				#计算滑动平均模型在验证数据上的结果。我也MNIST数据集比较小,所以一次
				#可以处理所有的验证数据。为了计算方便。本程序没有将数据划分为更小的batch.
				#当神经网络模型比价复杂或者验证数据比较大时,太大的batch会导致计算时间过长
				#甚至导致内容溢出的错误
				validate_acc = sess.run(accuracy,feed_dict=validate_feed)
				print("Aftrr %d training step(s),validation accuancy"
					  "using average model is %g"%(i,validate_acc))


				#产生这一轮使用的一个batch训练集,并运行训练过程
				xs, ys = mnist.train.next_batch(BATCH_SIZE)
				sess.run(train_op,feed_dict={x: xs,y_:ys})

		#训练结束之后,在测试数据上检验神经网络模型的最终正确率
		test_acc = sess.run(accuracy,feed_dict=test_feed)
		print("After %d training strep(s),test accuracy using average model is %g"%(TRAINING_STEPS,test_acc))
		 

#主程序入口
def main(argv=None):
	#声明处理MNIST数据集的类,这个类在初始化数据时会自动下载数据
	 mnist = input_data.read_data_sets("/path/to/MNIST_data/",one_hot=True)
	 train(mnist)

#Tensorflow提供一个主程序入口。tf.app.run()会调用上面定义的main函数
if __name__ == '__main__':
	#这句话的意思就是,当模块被直接运行时,以下代码块将被运行,当模块是被导入时,代码块不被运行。
	tf.app.run()
三、结果总结
Tensorflow基础知识梳理(一)_第2张图片


经过了280s的运行,最终该模型在测试数据集上取得的平均精确度为92.8%,经过实验发现,最后的精确度和隐藏层           神经元的个数,基础学习率的选取,衰减率的设置,优化方法的选取,batch大小的设置等均有密切关系,因此除了有一个好的模型之外,初始数据的选取还需要下功夫。

你可能感兴趣的:(Tensorflow学习)