美文网首页
BP神经网络|手写数字识别

BP神经网络|手写数字识别

作者: 大饼与我 | 来源:发表于2020-02-18 19:19 被阅读0次

整体思路:模型搭建--训练--测试--优化

搭建基本模型阶段:

step1:引入要用的包

step2:定义神经网络

step3:定义正向传播训练过程

step4:定义反向传播过程--更新权重

step5:查询网络--输入数据、返回输出

step6:设定各层数量和参数

模型训练阶段

模型测试阶段

模型准度计算以及后续优化


一、搭建基本模型阶段:

step1 导入后面需要用到的包:

为了方便,numpy简记为np,scipy.special简记为ss

numpy包的各种用法:https://blog.csdn.net/cxmscb/article/details/54583415 (非常详细)

scipy包的知识:https://www.jianshu.com/p/6c742912047f

tqdm:Tqdm 是 Python 进度条库,可以在 Python 长循环中添加一个进度提示信息用法

step2:定义神经网络

解释:

涉及到属性的调用,详细知识点请移步:https://www.jianshu.com/writer#/notebooks/4844988/notes/58754235

inputNodes为输入层,hiddenNodes为隐层,outputNodes为输出层,learingRate为学习率

w_ih为输入层与隐层之间的权重; w_ho为隐层到输出层的权重

正态分布的随机数产生

numpy.random.normal(loc=0.0,scale=1.0, size=None)

loc:float 此概率分布的均值(对应着整个分布的中心centre)

scale:float  此概率分布的标准差(对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高)

size:int or tuple of ints    输出的shape,默认为None,只输出一个值

pow() 方法返回 xy(x的y次方) 的值;

lambda表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数

expit函数,也称为logistic sigmoid函数,定义为expit(x)= 1 /(1 + exp(-x))。 它是logit函数的反函数。


step3:定义正向传播训练过程

解释:

inputs=np.array(inputlist,ndmin=2).T 初始输入值为输入列的二维矩阵数据。.T就是转置,简单来说将x和y值交换。后面targets同理。

hiddenInput=np.dot(self.w_ih,inputs) 隐藏层输入值为权重和初始输入值的矩阵积

numpy.dot用法详见:https://www.cnblogs.com/luhuan/p/7925790.html

self.activate 为激活函数方法的调用 ,每次输出时,符合阈值条件的将触发激活函数。

step4:定义反向传播过程--更新权重

权重更新的公式

step5:查询网络--输入数据、返回输出

这里就是实际输入数据了,然后根据数据得到模型预测出来的值。

step6:设定各层数量和参数

神经网络由输入层、隐层、输出层、学习率四个参数构成

inputNodes: 输入层的数量,取决于输入图片(训练和识别)的像素,像素点的数量等于输入层的数量

hiddenNodes: 隐藏层的数量,一般比输入层少,但具体不确定,可根据准确率进行调整

outputNodes: 输出层的数量,等于需要分类的数量。

学习率越大,每次学习变化越大,改变的越多,但接近准确点时无法准确到达

学习率越小,每次学习更改的参数值就越小,只有大量的数据才能习得准确值

需要注意的是:在89个训练集和11个测试集下,inputNodes=307200才能跑。后续加大训练集和测试集,分别达到6万和2万的时候,inputNodes=784.


二、模型训练阶段

多次利用相同的数据训练:tqdm.tqdm一共5个,每次更新1个,一共更新5次

tqbar:遍历循环每个图片的数据矩阵,一共100个,每次更新1个,一共更新100次

图像处理为什么转换为double类型?详见:https://blog.csdn.net/mine_land/article/details/79947734

numpy.asfarrary用法详见:https://docs.scipy.org/doc/numpy/reference/generated/numpy.asfarray.html

numpy.zeros(outputNodes)返回一个给定形状和类型的用0填充的数组;详见:https://blog.csdn.net/qq_26948675/article/details/54318917

输入数据x设置为0-1,最正确的目标值y整数形式设置为0.99


三、模型测试阶段

测试图片用逗号分隔,输出的的识别答案就是Y值,即[0]的索引值。将测试输入转换为double的形式。将测试集数据输入查询网络中得到replyOutput.

numpy.argmax输出的是矩阵的最大值的索引值。如果预测值正确,则输出1,如果预测值不正确,则输出0.

四、优化阶段:

首先测试准确度

在以上的参数下,我们只能得到0.45的准确率,准确率如此之低,我们需要进行优化。

我的优化方方案如下

主要是调整:训练次数、隐层数量、测试集和训练集的数量、学习率

调试方法1 在其他条件不变的前提下,调整迭代次数和隐层数量

调试方法2 在其他条件不变的前提下,调整学习率和隐层数量

调试方法3 根据前面得到的最优组合进一步研究

调试方法4 将训练集和测试集扩大




调试方法1  在其他条件不变的前提下,调整迭代次数和隐层数量

测试集为11,训练集为89,学习率为0.1

通过上图我们可以得到结论:在训练集和测试集较小的时候,搭配0.1的学习率,我们无论如何改变隐层数量和迭代数,都无法提升准确率。

有空白的原因:已经测了19次了,准确率仍然无法上升,提示着我们需要转换思路。

那么接下来提升准确率就将往:扩大训练集、测试集的数量或者改变学习率 这两个方面探索。

接下来我们先尝试改变学习率。



调试方法2 在其他条件不变的前提下,调整学习率和隐层数量

测试集为11,训练集为89,迭代次数为5

通过上图我们发现,在学习率为0.005的条件下,平均准度在所测范围内达到了最高。同时在0.001的学习率下,产生了目前最高的准确度0.82。并且这两者的平均准度也达到了0.6以上,已经较调试方法1的准确率有了0.2以上的增幅了。

综上,我们得到了两个比较合适的学习率:0.005和0.001。

同时,我们可以推测:在上述条件下,当层数达到150以上,准确度会有比较不错的表现



调试方法3 根据前面得到的最优组合进一步研究

我们选取隐层层数在200和300并且在0.001学习率的条件下,研究迭代数对于目前最优的参数组合影响大不大。(训练集为89,测试集为11)

学习率为0.001

同时我们再回顾一下调试方法1的结果:

学习率为0.1

从这两个表格,我们可以得出结论:学习率在0.001和0.1时,和训练集为89、测试集为11时,改变迭代次数对于准确率的影响不大。

我们可以推测:在测试集和训练集的数量较少的情况下,迭代数的增加对于准确度的提升帮助不大。

至此,学习率的影响、迭代数的影响、隐层层数的影响我们都已经讨论过了。那么接下来我们的方向是:改变训练集和测试集的数量大小。



调试方法4 将训练集和测试集扩大

前面的调试方法留给我们的疑问:

①当扩大了训练集和测试集后,迭代数的改变对于准确度的影响大不大?

②当扩大了训练集集和测试集后,学习率的改变和隐层数量的改变的影响又是如何?

在这里首先感谢刘继端同学提供的2万测试集和6万训练集。

疑问1解答:

在扩大后的训练集和测试集下,迭代次数的变化对于准确度的变化影响在0.1之内。这对于找到0.99的准确度还是挺有帮助的,但对于0.9以下的准确率提升作用不大。

疑问2解答:

根据上表,我们可以看出在其他条件不变的情况下,隐层数量越多,准确度越高。同时,在充分大的训练集和测试集的前提下下,学习率越高(但不宜过高),准确度越高。

因此,在扩大了训练集和测试集之后,模型的准确度有了质的飞跃。另外,准确度在隐层数量300-400之间,学习率为0.05-0.1之间准确度会有比较不错的表现。


五、调试结果

通过多次测试,我们发现训练次数、隐层数量、测试集和训练集的数量、学习率这四个是影响准确率的主要因素。其中训练次数的影响力对比其他三个因素较小。训练集和测试集的数量影响最大。

总的来说:

①我们发现隐层的增加确实能增加准确率。但这需要合适的训练次数配合和学习率的配合。并不是隐层越多、学习率越大、训练次数越多就能增加准确率。

②充分大的训练集和测试集对于准确度的提升至关重要

最终,基于以上调试方法,我调试的的最佳参数为:

最优准确率为:

尽力了还是没能调试到0.99.

代码地址:https://gitee.com/kristina666/test.git

相关文章

网友评论

      本文标题:BP神经网络|手写数字识别

      本文链接:https://www.haomeiwen.com/subject/ylaefhtx.html