前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mnist手写数字识别(TensorFlow-GPU)------原理及源码

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

作者头像
andrew_a
发布2019-07-30 15:08:12
5.5K0
发布2019-07-30 15:08:12
举报
文章被收录于专栏:Python爬虫与数据分析

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

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

分以下几个部分来进行:

  1. 导入数据集。
  2. 分析mnist样本特点定义变量。
  3. 构建模型。
  4. 训练模型并输出中间状态参数。
  5. 测试模型。
  6. 保存模型。
  7. 读取模型。

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

(1) mnist数据集

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

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

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

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

代码语言:javascript
复制
# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time    : 2019/5/17 17:03
# @Author  : xhh
# @Desc    :  minist数据集下载
# @File    : mnist_data_load.py
# @Software: PyCharm
from tensorflow.examples.tutorials.mnist import  input_data
import 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所在的位置就代表着第几类。

运行结果:


看到上面的打印出来的训练集的图片信息,是一个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数据集压缩包:

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

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

代码如下:

代码语言:javascript
复制
from tensorflow.examples.tutorials.mnist import  input_data
import pylab
import 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=784
y = tf.placeholder(tf.float32, [None, 10])  #0-9 数字 ==>10class

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

三、构建模型

(1) 定义学习参数

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

代码语言:javascript
复制
# 定义学习参数
# 设置模型的权重
W = tf.Variable(tf.random_normal([784, 10]))  # W的维度是[784, 10]
b = tf.Variable(tf.zeros([10]))

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

(2) 定义输出节点

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

代码语言:javascript
复制
# 定义输出节点, 构建模型
pred = tf.nn.softmax(tf.matmul(x, W) + b)  # softmax分类

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

(3) 定义反向传播结构

代码语言:javascript
复制
# 定义反向传播的结构,编译训练模型,得到合适的参数
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) 训练模型并输出中间状态参数,并且进行模型的保存与测试定义状态参数

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

启动session:

代码语言:javascript
复制
# 开始训练
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

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

代码语言:javascript
复制
# 读取模型
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.]]

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

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

代码获取:扫下面的二维码关注公众号“ python爬虫scrapy”, 后台回复mnist代码,即可获取哦~~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python爬虫scrapy 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、导入手写图片的数据集
  • 二、分析图片的特点,定义变量
  • 三、构建模型
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档