本文主要是对mnist手写数据集这中的迷糊数字进行识别,在Softmax Regression基础上建立了一个较为简单的机器学习模型。

通过这篇文章,可以对神经网络有一个大体的了解,还可以掌握简单的图像识别技术,本章的图片来源是于一个开源的训练数据集(mnist)。

分以下几个部分来进行:

  1. 导入数据集。

  2. 分析mnist样本特点定义变量。

  3. 构建模型。

  4. 训练模型并输出中间状态参数。

  5. 测试模型。

  6. 保存模型。

  7. 读取模型。

一、导入手写图片的数据集

(1) mnist数据集

    mnist数据集里面包含各种手写数字图片,如下图一所示:

mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist

它包含每一张图片对应的标签,告诉我们这个是数字几,并对下面的四张图片打上标签5,0,4,1

 

   (2) 利用TensorFlow代码下载mnist数据集

     通过TensorFlow所提供的库mnist ,进行下载minst数据集:

  •  
# -*- coding: utf-8 -*-# !/usr/bin/env python# @Time    : 2019/5/17 17:03# @Author  : xhh# @Desc    :  minist数据集下载# @File    : mnist_data_load.py# @Software: PyCharmfrom tensorflow.examples.tutorials.mnist import  input_dataimport pylab
mnist = input_data.read_data_sets("MINST_daya/", one_hot=True)print("输入数据:",mnist.train.images)print("数据的shape:",mnist.train.images.shape)
# 展示数据集中的一张图片im = mnist.train.images[1]im = im.reshape(-1,28)pylab.imshow(im)pylab.show()

运行上面的代码,会自动下载数据集,并将文本文件解压到当前所在的同级目录下的MNIST_daya文件夹下

注意:代码中的one_hot=True,表示将样本标签转化为one_hot编码

one_hot编码:假如一共有10类编码(比如说0,1,2,3,4,5,6,7,8,9)。0的one_hot为1000000000, 1的one_hot为0100000000,2 的one_hot为0010000000....依次类推,只有一个位为1,1所在的位置就代表着第几类。

运行结果:

  mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist_02

               mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist_03


   

    看到上面的打印出来的训练集的图片信息,是一个55000行,784列的矩阵,也即训练集里面有55000张图片,每张的图片就是1行784(28*28)列的数据,括号中的每一个值代表一个像素。

    mnist数据集如上图的彩色图片数字3所示,为彩色图片,它是3通道的,由RGB(红、黄、蓝)构成,图一的是黑白的是单通道图片,数值为0~255之间的数字,代表其颜色的深度。

(3)mnst数据集的组成

      在MNIST训练数据集中,mnist.train.images是一个形状为[55000,784]的张量。其中,第1个维度数字用来索引图片,第2个维度数字用来索引每张图片中的像素点。此张量里的每一个元素,都表示某张图片里的某个像素的强度值,值介于0~255之间。

 MNIST里包含3个数据集:

第一个是训练据集,另外两个分别是测试数据集(mnist.test)和验证数据集(mnist.validation)如下图就是下载下来的mnist数据集压缩包:

mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist_04

二、分析图片的特点,定义变量

     由于输入图片是个550000×784的矩阵,所以先创建一个[None,784]的占位符x和一个[None,10]的占位符y,然后使用feed机制将图片和标签输入进去。

代码如下:

  •  
from tensorflow.examples.tutorials.mnist import  input_dataimport pylabimport tensorflow as tf
mnist = input_data.read_data_sets("MINST_daya/", one_hot=True)
tf.reset_default_graph()
# 定义占位符x = tf.placeholder(tf.float32, [None, 784]) # mnist data 维度28*28=784y = tf.placeholder(tf.float32, [None, 10]) #0-9 数字 ==>10class

   在定义占位符时,x和y中的None,表示此张量的第一个维度可以是任何长度的。x代表能够输入任意数量的mnist图像,每张图可以展成784维的向量。

三、构建模型

(1) 定义学习参数

    在TensorFlow里,使用Variable来定义学习参数。模型也需要权重值和偏置量,它们被统一叫做学习参数一个Variable代表一个可修改的张量,定义在TensorFlow的图(一个执行任务)中,其本身也是一种变量。使用Variable定义的学习参数可以用于计算输入值,也可以在计算中被修改。

  •  
# 定义学习参数# 设置模型的权重W = tf.Variable(tf.random_normal([784, 10]))  # W的维度是[784, 10]b = tf.Variable(tf.zeros([10]))

在这里赋予tf.Variable不同的初值来创建不同的参数。一般将W设为一个随机值,将b设为0。

(2)  定义输出节点

有了输入和模型参数,接着便可以将它们串起来构建成真正的模型。

  •  
# 定义输出节点, 构建模型pred = tf.nn.softmax(tf.matmul(x, W) + b)  # softmax分类

首先,用tf.matmul(x,W)表示x乘以W,这里x是一个二维张量,拥有多个输入。然后再加上b,把它们的和输入tf.nn.softmax函数里。至此就构建好了正向传播的结构。也就是表明,只要模型中的参数合适,通过具体的数据输入,就能得到我们想要的分类。

(3) 定义反向传播结构

  •  
# 定义反向传播的结构,编译训练模型,得到合适的参数cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred), reduction_indices=1))
# 参数设置learning_rate = 0.01# 使用梯度下降优化器optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

对反向传播结构的理解:

  1. 将生成的pred与样本标签y进行一次交叉熵的运算,然后取平均值。

  2. 将这个结果作为一次正向传播的误差,通过梯度下降的优化方法找到能够使这个误差最小化的b和W的偏移量。

  3. 更新b和W,使其调整为合适的参数。整个过程就是不断地让损失值(误差值cost)变小。因为损失值越小,才能表明输出的结果跟标签数据越相近。当cost小到我们的需求时(可以自己定),这时的b和W就是训练出来的合适值。

(4) 训练模型并输出中间状态参数,并且进行模型的保存与测试定义状态参数

  •  
training_epochs = 25   # 将整个训练样本迭代25次batch_size = 100    # 在训练过程中每次随机抽取100条数据进行训练display_step = 1   # 迭代的步数saver = tf.train.Saver()model_path = "mnist/521model.ckpt" # 模型保存的位置

启动session:

  •  
# 开始训练with tf.Session()  as sess:    # 初始化节点    sess.run(tf.global_variables_initializer())
# 启动循环开始训练 for epoch in range(training_epochs): avg_cost = 0. total_batch = int(mnist.train.num_examples/batch_size) # 遍历全部的数据集 for i in range(total_batch): batch_xs, batch_ys = mnist.train.next_batch(batch_size) # 运行和优化节点的损失函数值 _, c = sess.run([optimizer, cost], feed_dict={x:batch_xs, y: batch_ys}) # 计算平均损失值 avg_cost += c / total_batch
# 显示训练中的详细信息 if (epoch+1) % display_step ==0: print("Epoch:","%04d"%(epoch+1), "cost=",'{:.9f}'.format(avg_cost))
print("训练成功!!")
# 模型测试 correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) # 计算准确率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) print("准确度:",accuracy.eval({x:mnist.test.images, y:mnist.test.labels}))
# 保存模型的权重 save_path = saver.save(sess, model_path)    print("模型文件在:%s"%save_path)

最终的运行结果:

Epoch: 0001 cost= 8.658398746
Epoch: 0002 cost= 4.599675331
Epoch: 0003 cost= 3.098299387
Epoch: 0004 cost= 2.414841038
Epoch: 0005 cost= 2.031551510
Epoch: 0006 cost= 1.787429208
Epoch: 0007 cost= 1.617599975
Epoch: 0008 cost= 1.491779541
Epoch: 0009 cost= 1.394358738
Epoch: 0010 cost= 1.316281419
Epoch: 0011 cost= 1.251967654
Epoch: 0012 cost= 1.197913221
Epoch: 0013 cost= 1.151722029
Epoch: 0014 cost= 1.111743248
Epoch: 0015 cost= 1.076424035
Epoch: 0016 cost= 1.045415161
Epoch: 0017 cost= 1.017401275
Epoch: 0018 cost= 0.992323116
Epoch: 0019 cost= 0.969426456
Epoch: 0020 cost= 0.948599738
Epoch: 0021 cost= 0.929346439
Epoch: 0022 cost= 0.911827402
Epoch: 0023 cost= 0.895336545
Epoch: 0024 cost= 0.880129020
Epoch: 0025 cost= 0.865876571

 

在最后对模型保存:
模型文件在:mnist/521model.ckpt

mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist_05

四、读取模型,并进行测试

  •  
# 读取模型print("启动第二次session")with tf.Session() as sess2:    # 初始化参数    sess2.run(tf.global_variables_initializer())    #从保存的模型中获取权重    saver.restore(sess2, model_path)
# 测试 model correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) # 计算准确率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) print("准确度:",accuracy.eval({x:mnist.test.images, y:mnist.test.labels}))
output = tf.argmax(pred, 1) batch_xs, batch_ys = mnist.train.next_batch(2) outputval, predv = sess2.run([output, pred], feed_dict={x:batch_xs}) print(outputval, pred, batch_ys)
im = batch_xs[0] im = im.reshape(-1, 28) pylab.imshow(im) pylab.show()
im = batch_xs[1] im = im.reshape(-1, 28) pylab.imshow(im)    pylab.show()

最终的运行结果:

准确度: 0.8296
[0 2] Tensor("Softmax:0", shape=(?, 10), dtype=float32) [[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.][0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]]

mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist_06mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist_07

我们可以看到在测试集中随机取到两个数字进行预测的时候,在这里取的是0和2预测结果与所打的标签是相同的,对应的总的准确度有80%。

 

到此mnist手写数据集识别就完成了。

 

 

mnist手写数字识别(TensorFlow-GPU)------原理及源码_mnist_08