MNIST手写数字识别实现

MNIST数据集
  MNIST是一个简单的手写体数字识别数据集,由70000张28×28像素的黑白图片组成(分辨率较小) 。其中的每一张图片都写有0~ 9中的一个数字,任务就是根据图片上的数字对这些图片进行10分类。
  数据集官网地址为http://yann.lecun.com/exdb/mnist/,由以下四部分组成:
  train-images-idx3-ubyte.gz: training set images (9912422 bytes)
  train-labels-idx1-ubyte.gz: training set labels (28881 bytes)
  t10k-images-idx3-ubyte.gz: test set images (1648877 bytes)
  t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes)
 分别为一个训练图片集,一个训练标签集,一个测试图片集,一个测试标签集;这个不是普通的文本文件或是图片文件,而是一个压缩文件,下载并解压出来得到的是二进制文件。训练集中包含了作为训练数据的 60000 张图片,测试集包含了作为测试数据的10000 张图片。
代码


import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# mnist = input_data.read_data_sets("/home/jiangziyang/MNIST_data",one_hot=True)
mnist = input_data.read_data_sets("/mnt/projects/tflearn/chapter6/MNIST_data",one_hot=True)

batch_size = 100                #设置每一轮训练的batch大小
learning_rate = 0.8             #学习率
learning_rate_decay = 0.999     #学习率的衰减
max_steps = 30000               #最大训练步数

#定义存储训练轮数的变量,在使用Tensorflow训练神经网络时,
#一般会将代表训练轮数的变量通过trainable参数设置为不可训练的
training_step = tf.Variable(0, trainable=False)

#定义得到隐藏层和输出层的前向传播计算方式,激活函数使用relu()
def hidden_layer(input_tensor,weights1,biases1,weights2,biases2,layer_name):
    layer1=tf.nn.relu(tf.matmul(input_tensor,weights1)+biases1)
    return tf.matmul(layer1,weights2)+biases2

x = tf.placeholder(tf.float32,[None,784],name="x-input")   #INPUT_NODE=784
y_ = tf.placeholder(tf.float32,[None,10],name="y-output")   #OUT_PUT=10
#生成隐藏层参数,其中weights包含784x500=392000个参数
weights1=tf.Variable(tf.truncated_normal([784,500],stddev=0.1))
biases1 = tf.Variable(tf.constant(0.1,shape=[500]))
#生成输出层参数,其中weights2包含500x10=5000个参数
weights2 = tf.Variable(tf.truncated_normal([500, 10], stddev=0.1))
biases2 = tf.Variable(tf.constant(0.1, shape=[10]))

#计算经过神经网络前向传播后得到的y的值,这里没有使用滑动平均
y = hidden_layer(x,weights1,biases1,weights2,biases2,'y')


#初始化一个滑动平均类,衰减率为0.99
#为了使模型在训练前期可以更新地更快,这里提供了num_updates参数
#并设置为当前网络的训练轮数
averages_class = tf.train.ExponentialMovingAverage(0.99,training_step)
#定义一个更新变量滑动平均值的操作需要向滑动平均类的apply()函数提供一个参数列表
#train_variables()函数返回集合图上Graph.TRAINABLE_VARIABLES中的元素,
#这个集合的元素就是所有没有指定trainable_variables=False的参数
averages_op = averages_class.apply(tf.trainable_variables())
#再次计算经过神经网络前向传播后得到的y的值,这里使用了滑动平均,但要牢记滑动平均值只是一个影子变量
average_y = hidden_layer(x,averages_class.average(weights1),averages_class.average(biases1),
                averages_class.average(weights2),averages_class.average(biases2),'average_y')

#计算交叉熵损失的函数原型为sparse_softmax_cross_entropy_with_logits(_sential, labels, logdits, name)
#它与softmax_cross_entropy_with_logits()函数的计算方式相同,适用于每个类别相互独立且排斥的情况,
#即一幅图只能属于一类。在1.0.0版本的TensorFlow中,这个函数只能通过命名参数的方式来使用,在这里
#logits参数是神经网络不包括softmax层的前向传播结果,lables参数给出了训练数据的正确答案
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=tf.argmax(y_, 1))
#argmax()函数原型为argmax(input, axis, name, dimension),用于计算每一个样例的预测答案,
#其中input参数y是一个batch_size * 10(batch_size行,10列)的二维数组,每一行表示一个样例前向传播的结果,
#axis参数“1”表示选取最大值的操作仅在第一个维度中进行,即只在每一行选取最大值对应的下标。
#于是得到的结果是一个长度为batch_size的一维数组,这个一维数组中的值就表示了每一个样例对应的
#数字识别结果。


regularizer = tf.contrib.layers.l2_regularizer(0.0001)       #计算L2正则化损失函数
regularization = regularizer(weights1)+regularizer(weights2) #计算模型的正则化损失
loss = tf.reduce_mean(cross_entropy)+regularization          #总损失


#用指数衰减法设置学习率,这里staircase参数采用默认的False,即学习率连续衰减
laerning_rate = tf.train.exponential_decay(learning_rate,training_step,mnist.train.num_examples/batch_size,
                                                                                       learning_rate_decay)
#使用GradientDescentOptimizer优化算法来优化交叉熵损失和正则化损失
train_step= tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=training_step)


#在训练这个模型时,每过一遍数据既需要通过反向传播来更新神经网络中的参数又需要
#更新每一个参数的滑动平均值,control_dependencies()用于完成这样的一次性多次操作,
# 同样的操作也可以使用下面这行代码完成:
# train_op = tf.group(train_step,averages_op)
with tf.control_dependencies([train_step,averages_op]):
     train_op = tf.no_op(name="train")


#检查使用了滑动平均值模型的神经网络前向传播结果是否正确。
#equal()函数原型为equal(x, y, name),用于判断两个张量的每一维是否相等,如果相等返回True,否则返回False。
crorent_predicition = tf.equal(tf.argmax(average_y,1),tf.argmax(y_,1))

#cast()函数原型为cast(x, DstT, name)。在这里用于将一个bool型的数据转为float32类型
#之后会将得到的float32 的数据求一个平均值,这个平均值就是模型在这一组数据上的正确率
accuracy = tf.reduce_mean(tf.cast(crorent_predicition,tf.float32))


with tf.Session() as sess:
    #在稍早的版本中一般使用 initialize_all_variables()函数初始化全部变量
    tf.global_variables_initializer().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(max_steps):
        if i%1000==0:
            #计算滑动平均模型在验证数据上的结果。
            # 为了能得到百分数输出,需要将得到的validate_accuracy扩大100倍
            validate_accuracy = sess.run(accuracy, feed_dict=validate_feed)
            print("After %d trainging step(s) ,validation accuracy"
                  "using average model is %g%%"%(i,validate_accuracy*100))

        #产生这一轮使用的一个batch的训练数据,并进行训练
        #input_data.read_data_sets()函数生成的类提供了train.next_bacth()函数,
        #通过设置函数的batch_size参数就可以从所有的训练数据中提读取一小部分作为一个训练batch
        xs,ys = mnist.train.next_batch(batch_size=100)
        sess.run(train_op,feed_dict={x:xs,y_:ys})

    #使用测试数据集检验神经网络训练之后的最终正确率
    # 为了能得到百分数输出,需要将得到的test_accuracy扩大100倍
    test_accuracy = sess.run(accuracy,feed_dict=test_feed)
    print("After %d trainging step(s) ,test accuracy using average"
                  " model is %g%%"%(max_steps,test_accuracy*100))

其中,input_data.read_data_sets函数可以获得上述官网提供的数据集,函数原型如下:

def read_data_sets(train_dir,
                   fake_data=False,
                   one_hot=False,
                   dtype=dtypes.float32,
                   reshape=True,
                   validation_size=5000,
                   seed=None,
                   source_url=DEFAULT_SOURCE_URL):

在调用函数时, 一般只传入train_dir 和 one_hot 参数。其中参数train_dir是放置MNIST数据的路径 ,如果在train_dir路径下没有找到MNIST数据集文件, read_ data_ sets()函数就会调用mnist.py文件中的其他函数在 Yann LeCun 教授的网站下载MNIST数据集文件 。one_hot=True指定是否将样本图片对应到标注信息 。
  同时mnist.py文件中也实现了一些函数来处理MNIST数据,大致的过程是将数据从原始的数据包中解析成训练和测试神经网络时使用的格式,read_ data_ sets()函数也对这些函数进行了调用 。
  由于本地电脑没有储存数据集,所以需要下载,运行代码时,遇到报错:  在这里插入图片描述  这是因为用TensorFlow从官网下载数据集到本地时,pycharm没有写入权限,使用pycharm Terminal运行sudo python3 MNIST.py可以正常执行 。
  read_ data_ sets()函数会返回 一个类,这里将这个类实例命名为mnist 。这个类会自动将 MNIST 数据集划分为train 、 validation和 test 3 个数据集 。其中 train集内有55000张图片, validation集内有5000张图片,这两个集合组成了MNIST本身提供的训练数据集 。
  最终运行结果如下:
  在这里插入图片描述
  上述代码用到了很多的优化方法,如 L2 正则化、滑动平均模型以及学习率衰减等,这些优化方法为提高模型在测试集上的预测正确率做出了一定的贡献。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值