MNIST数字识别问题(一)
TensorFlow
最后更新 2020-08-14 15:49 阅读 6824
最后更新 2020-08-14 15:49
阅读 6824
TensorFlow
关键词: 隐藏层、激活函数、正则化、指数衰减的学习率、滑动平均模型
准备:下载数据集
- tensorflow提供了input_data类可以下载和处理MNIST数据
- 将数据从原始的数据包来解析成训练和测试神经网络时使用的格式,每张图片是一个长度为784的一维数组,数组中每个元素对应图片像素矩阵中的每一个数字,数字的取值范围为[0,1],代表颜色深浅
- mnist.train.next_batch函数可以从训练数据中读取一小部分作为训练batch
from tensorflow.examples.tutorials.mnist import input_data mnist =input_data.read_data_sets("./data/MNIST_data",one_hot=True) print(len(mnist.train.images[0]))
关键点:
1.使用滑动平均模型,将每一轮迭代得到的模型综合起来,从而使最终得到的模型更加健壮
# 定义一个变量用于计算滑动平均,这个变量的初始值为0 v1 = tf.Variable(0,dtype=tf.float32) # step用于模拟神经网络中迭代的轮数,用于动态控制衰减率 step = tf.Variable(0,trainable=False) # 初始化一个滑动平均的类 ema = tf.train.ExponentialMovingAverage(0.99,step) # 定义一个更新变量滑动平均的操作,给定一个列表,每次执行这条语句时,列表中的变量都会被更新 maintain_averages_op = ema.apply([v1]) with tf.Session() as sess: init_op = tf.initialize_all_variables() sess.run(init_op) sess.run(maintain_average_op)
2.指数衰减的学习率,使前期更快收敛,后期更加稳定
global_step = tf.Variable(0) # 通过exponential_decay函数生成学习率 # 0.1表示初始学习率,global_step表示当前迭代轮数,100和0.96表示每100轮学习率*0.96,staircase=True表示 # 按照阶梯递减 learning_rate = tf.train.exponential_decay(0.1,global_step,100,0.96,staircase=True) # 使用指数衰减的学习率,在minimize函数中传入global_step会自动更新global_step参数,从而使学习率也得到更新 learning_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)
3.正则化解决过拟合问题
损失函数中加入刻画模型复杂度的指标,优化的时候优化J(θ)+γR(w),R(w)表示模型复杂度,分为L1正则和L2正则
代码:
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # xs,ys = mnist.train.next_batch(batch_size) # MNIST数据集相关参数 INPUT_NODE = 784 # 输入层节点个数 OUTPUT_NODE = 10 # 输出层节点个数 # 排至神经网络的参数 LAYER1_NODE = 500 # 隐藏层节点数 BATCH_SIZE = 100 # 一个batch训练数据个数 LEARNING_RATE_BASE = 0.8 # 基础学习率 LEARNING_RATE_DECAY = 0.99 # 学习率的衰减率 REGULARIZATION_RATE = 0.0001 # 正则化项在损失函数中的系数 TRAINING_STEPS = 30000 # 训练轮数 MOVING_AVERAGE_DECAY = 0.99 # 滑动平均衰减率 # 给定神经网络的输入和所有参数,计算神经网络的前向传播结果的函数 # 三层全连接神经网络 def inference(input_tensor,avg_class,weights1,biases1,weights2,biases2): """ :param input_tensor: 输入张量 :param avg_class: 用于计算参数平均值的类,方便测试时使用滑动平均模型 :return: """ # 当没有提供滑动平均类时,直接使用参数当前的取值 if avg_class == None: layer1 = tf.nn.relu(tf.matmul(input_tensor,weights1) + biases1) 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') # 生成隐藏层的参数 weithts1 = tf.Variable(tf.truncated_normal([INPUT_NODE,LAYER1_NODE],stddev=0.1)) biases1 = tf.Variable(tf.constant(0.1,shape=[LAYER1_NODE])) # 生成输出层的参数 weithts2 = tf.Variable(tf.truncated_normal([LAYER1_NODE,OUTPUT_NODE],stddev=0.1)) biases2 = tf.Variable(tf.constant(0.1,shape=[OUTPUT_NODE])) # 计算当前参属下神经网络前向传播结果,没有滑动平均 y = inference(x,None,weithts1,biases1,weithts2,biases2) # 定义存储训练轮数的变量 global_step = tf.Variable(0,trainable=False) # 给定滑动平均衰减率和训练轮数的变量,初始化滑动平均类 variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step) # 在所有代表神经网络参数的变量上使用滑动平均 variable_averages_op = variable_averages.apply(tf.trainable_variables()) # 计算使用了滑动平均之后的前向传播结果 average_y = inference(x,variable_averages,weithts1,biases1,weithts2,biases2) # 计算交叉熵作为刻画预测值和真实值之间差距的损失函数 cross_entropy= tf.nn.sparse_softmax_cross_entropy_with_logits(labels=tf.argmax(y_,1),logits=y) # 计算在当前batch中所有样例的交叉熵平均值 cross_entropy_mean = tf.reduce_mean(cross_entropy) # 计算L2正则化损失函数 regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE) # 计算模型的正则化损失 regularization = regularizer(weithts1) + regularizer(weithts2) # 总损失等于交叉熵损失和正则化损失的和 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优化算法来优化损失函数 train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step) with tf.control_dependencies([train_step,variable_averages_op]): train_op = tf.no_op(name='train') # 检验使用了滑动平均模型的网络向前传播结果是否正确 correct_prediction = tf.equal(tf.argmax(average_y,1),tf.argmax(y_,1)) # 将布尔型的数值转换为实数型,然后计算平均值,即为正确率 accuracy = tf.reduce_mean(tf.cast(correct_prediction,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: validate_acc = sess.run(accuracy,feed_dict=validate_feed) print("After %d training step(s),validation accuracy 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 step(s),test accuracy using average model is %g" % (TRAINING_STEPS,test_acc)) # 主程序入口 def main(argv=None): mnist = input_data.read_data_sets("./data/MNIST_data",one_hot=True) train(mnist) # TensorFlow提供的一个主程序入口,tf.app.run会调用上面定义的main函数 if __name__ == '__main__': tf.app.run()
总结:
滑动平均模型和指数衰减的学习率主要影响模型收敛的速度,对正确率影响不明显,正则化对模型正确率影响比较大
赞
讨论
500字
表情
删除确认
是否删除该条评论?
取消
删除