# 一、题目要求:
采用的数据集著名的“MNIST 数据集”完成一个神经网络的训练和测试,不允许使用 tensorflow 等框架。并用两种不同的 bp 模型做性能对比 (比如一个层数和神经元较少的简单模型和一个层数和神经元较多的复杂模型)。
## 1.1 问题分析:
MNIST 数据集是一系列的手写图片,它们是由 28*28 的像素点构成,所以这里在设计神经网络时的输入节点数就是 28*28=784 个节点,输出节点设计为 10 个每一个结点对应 0-9 的一个数字,第几个节点的输出值最大,就判定输出结果为节点对应序号。将神经网络包装为一个类,它的层数可自定义,每层的节点个数也可自定义。
## 1.2 问题解决:
首先合理的加载训练集的文件,将每个图片数据格式化为 784*1 的 numpy 数组,标签数据格式化为 10*1 的 numpy 数组:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/4922ce34c2659692665f211822bead02.writebug)
在加载 labels 数据时,需要将原本的 0-9 转化为十位的 numpy 数组,为 1 的那一位的下标就代表真实标签,其余位均为 0。在加载 images 数据时,由于原始数据中游的数据偏大,若不改变数据大小会导致计算激活函数时溢出,又因为图片数据每一位均在 0-255 之间,但统一除以 255 后发现当神经元个数达到一定数目或层数增加时还是会计算溢出,于是决定统一除以 2550。
然后就可以开始编写神经网络类了。在构造函数中,我们定义 numNeuronLayers,learningrate, numNeurons_perLayer 来初始化网络层数,学习率和每层神经元个数,初始权重值为均值为 0,标准差为<img src="https://www.writebug.com/myres/static/uploads/2022/1/12/286c42a4c2bf542710bcc808fe68fb10.writebug" style="zoom:80%;" />的正态分布,<img src="https://www.writebug.com/myres/static/uploads/2022/1/12/e5ed4c1d9d0956c39fb049e8fc5b86db.writebug" style="zoom:80%;" />为当前输出层的节点数,这里之所以采用这样的初始化方式,若直接采用标准正态分布的方式,则可能出现以下问题:
假设一个输入样本(特征向量 x,维度为 1000),一半为 1,一半为 0(这样的假设很特殊,但也很能说明问题),根据前向传递公式,z=500,z 即为输入层向中间隐层第一个神经元的输入。因为输入的一半为 0 的缘故,权重初始化为独立同分布的标准高斯随机变量,z 为 500 个标准正态随机变量的和,由独立随机变量和的方差等于方差的和可知,因此 z 的分布服从 0 均值,标准差为<img src="https://www.writebug.com/myres/static/uploads/2022/1/12/10954c1f6d68031a2d1904fe3c78adb0.writebug" style="zoom:80%;" />≈22.4,标准差从 1 升高到 22.4,由高斯密度函数可知,方差越大,密度函数的分布越扁平,也即分布越均匀而不是集中在一段区域,其概率密度函数为(可见十分平坦):
![](https://www.writebug.com/myres/static/uploads/2022/1/12/7119a97563718a0c2b180649e99d46cf.writebug)
因为概率密度函数较为均匀,z 的值就不会像 N(0,1)那样集中于均值附近(越远离均值中心,密度值会迅速衰减),而会以更大的概率取更大的值。这中初始化机制可能带来 |z||z| 取值很大,也即 z>>1 或者 z<<-1,相应的该神经元的 activation 值就会接近 0 或者 1,而我们知道,如下图示,激活函数越靠近 0 或者 1 其变化率越小,也即是达到一种饱和(saturate)状态。
![](https://www.writebug.com/myres/static/uploads/2022/1/12/a5992070681f78f0bb352fc0131f6e46.writebug)
也就意味着,在相同学习率的前提下,梯度变化更小,学习速度越慢,会导致模型收敛越慢。
而如果更改为均值为 0,标准差为<img src="https://www.writebug.com/myres/static/uploads/2022/1/12/4e03a6d2ae84d9dffc2c71dfe1f8f319.writebug" style="zoom:80%;" />的正态分布,在之前的例子中,概率密度函数的标准差就会变为<img src="https://www.writebug.com/myres/static/uploads/2022/1/12/4ca6a894f159ef52149608241a696da0.writebug" style="zoom:80%;" />≈0.7,权值的分布就会变得陡峭:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/af295512f5569a8d8a8754e8eccb1f6d.writebug)
这样模型的收敛速度也会加快。
还有就是激活函数的定义,这里激活函数采用“S”型函数。
以下是神经网络类构造函数的代码:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/a92a70b1f1b383f35f06a9e3b933d639.writebug)
接下来定义训练函数 update:
首先是前向传播代码的编写:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/36c8b2c2943dab11103c0cebd143342f.writebug)
根据定义的神经网络层数,遍历每一层节点,根据激活函数和输入值算出输出值,并保存在 outputs 列表中(outputs[0]为 inputnodes)。
有了前向传播的输出值,我们就可以计算每层的误差:
对于输出层的误差,我们可以用 targets-outputs[-1]得到,也就是目标值减输出层的输出,对于隐藏层的误差,我们可以用当前层与下一层之间的权值矩阵乘下一层的误差矩阵得到:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/beca5f9eb5b244da169a1c7192e38e30.writebug)
有了每一层的误差值,我们就可以更新各层权值了:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/bf9258719a6b5a450cfac0dd50690cba.writebug)
更新规则为之前权值 + 学习率*误差*第二层输出*(1-第二层输出)*第一层输出,f(x)*(1-f(x))即为激活函数 f(x)的导函数,更新过程从后向前进行。
最后是测试函数的编写,思路就是将测试用例作为输入,让模型走一遍前向传播过程得到输出,然后返回输出结果是否与测试用例标签一致:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/fa1f46214e13644c31518a2602e9582b.writebug)
在 main 函数中载入训练集和测试集,神经网络定义为三层,输入层节点为 784,隐藏层节点为 30,隐藏层的节点个数选择,我参考了别人的经验公式 m=<img src="https://www.writebug.com/myres/static/uploads/2022/1/12/c0d409ba0b2196dd438dccb7b3c826a2.writebug" style="zoom:80%;" />,其中 n 为输入层节点数,l 为输出层节点数,α一般取 1-10,同时,我将回合数设为 30,因为在学习过程中,反向传播时一开始梯度下降应较大,让训练速度加快,随着训练的进行,训练结果越来越接近正确值,所以应逐步减少学习率,从而防止随着回合数增加,模型跳过最优值,造成模型不收敛,甚至发散的结果,但学习率太低又会造成训练速度过慢的缺陷,如果是深入研究的话,是可以根据损失函数的变化找到最优学习率的,这里由于是刚刚入门机器学习,所以简单地随着训练轮数增加降低学习率,当回合进行到 30 时,学习率减少一个数量级:
![](https://www.writebug.com/myres/static/uploads/2022/1/12/86c3d6d229f52c71e9c12bfa50ea3f7d.writebug)
最终得到的识别率结果为 96.42%。
![](https://www.writebug.com/myres/static/uploads/2022/1/12/3c2e122b058e6c995f6cc62248c4f72a.writebug)
接下来我们进行调超参数的工作,首先考虑增加神经网络隐藏层的个数,将隐藏层设为两层,由于层数的增长让程序运行时间急剧增加,所以这里将训练回合将为 5 后做对比。第一层隐藏层设为 100 个节点,第二个隐藏层设为 20 个节点,学习率依然是 0.3。最终的识别结果为 96.15%。
![](https://www.writebug.com/myres/static/uploads/2022/1/12/f329d6be57b935c6d621a8f5b7a5f69a.writebug)
而同样经过 5 个回合训练的三层神经网络(隐藏层节点数为 30)的
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
采用的数据集著名的“MNIST 数据集”完成一个神经网络的训练和测试,不允许使用 tensorflow 等框架。并用两种不同的 bp 模型做性能对比 (比如一个层数和神经元较少的简单模型和一个层数和神经元较多的复杂模型)。
资源推荐
资源详情
资源评论
收起资源包目录
100011325-基于Python 实现一个神经网络的训练和测试(无框架).zip (9个子文件)
bpneuralnetworktest
LICENSE 1KB
train-images.idx3-ubyte 44.86MB
t10k-images.idx3-ubyte 7.48MB
train-labels.idx1-ubyte 59KB
作业四实验报告赵虎201600301325.docx 420KB
Neural_Network.py 5KB
classificationforNN.txt 0B
t10k-labels.idx1-ubyte 10KB
README.md 9KB
共 9 条
- 1
资源评论
神仙别闹
- 粉丝: 2705
- 资源: 7631
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Screenshot_20240601_132255.jpg
- Screenshot_20240601_132403.jpg
- Swift语言优质学习资料资源工具与案列应用场景开发文档教程资料.txt
- Screenshot_20240601_132415.jpg
- Fortran语言优质学习资源工具与案列应用场景开发文档.txt
- Oracle ASM + 12c R1 + Linux 6.5安装
- SQL语言优质学习资源工具与案列应用场景开发文档.txt
- PHP语言优质学习资源和工具与案列应用场景和开发文档.txt
- go语言优质学习资源和工具与案列应用场景.txt
- 23957825633dCar.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功