Mnist手写数字识别,图片上有0-9 10个不同的数字,每个图片是大小为28*28像素的灰度图像。Mnist在机器学习中是个入门学习,相当于学习编程时候的“hello world"。
一、数据集准备
Tensorflow Data 提供了Mnist数据集,可以直接下载数据,并将下载好的数据集存在MNIST-data当中。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
#one-hot向量除了某一位的数字是1以外其余各维度数字都是0
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
我在线下载失败了,所以在官网把数据集下载存到MNIST文件夹中,不用解压。
载下来的数据集分两部分:60000行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test),并且每组数据集又包括手写数字图片和对应的标签,如训练数据集的图片是 mnist.train.images ,训练数据集的标签是 mnist.train.labels。
我们知道图片在计算机中使用像素来表示,这里每张图片都是28 * 28,我们可以用一个数字数组来表示图片,
并且将它拉成一个长度为784的向量。例如下图是4 * 4像素的表示数字7的图片,将它拉成一个长度为16维的向量。
由于训练集中有60000张图片,因此训练数据集可以表示成一个[60000,784]的二维张量,第一个维度索引图片,第二个索引像素点。
用one-hot向量来表示标签数据,在导入数据时,标签不是用指定的0-9的数字出现的,而是以numpy的数组的格式出现的,索引从0开始,例如1用[0,1,0,0,0,0,0,0,0,0]表示。同样的60000张图片,mnist.train.labels 是一个 [60000, 10] 的二维张量。
这些对图片数据的处理不需要手动去做,我们只需要理解。
二、创建模型
Softmax模型一般用于多分类问题上,模型可能推测一张包含9的图片代表数字9的概率是80%,但是判断它是8的概率是5%(因为8和9都有上半部分的小圆),然后给予它代表其他数字的概率更小的值。
那么这个概率是如何得出的呢?
首先对图片像素加权求和,权值为正则属于该类,为负不属于。输入往往带有无关干扰,所以加入偏置b。x代表被拉成长度784的像素输入,W是权值。
然后用softmax函数将其转化成概率
例如 x1=[1,2,3], W1=[0.1,0.2,0.3] ,b1=1, 则Z1=W1*X1+b=2.4
x2=[2,1,3],W2=[0,2,0.1,0.3],b2=2, 则Z2=3.4
模型的代码实现如下:
x = tf.placeholder(tf.float32, [None, 784]) #placeholder是一个占位符,用2维的浮点数张量来表示这些图,[None, 784]表示输入多少张图片(这里每张图片已经被拉成了784维的向量)
W = tf.Variable(tf.zeros([784, 10])) #将一个784行,10列的0矩阵存入变量里,用来初始化权值
b = tf.Variable(tf.zeros([10])) #初始化偏置,[0,0,0,0,0,0,0,0,0,0]
y = tf.nn.softmax(tf.matmul(x, W) + b) #softmax(x*w+b)
W为什么是[784,10]? 因为最后输出有10类(0-9),标签是用one-hot向量表示的,所以是10。矩阵乘法为[None,784]*[784,10]=[None,10]。
三、训练模型
训练模型时要通过一个指标来判断是好是坏,这个指标是是成本或者损失,指标越小,模型越好。这里使用交叉熵成本函数来判断。
例如手写数字为1,假设预测的概率分布y如下,那么它的交叉熵损失为:
确定好损失函数之后,用梯度下降法法来使Loss值最小,从而得到一个最优的模型。代码如下:
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)#梯度下降法以0.01的学习速率最小化交叉熵。
#启动图,初始化所有变量
init=tf.initialize_all_variables()
sess=tf.Session()
sess.run(init)
训练模型
for i in range(1000):#训练1000次
batch_xs,batch_ys=mnist.train.next_batch(100)#按批次训练,随机抓取训练数据中的100个批处理数据点
sess.run(train_stap,feed_dict={x: batch_xs, y_: batch_ys})#feed_dict字典填充,将batch_x和batch_ys分别填充到x,y_这两个占位符中
四、评估模型
tf.argmax()函数 找到某一维上的数据最大值所在的索引值。由于标签向量是由0,1组成,因此最大值1所在的索引位置就是类别标签。tf.argmax(y,1)返回的是模型对于任一输入x预测到的标签值,tf.argmax(y_,1)返回的是真实标签。
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1))#比较预测的标签值和真实标签是否相等,是返回True
为了确定正确预测项的比例,我们可以把布尔值转换成浮点数,然后取平均值。例如,[True, False, True, True] 会变成 [1,0,1,1] ,取平均值后得到 0.75.
accuracy=tf.reduce_mean(tf.cast(correct_prediction,"float"))#reduce_mean取均值,tf.cast将布尔类型转化成float
最后打印结果
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
结果如下: