Python :MNIST手写数据集识别 + 手写板程序
可以帮写大报告和课程设计!联系方式qq2099890266
所有的工程文件百度云连接,包含模型!
链接:https://pan.baidu.com/s/1RlS0aVPOFwmNBPBHmcF0SQ
提取码:MATR
–来自百度网盘超级会员V3的分享
注意:人工智能预测的闪退问题是在main文件同目录下没有image_rgzn的文件夹,添加就好。
一、背景与总概
利用Python语言编写和调试一个识别手写数字图像的三层深度前馈网络,包括数据预处理,网络模型构建,模型参数初始化和正向推理,反向梯度下降参数寻优,最后模型预测的功能。目的是学会基本的深度网络模型建立、训练和推理过程,理解深度网络的实现原理。
通过自己学习人工智能之后,发现了三个的重要经验和总结,第一个是你对你研究事物本质的理解;第二个是,将你研究事物进行数据化,找到一个合理的数据表示以及数据的结构;第三个是,寻找与这个数据表示的形式和结构合适的“模型”(即模型算法等)。依据上面数据到模型的这个思路,对下文进行一个描写
首先,介绍一下MNIST手写数据集,这就是我们研究的事物了。该数据集包含60,000个用于训练的示例和10,000个用于测试的示例。数据集包含了0-9共10类手写数字图片,每张图片都做了尺寸归一化,都是28x28大小的灰度图。
训练集图像:train-images-idx3-ubyte.gz(9.9MB,包含60000个样本)
训练集标签:train-labels-idx1-ubyte.gz(29KB,包含60000个标签)
测试集图像:t10k-images-idx3-ubyte.gz(1.6MB,包含10000个样本)
测试集标签:t10k-labels-idx1-ubyte.gz(5KB,包含10000个标签)
下图展示一些具体例子:
其次是手写板程序,在PyQt5实例 画板小程序_pyqt5画图板_CreatorGG的博客-CSDN博客的程序基础之上添加了,1人工智能预测,2预测结果展示的文本框。
传统机器学习的问题与缺陷随着深度学习的发展被得到解决,深度学习也可以说是神经网络的重命名,他是建立在多层非线性的神经网络结构之上,对数据表示进行抽象的一系列机器学习。深度学习的出现使得图像,语言得到突破性的发展。本此处理的数据为图像,所以最后我本次选用的模型是人工智能深度神经网络(一般的神经网络)。你也可以使用卷积神经网络模型,卷积神经网络是对将局部的特征十分的敏感,正确率会更高。
二、研究对象
在你的PycharmIDE里创建一个function.py的文件,在里面定义如下函数:
1:jiexi_image(path),此函数需要一个字符串对象的输入,是两个训练集和测试集的图像文件地址,返回的对象是一个numpy.array的对象。
1 | def jiexi_image(path): |
2: jiexi_label(path) ,传入参数是训练集和测试集的两个label标签文件地址,是一个字符串对象,返回的也是一个numpy.array的对象。
1 | def jiexi_label(path): |
3:plot_data(images,labels,n,issave = False),传入图像,image是一个numpy.array对象;传入的标签,labels是一个numpy.array对象;传入的issave是一个判断逻辑值,如果是真就保存图片,但是一般是不保存的。
1 | def plot_data(images,labels,n,issave = False): |
接下来在你的工程文件夹下建立一个train.py 文件,在里面利用function.py里你设定的函数来解析训练集图像和测试集图像,训练集标签和测试集标签,然后利用plot_data函数打印数据,查看是否对应。
1 | import function |
最终效果:
可以看出是正确的。
三、数据表示与结构
既然train_image, train_lable, teat_image , test_lable 是numpy.array对象,那么我们就可以对他进行操作,对他进行打印输出,print(train_image):
什么也看不出来,那我们打印一下他的维度来看看, ,是一个三维数组。
打印train_image[0]来看:
然后可以推知,我们要处理的对象结构是如下图所示。
四、选择的模型
传统机器学习的问题与缺陷随着深度学习的发展被得到解决,深度学习也可以说是神经网络的重命名,他是建立在多层非线性的神经网络结构之上,对数据表示进行抽象的一系列机器学习。深度学习的出现使得图像,语言得到突破性的发展。本此处理的数据为图像,所以最后我本次选用的模型是人工智能深度神经网络(一般的神经网络)。你也可以使用卷积神经网络模型,卷积神经网络是对将局部的特征十分的敏感,正确率会更高。
在你的工程文件下创建一个DeepNET.py的文件,里面是深度神经网络所需要的各种函数。从零开始,从理论到代码实现无论是在研究和学习都是十分有帮助的,希望我和各位读者都保持住这个习惯。
本次,假设你已经有一定的知识储备了,如梯度下降法的本质,神经网络结构基本清楚,如果不清楚就十分推荐,deeplearning的吴大师的视频教程 [双语字幕]吴恩达深度学习deeplearning.ai_哔哩哔哩_bilibili 教的非常细致。
第一步,导入库,在DeepNET.py的文件里完善搭建深度神经网络所需要的函数。
深度神经网络概述,Deep Neural Networks, 深度神经网络,以下简称DNN。DNN里最基本的单元是神经元模型。每个神经元与其他神经元相连,当他“兴奋”时,就会向相连的神经元发送物质,改变神经元的电位。如果某个神经元的电位超过了一个阀值,那么它就会被激活。结果抽象可以得到沿用至今的M_P神经元模型。
线性部分,是简单的相乘相加,激活部分是利用激活函数处理得到输出。常见的激活函数有sigmoid,relu等,本次采用的激活函数是relu函数。
由神经元组成的多层神经网络,如图所示。有输入层,输出层以及中间隐含层。每一个输入线性求合,通过激活函数,传到下一个神经元,我们大可不必一个个的去算,我们可以使用向量化来使得我们的程序更加简洁。
梯度下降法:
(下面为了简单我以输入的对象是28*28规格图片,第一层隐含单元有200个,第二层隐含单元是100个,输出层为10个的网络结构阐述。)
一般的构造网络的流程:
初始化超参数(包括启动深度神经网络的权值w,偏执b)–》向前传播(线性部分+激活函数)–》 计算代价 --》 反向传播 (激活函数反向,线性部分反向)–》更新超参数.
基础部分和总概 网络结构为 [28*28 200 100 10]
学习人工智能,应该理论应用于实践,应该多动手进行数学演算,将演算用代码实现,最后进行总结于改进。
(1)对这个网络的结构要有一个清楚的认识
在草稿本上进行矩阵维数的测试
下面是对于想要了解代码一个个看清楚流程的去看,如果想直接跑通,代码在最后!
1、导入库,是导入一些必要的库
1 | import matplotlib.pyplot as plt |
2、定义所需要的softmax函数
1 | def sigmoid(Z): |
在此我把relu和sigmoid函数也给出,方便读者后续的使用,可以利用这个去做逻辑回归啊什么什么的,增加泛用性。
3、初始化参数
使用梯度下降法的首要步骤就是初始化参数,这个点是随机的。
输入的是 layers_dims是一个向量,是你的网络结构。返回的是一个字典对象parameters,里面有超参数w和b。、
恭喜你,走出了第一步,完成了初始化参数的步骤。
1 | def init_W(layers_dims): |
4.1、向前传播之线性部分
,也就是输入x与权值相乘与偏执相加。是一层的线性部分。
1 | def L_forword_sum(W,A,b): |
4.2、向前传播之激活函数向前
隐含层使用的是relu函数,输出层使用的是softmax函数,参考(311条消息) 入门级都能看懂的softmax详解_bitcarmanlee的博客-CSDN博客。
(311条消息) ReLU函数简介_潇湘_AQ的博客-CSDN博客
本函数是基于线性部分建立的一个输入是A_prev是上一层的输出,W,b是本层的网络参数,activation是激活函数的名字,用于选择用哪一个函数。返回值是一个元组,包含A隐含层输出的激活值,和用于反向传播时的重要数据。
1 | def L_activate_forworld(A_prev,W,b,activation): |
4.3、向前传播函数接口
线性部分+激活函数组成一次向前传播,线性部分的输出输入到激活函数最后得到的最终值。
函数输入x是初始的输入值即图片的大小,parameters是超参数字典。经过一个for循环可以完成整个向前传播。
恭喜你,你的网络利用这个函数就可以进行向前传播了。
1 | def L_forword(X, parameters): |
5、计算代价之交叉熵代价函数
(311条消息) 交叉熵损失函数(Cross Entropy Loss)_SongGu1996的博客-CSDN博客
你可以计算你的网络的代价了,每个网络都希望做到收敛快,代价小。
1 | def cost(Y_out,Y): |
5.1、反向传播之线性部分的反向
感兴趣的可以到我的草稿上看。
1 | def linear_backward(dZ, cache): |
5.2、反向传播之激活函数的反向
感兴趣的可以到我的草稿上看。
1 | def linear_activation_backward(dA, cache, Y,activation="relu"): |
5.3、 反向传播函数接口
将激活函数的反向和线性部分的反向组织好后,封装为一个反向函数接口。
恭喜你,你已经做好了反向传播了。
1 | def L_model_backward(AL, Y, caches,case): |
6、利用梯度下降法 更新参数
梯度下降法是一个十分好的优化算法,他的目的更改参数使代价优化到最小。
1 | def update_parameters(parameters, grads, learning_rate): |
7、神经网络搭建
依据下面的过程,将你的函数,像拼拼图一样做出来。
初始化超参数(包括启动深度神经网络的权值w,偏执b)–》向前传播(线性部分+激活函数)–》 计算代价 --》 反向传播 (激活函数反向,线性部分反向)–》更新超参数
for循环是来进行重复训练的。.
X, 输入的样本集;Y,label集;
net_layers,网络结构;learning_rate=0.0075, 学习率;num_iterations=3000,迭代次数;step =1, 步长;print_cost=False, 是否打印代价;isPlot=True,是否绘制代价—迭代次数图;
1 | def deepnet(X, Y,net_layers,learning_rate=0.0075, num_iterations=3000,step =1, print_cost=False, isPlot=True): |
8、测试集合测试
将得到的模型,用于测试集看准确率。
1 | def predict(X, y, parameters,Y_org): |
9、保存模型
你所训练好的网络不仅仅只是训练好就完了,你要应用它,就得保存下来,我这里有两个保存函数,一个是保存为txt文本,一个是保存为h5文件,建议使用h5文件,也可以像vvg19那样使用.mat文件数据,只要是数据,你就可以打开,打开的接口可以自己写,如果自己写的话一般是学习其结构,转化为二进制在转化为你想要的数据,不过,基本有大佬写出来了,不要闭门造车。
1 | def save_model(parameters): |
10、利用模型预测和读取h5数据格式的模型
保存好了数据,就是如何读取我们的网络参数,进行运用人工智能深度神经网络。利用这两个函数就可以。
1 | def predict1(X, parameters): |
第二步,有了相应功能的函数,我们就可以进行训练。train.py里的具体内容如下。
1 | import DeepNET |
五、效果展示
(1)训练情况
(2)模型保存情况 h5数据情况
最终效果
综合来说,没有加优化正确率也是不错的,感兴趣的可以对网络进行优化。
六、画板部分
这里参考的是(311条消息) PyQt5实例 画板小程序_pyqt5画图板_CreatorGG的博客-CSDN博客
对qtpy5感兴趣的可以去学习一下。
整个手绘板加训练的程序在最后给出。
七、直接抄,直接方向跑!
训练网络,运行train.py。
训练出自己的网络后,使用main.py运行利用使用你的模型。
文件结构和目录:
创建我红线的文件。
(1)function.py代码:
1 | #此文件是一些函数 有加载数据模块 |
(2)DeepNet.py
1 | import matplotlib.pyplot as plt |
(3)train.py
1 | import DeepNET |
(4) main.py
1 | # 加载库 |
使用画板程序之前得跟该你的模型路径名字。就是红色部分。
def yuce(self):
# #标准化图片 获取Y
savePath = “./image_rgzn/test.png”
image = self.__paintBoard.GetContentAsQImage()
image.save(savePath)
img = Image.open(savePath)
img = img.convert(“I”)
img = img.resize((28, 28))
x = np.array(img)
train_image = x.reshape(1, -1).T / 255
w,layer = DeepNET.read_ccs(“./model/model20221119225104.h5”)
p = DeepNET.predict1(train_image,w)
self.__text_out.setText(str(p[0]))
print§
# print(“hello”)
# res = QMessageBox.information(self,“人工智能判断为:”,str§,QMessageBox.Yes|QMessageBox.No)
# res.exec_()
# 读取数据权重
# 预测并输出
1 | ''' |
1 | ''' |
感谢看完的读者,希望你们都可以对编程产生热爱!