利用Python对MNIST手写数据集进行数字识别

一、编程环境Jupyter Notebook

Jupyter Notebook,之前被称为IPython notebook,是一个交互式的Web应用程序,可以用Python进行编程。它能实时反馈结果,与MATLABd的交互式应用相似。

对于Jupyter Notebook如何进行下载与安装并建立程序在这里就不做过多叙述,由于外网限制,可以通过清华镜像网站下载Anaconda,安装后该软件中就可以使用Jupyter Notebook,下载网址放在下面:

Anaconda下载(https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/)

另外,在看本文章之前,需要对Python有基础的了解,会进行简单的编程与基本的函数库导入操作,对于神经网络算法有基础的认识。

二、MNIST数据集

  1. MNIST介绍
    MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST). 训练集 (training set) 由来自 250 个不同人手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员. 测试集(test set) 也是同样比例的手写数字数据。

人工智能领域大佬Yann LeCun在利用MNIST做过测试,他首次提出了CNN神经网络的概念,并且用神经网络实现了MNIST数字识别的算法,有兴趣的同学可以去查一查他的个人经历,他被誉为CNN之父,他的关于CNN的论文的网盘链接我放在下面,可以看一看。

Jann LeCun的论文链接:https://pan.baidu.com/s/1eDy4aTDlMmQo9UEhmZiUXQ 提取码:igs5

MNIST数据集下载地址http://yann.lecun.com/exdb/mnist/

数据集分为训练集和测试集,训练集有60000条数据,测试集有10000条数据,每一条数据都是由785个数字组成,数值大小在0~255之间,第一个数字代表该条数据所表示的数字,后面的784个数字可以形成28×28的矩阵,每一个数值都对应该位置的像素点的像素值大小,由此形成了一幅像素为28×28的图片。

2、MNIST的预处理

首先下载的数据集是train-images.idx3-ubyte与t10k-images.idx3-ubyte文件,由于本人不会使用该类型的文件进行相应的操作,所以本文对文件进行预处理,使其转换成.csv文件类型,该类型的文件可以用WPS或者office的EXCEL表格直接查看,由于这部分不是文章重点,本文将转换需要的Python代码直接放到下面,读者可直接进行复制并且将下载并解压好的数据集文件与该程序放到同一文件夹下,直接在Jupyter Notebook上运行该程序就可以生成对应的.csv文件。

def convert(imgf, labelf, outf, n):f = open(imgf, "rb")o = open(outf, "w")l = open(labelf, "rb")f.read(16)l.read(8)images = []for i in range(n):image = [ord(l.read(1))]for j in range(28*28):image.append(ord(f.read(1)))images.append(image)for image in images:o.write(",".join(str(pix) for pix in image)+"\n")f.close()o.close()l.close()convert("train-images.idx3-ubyte", "train-labels.idx1-ubyte","mnist_train.csv", 60000)
convert("t10k-images.idx3-ubyte", "t10k-labels.idx1-ubyte","mnist_test.csv", 10000)

同时,本文将转换之后的.csv文件放到下面,供读者下载
链接: https://pan.baidu.com/s/14blvBCnwR6Bs1tYCFk7EgA 提取码: wzht

                 图一  下载后的压缩包解压的MNIST数据集的.csv文件

如上图所示该文件夹中有四个文件,mnist_test.csv是转换后的测试集,mnist_train.csv是转换后的训练集,mnist_test_10.csv是从测试集中选取的十条测试数据,也就是测试集的十个数字,mnist_train_100.csv是训练集的100条数据,也就是训练集的前100个数字。因为我们一开始学习神经网络只需要其中的一小部分训练集与测试集即可,因为如果用的数据过多,每次运行程序都需要耗费很长时间,所以一开始我们是用的是mnist_train_100.csv和mnist_test_10.csv两个文件即可,最后完成神经网络算法的编写之后就可以将程序中的文件换成mnist_train.csv和mnist_test.csv。

3、MNIST数据集的图像输出
为了让读者更直观的感受MNIST数据集,本文对数据集进行了处理,并以数组和图片的形式输出。下面是对应的Python代码与相应的输出结果。

data_file = open("mnist_train_100.csv") # open("文件路径") 该函数用于打开.csv文件,并分配给data_file变量方便使用
data_list = data_file.readlines() # readlines()函数用于读取.csv文件并将其读入到data_list变量中
data_file.close() # 关闭.csv文件,为了防止之后的处理中不小心对原始.csv文件进行修改
len(data_list) # len(变量名)用于检测读取的文件长度
print(data_list[0]) # 运行该语句会直接显示.csv文件中第一个数组的内容

输出结果:


其中第二个输出结果的第一个数字 “5” 代表跟在后面这一串784个数字组成的28×28的像素图片是数字5的手写体。下面我们来输出图片,看看mnist_train_100.csv文件中的第一条数据所形成的数字长什么样。以下是Python代码与相应的输出结果。

import numpy as np  # numpy是矩阵和数组进行运算或其他处理时所需用到的函数库
import matplotlib.pyplot as plt  # matplotlib是图像处理所需用到的函数库
%matplotlib inline  all_values = data_list[50].split(',') # split()函数将第49条数据进行拆分,以‘,’为分界点进行拆分
image_array = np.asfarray(all_values[1:]).reshape((28,28)) # asfarray()函数将all_values中的后784个数字进行重新排列
# reshape()函数可以对数组进行整型,使其成为28×28的二维数组,asfarry()函数可以使其成为矩阵。
plt.imshow(image_array, interpolation = 'nearest')  # imshow()函数可以将28×28的矩阵中的数值当做像素值,使其形成图片
print(data_list[50])  # 打印data_list中的第49条数据,可以看到第一个数字为3,也就是说该条数据表示的手写体为数字3

输出结果:

三、利用神经网络进行MNIST数字识别程序编写

如果有想了解更深的内容与推导过程的读者可以看一本书叫做《Python神经网络编程》,该书是由英国人工智能领域的硕士Tariq Rashid先生编写,本文的大部分内容与感悟都来自于这本书,给予了我很大帮助,另外吴恩达老师的视频课对于我的前期学习也帮助很大。

程序编写与结果输出如下:(以下代码需要有对神经网络的基本认识,并且对Python有基前期的学习)

# code for a 3-layer neural network,and code for learning the MNIST daeaset
# 一个用于MNIST数字识别的三层神经网络程序(输入层,隐藏层,输出层)import numpy as np  # 用于进行数组和矩阵的运算操作
import scipy.special as ssp  # 里面有激活函数sigmoid函数,可以直接调用
import matplotlib.pyplot as plt  # 用于进行数字矩阵的图像输出,该函数库时进行图像处理常用到的函数库
%matplotlib inline# neural network class definition
# 制作一个神经网络算法的类,其名为神经网络,相当于函数库,直接进行调用里面的函数即可。
class neuralNetwork:# initialise the neural network# 对神经网络的参数进行初始化def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate): # 用于类的初始值的设定# set number of nodes in each input, hidden, output layer# 设置节输入层、隐藏层、输出层的节点数  (self表示类所自带的不能改变的内容)self.inodes = inputnodes # 输入层节点数self.hnodes = hiddennodes # 隐藏层节点数self.onodes = outputnodes # 输出层节点数# link weight matrices, wih and who# 设置输入层与隐藏层直接的权重关系矩阵以及隐藏层与输出层之间的权重关系矩阵# (一开始随机生成权重矩阵的数值,利用正态分布,均值为0,方差为隐藏层节点数的-0.5次方,)self.wih = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes)) #矩阵大小为隐藏层节点数×输入层节点数self.who = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes)) #矩阵大小为输出层节点数×隐藏层节点数# learning rate# 设置学习率αself.lr = learningrate# activation function is the sigmoid function# 将激活函数sigmoid定义为self.activation_functionself.activation_function = lambda x: ssp.expit(x) # lambda x:表示快速生成函数f(x) 并将其命名为self.activation_functionpass# train the neural network# 训练数据集所要用到的函数定义为:train()def train(self, inputs_list, targets_list):# convert inputs list to 2d array# 将导入的输入列表数据和正确的输出结果转换成二维矩阵inputs = np.array(inputs_list, ndmin = 2).T # array函数是矩阵生成函数,将输入的inputs_list转换成二维矩阵,ndmin=2表示二维矩阵targets = np.array(targets_list, ndmin = 2).T # .T表示矩阵的转置,生成后的矩阵的转置矩阵送入变量targets# 进行前向传播# calculate signals into hidden layer# 利用导入的数据计算进入隐藏层的数据hidden_inputs = np.dot(self.wih, inputs) # dot()函数是指两个矩阵做点乘# calculate the signals emerging from hidden layer# 利用激活函数sigmoid计算隐藏层输出的数据hidden_outputs = self.activation_function(hidden_inputs)# calculate signal into final output layer# 利用隐藏层输出的数据计算导入输出层的数据final_inputs = np.dot(self.who, hidden_outputs) # dot()函数是指两个矩阵做点乘# calculate the signals emerging from final output layer# 利用激活函数sigmoid计算输出层的输出结果final_outputs = self.activation_function(final_inputs)# 前向传播结束# 进行反向传播# output layer error is the (target - actual)# 计算前向传播得到的输出结果与正确值之间的误差output_errors = targets - final_outputs# hidden layer error is the output_errors, split by weights, recombined at hidden nodes# 隐藏层的误差是由输出层的误差通过两个层之间的权重矩阵进行分配的,在隐藏层重新结合hidden_errors = np.dot(self.who.T, output_errors) # 隐藏层与输出层之间的权重矩阵的转置与前向传播的误差矩阵的点乘# update the weights for the links betwwen the hidden and output layers# 对隐藏层与输出层之间的权重矩阵进行更新迭代self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)),np.transpose(hidden_outputs))# update the weights for the links between the input and hidden layers# 对输入层与隐藏层之间的权重矩阵进行更新迭代self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))pass# query the nerual network# 查询函数,用于在训练算法完成训练之后检验训练所得的权重矩阵是否准确def query(self, inputs_list):# convert inputs lst to 2d array# 将输入的测试集数据转换成二维矩阵inputs = np.array(inputs_list, ndmin = 2).T# 以下程序为计算输出结果的程序,与上面前向传播算法一致(到 return final_outputs结束)# calculate signals into hidden layerhidden_inputs = np.dot(self.wih, inputs)# calculate the signals emerging from hidden layerhidden_outputs = self.activation_function(hidden_inputs)# calculate signal into final output layerfinal_inputs = np.dot(self.who, hidden_outputs)# calculate the signals emerging from final output layerfinal_outputs = self.activation_function(final_inputs)return final_outputs
# 神经网络算法的类定义完毕# number of input, hidden and output nodes
# 设置输入节点数、隐藏层节点数、输出节点数
input_nodes = 784 # 因为有784个像素值(28×28),所以相当于输入有784个
hidden_nodes = 200  # 隐藏层节点数设置为200,可以随意设置,理论上节点数越多,得到的算法准确率越高
# 实际上达到一定值后将会基本不变,而且节点数越多,训练算法所需花费时间越长,因此节点数不宜设置的过多
output_nodes = 10 # 因为从0到9一共十个数,所以输出节点数为10# learning rate
learning_rate = 0.1 # 学习率设置为0.1,可以随意设置,但是经过测试,当为0.1时,得到的算法准确率最高# create instance of neural network
# 建立神经网络的类,取名为"n",方便后面使用
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)# load the mnist training data CSV file into a list
# 将mnist_train.csv文件导入
training_data_file = open("mnist_train.csv", 'r') # ‘r’表示只读
training_data_list = training_data_file.readlines()
training_data_file.close()# train the neural network
# 利用导入的数据训练神经网络算法epochs = 5
# epochs为世代,让算法循环5次for e in range(epochs):# go through all records in the training data set# 遍历所有输入的数据for record in training_data_list:# split the record by the ',' commas# 将所有数据通过逗号分隔开all_values = record.split(',')# scale and shift the inputs# 对输入的数据进行处理,取后784个数据除以255,再乘以0.99,最后加上0。01,是所有的数据都在0.01到1.00之间inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01# create the target output values (all 0.01, except the desired label which is 0.99)# 建立准确输出结果矩阵,对应的位置标签数值为0.99,其他位置为0.01targets = np.zeros(output_nodes) + 0.01# all_values[0] is the target label for this recordtargets[int(all_values[0])] = 0.99n.train(inputs, targets) # 利用训练函数训练神经网络passpass# load the mnist test data CSV file into a list
# 导入测试集数据
test_data_file = open("mnist_test.csv", 'r')
test_data_list = test_data_file.readlines()
test_data_file.close()# test the neural network
# 用query函数对测试集进行检测
# go through all the records in the test data set for record in the test_data_list:
scorecard = 0 # 得分卡,检测对一个加一分for record in test_data_list:# split the record by the ',' comas# 将所有测试数据通过逗号分隔开all_values = record.split(',')# correct answer is first value# 正确值为每一条测试数据的第一个数值correct_lebal = int(all_values[0])print("correct lebal", correct_lebal) # 将正确的数值在屏幕上打印出来# scale and shift the inputs# 对输入数据进行处理,取后784个数据除以255,再乘以0.99,最后加上0。01,是所有的数据都在0.01到1.00之间inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01# query the network# 用query函数对测试集进行检测outputs = n.query(inputs)# the index of the highest value corresponds to out label# 得到的数字就是输出结果的最大的数值所对应的标签lebal = np.argmax(outputs) # argmax()函数用于找出数值最大的值所对应的标签print("Output is ", lebal) # 在屏幕上打出最终输出的结果# output image of every digit# 输出每一个数字的图片image_correct = np.asfarray(all_values[1:]).reshape((28, 28))plt.imshow(image_correct, cmap = 'Greys', interpolation = 'None')plt.show()# append correct or incorrect to listif (lebal == correct_lebal):# network's answer matchs correct answer, add 1 to scorecardscorecard += 1else:# network's answer doesn't match correct answer, add 0 to scorecardscorecard += 0passpass# calculate the performance score, the fraction
# 计算准确率 得分卡最后的数值/10000(测试集总个数)
print("performance = ", scorecard / 10000)

[1] 《Python神经网络编程》 [英]塔里克·拉希德(Tariq Rashid) 人民邮电出版社
[2] https://www.bilibili.com/video/BV164411b7dx
[3]https://blog.csdn.net/simple_the_best/article/details/75267863

利用Python对MNIST手写数据集进行数字识别(初学者入门级)相关推荐

  1. python画cpk图_TensorFlow MNIST手写数据集的实现方法

    MNIST数据集介绍 MNIST数据集中包含了各种各样的手写数字图片,数据集的官网是:http://yann.lecun.com/exdb/mnist/index.html,我们可以从这里下载数据集. ...

  2. 【Keras+计算机视觉+Tensorflow】DCGAN对抗生成网络在MNIST手写数据集上实战(附源码和数据集 超详细)

    需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 一.生成对抗网络的概念 生成对抗网络(GANs,Generative Adversarial Nets),由Ian Goodfellow在2014 ...

  3. 【机器学习】PCA主成分项目实战:MNIST手写数据集分类

    PCA主成分项目实战:MNIST手写数据集分类 PCA处理手写数字集 1 模块加载与数据导入 2 模型创建与应用 手动反爬虫:原博地址 https://blog.csdn.net/lys_828/ar ...

  4. 2.2 Mnist手写数据集

    2.2 Mnist手写数据集 全连接网络:网络层的每一个结点都与上一层的所有结点相连. 多隐层全连接神经网络: 代码如下: 1. 导入必要的模块 import numpy as np import p ...

  5. 基于TensorFlow1.4.0的FNN全连接网络识别MNIST手写数据集

    MNIST手写数据集是所有新手入门必经的数据集,数据集比较简单,训练集为50000张手写图片,测试集为张手写图片10000,大小都为28*28,不用自己下载,直接从TensorFlow导入即可 后续随 ...

  6. 【深度学习】我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)!

    今天我们将使用 Pytorch 来实现 LeNet-5 模型,并用它来解决 MNIST数据集的识别. 正文开始! 一.使用 LeNet-5 网络结构创建 MNIST 手写数字识别分类器 MNIST是一 ...

  7. 我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)!

    大家好,我是红色石头! 在上一篇文章: 这可能是神经网络 LeNet-5 最详细的解释了! 详细介绍了卷积神经网络 LeNet-5 的理论部分.今天我们将使用 Pytorch 来实现 LeNet-5 ...

  8. python实现mnist手写数字识别

    看了<python神经网络编程>,跟着书上敲了一下mnist手写数字的代码,对神经网络有了初步的了解. 此项目为三层神经网络识别,激活函数采用sigmoid函数,数据集为mnist手写数字 ...

  9. 深度学习练手项目(一)-----利用PyTorch实现MNIST手写数字识别

    一.前言 MNIST手写数字识别程序就不过多赘述了,这个程序在深度学习中的地位跟C语言中的Hello World地位并驾齐驱,虽然很基础,但很重要,是深度学习入门必备的程序之一. 二.MNIST数据集 ...

最新文章

  1. C++ : 编译单元、声明和定义、头文件作用、防止头文件在同一个编译单元重复引用、static和不具名空间...
  2. 根据.Net代码自动生成UML Sequence 图。
  3. 当用户控件有异动时,网页某部位作出相应变化
  4. 关于IB_DESIGNABLE / IBInspectable的那些事
  5. python elasticsearch
  6. 没有写入hosts文件权限
  7. Harris及Shi-Tomasi原理及源码【转载】
  8. 阿里云提示微擎被挂图片木马详解
  9. day13【前台】搭建环境
  10. 《一》Android 数据库 SQlite SQLiteOpenHelper
  11. 2020年内蒙古自治区第十五届大学生程序设计竞赛榜单
  12. iCollections—桌面管理工具
  13. 【Unity2D入门教程氵篇】简单制作一个弹珠游戏之制作场景④(设置不可破坏砖块,发布游戏设置)
  14. 开正式发票到底谁交税
  15. 单片机软件设计架构(C语言)
  16. 局域网arp攻击_3分钟告诉你,你是如何在使用公共WIFI时被黑客攻击的!
  17. 帝国cms小程序插件1.0上线,支持百度/微信/抖音等小程序
  18. 【推荐】产品经理需求模板,案例等文档合集15篇
  19. Android 手机功耗解决方案
  20. 卷(一)C++___二刷

热门文章

  1. 在你的iPad上调整图片尺寸
  2. 编译caffe时,遇到问题:无法打开文件“libboost_thread-vc120-mt-gd-1_58.lib
  3. 2020-2-24-数据库的基本使用-1
  4. frozen ui php,推荐几个移动端前端UI框架
  5. 塔望食品品牌策划:预制菜主要竞争品牌分析及研究
  6. 现在不买房子、买股票是最后一批傻子
  7. 科目一模拟考试错题集
  8. 影楼商业级一键修图磨皮插件dr5 下载 免费下载
  9. 厉害了!印度老头:从雅虎挖来陆奇,All in云业务,带领微软重生!
  10. 一文搞定!!!多智能体强化学习的前世今生