MNIST手写体识别任务

回眸只為那壹抹淺笑 提交于 2019-12-05 09:02:00

下面我们介绍一个神经网络中的经典示例,MNIST手写体识别。这个任务相当于是机器学习中的HelloWorld程序。

MNIST数据集介绍

MNIST是一个简单的图片数据集,包含了大量的数字手写体图片。下面是一些示例图片:


MNIST数据集是含标注信息的,以上图片分别代表5, 0, 4和1。

由于MNIST数据集是TensorFlow的示例数据,所以我们不必下载。只需要下面两行代码,即可实现数据集的读取工作:

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)    

MNIST数据集一共包含三个部分:训练数据集(55,000份,mnist.train)、测试数据集(10,000份,mnist.test)和验证数据集(5,000份,mnist.validation)。一般来说,训练数据集是用来训练模型,验证数据集可以检验所训练出来的模型的正确性和是否过拟合,测试集是不可见的(相当于一个黑盒),但我们最终的目的是使得所训练出来的模型在测试集上的效果(这里是准确性)达到最佳。

MNIST中的一个数据样本包含两块:手写体图片和对于的label。这里我们用xsys分别代表图片和对应的label,训练数据集和测试数据集都有xs和ys,我们使用 mnist.train.images 和 mnist.train.labels 表示训练数据集中图片数据和对于的label数据。

一张图片是一个28*28的像素点矩阵,我们可以用一个同大小的二维整数矩阵来表示。如下:


但是,这里我们可以先简单地使用一个长度为28 * 28 = 784的一维数组来表示图像,因为下面仅仅使用softmax regression来对图片进行识别分类(尽管这样做会损失图片的二维空间信息,所以实际上最好的计算机视觉算法是会利用图片的二维信息的)。

所以MNIST的训练数据集可以是一个形状为55000 * 784位的tensor,也就是一个多维数组,第一维表示图片的索引,第二维表示图片中像素的索引(”tensor”中的像素值在0到1之间)。如下图:


MNIST中的数字手写体图片的label值在1到9之间,是图片所表示的真实数字。这里用One-hot vector来表述label值,vector的长度为label值的数目,vector中有且只有一位为1,其他为0.为了方便,我们表示某个数字时在vector中所对应的索引位置设置1,其他位置元素为0. 例如用[0,0,0,1,0,0,0,0,0,0]来表示3。所以,mnist.train.labels是一个55000 * 10的二维数组。如下:


以上是MNIST数据集的描述及TensorFlow中表示。下面介绍Softmax Regression模型。

Softmax Regression模型

数字手写体图片的识别,实际上可以转化成一个概率问题,如果我们知道一张图片表示9的概率为80%,而剩下的20%概率分布在86和其他数字上,那么从概率的角度上,我们可以大致推断该图片表示的是9.

Softmax Regression是一个简单的模型,很适合用来处理得到一个待分类对象在多个类别上的概率分布。所以,这个模型通常是很多高级模型的最后一步。

Softmax Regression大致分为两步(暂时不知道如何合理翻译,转原话):

Step 1: add up the evidence of our input being in certain classes;
Step 2: convert that evidence into probabilities.

softmax函数的作用相当于是一个转换函数,它的作用是将原始的线性函数输出结果以某种方式转换为我们需要的值,这里我们需要0-9十个类别上的概率分布。softmax函数的定义如下:


具体计算方式如下:


这里的softmax函数能够得到类别上的概率值分布,并保证所有类别上的概率值之和为1. 下面的图示将有助于你理解softmax函数的计算过程:


如果我们将这个过程公式化,将得到


实际的计算中,我们通常采用矢量计算的方式,如下:


Softmax Regression的程序实现如下:

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

#载入数据集
mnist = input_data.read_data_sets('MNIST_data',one_hot = True)

#每个批次100张照片
batch_size = 100

#计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size

#定义两个placeholder
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])

#创建一个简单的神经网络,输入层784个神经元,输出层10个神经元
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
prediction = tf.nn.softmax(tf.matmul(x,W)+b)

#二次代价函数
# loss = tf.reduce_mean(tf.square(y-prediction))
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))

#使用梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

#初始化变量
init = tf.global_variables_initializer()

#结果存放在一个布尔型列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
#求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))


with tf.Session() as sess:
    sess.run(init)
    for epoch in range(11):
        for batch in range(n_batch):
            batch_xs,batch_ys =  mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})
        acc = sess.run(accuracy,feed_dict = {x:mnist.test.images,y:mnist.test.labels})
        print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))


运行结果如下图:


总结:该网络只有两层(输入与输出),增加网络的深度准确率会增加,参数的初始化为‘0’,若改为随机初始化也会增加准确率。。。




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!