本学期机器学习课程的第二个lab,数据集是UCI的iris数据集,没什么意外,又是C++手撕(就是玩儿?No,是python不会啊)。代码写完挺快的,炼丹过程贼痛苦,最终准确率也不那么高。主要内容是总结我自己实战出的bug,毕竟BP这个相当于机器学习里的Hello World了,算法都被讲烂了。

(代码还是晚点放)

一、iris数据集

bp神经网络数据分类 bp神经网络数据集_归一化


1.数据集介绍

有3个分类,4个特征(具体这分类这特征是啥,我也不知道)。总共150行,三个分类分别是50,50,50,按顺序排好的。

数据集:https://download.csdn.net/download/pvfeldt/18123868?spm=1001.2014.3001.5501

2.乱序问题

因为iris鸢尾花这个数据集是很整齐的按顺序排好的分类,不打乱顺序就会训练着训练着,模型倾向于第三类,不对。之前走的弯路就是高高兴兴跑出来94%的准确率,然后想到可能因为是第三类,再转去判别第一类、第二类的时候就出问题了。

关于C++的乱序,和python选手交流了一下,shuffle函数是都有的,

3.数据集划分比例

一开始的感觉是这个数据集比较小,就划了120行训练集,30行测试集(没有弄验证集)。

走到这一步的时候,我一开始是高高兴兴150行全员乱序,再抽前120行训练,后30行测试,然后发现准确率是飘的一塌糊涂,分析了原因,可能是碰到训练集和测试集每个类占比不一样这种情况。

然后我就去手动搞了一个40,40,40的训练集和一个10,10,10的测试集,但由于在乱序,准确率还是比较飘,并且在某些学习率和训练次数下,集中在60%-70%之间,偶尔会飘到83.3%,但基本上调不出更好的。

最后,我增加了测试集的量,是30,30,30的训练集和20,20,20的测试集,这种情况下基本能稳定在80%的准确率,时间有限,没有再继续换比例调。

二、BP算法

1.前向传播和反向传播

核心算法是这个,我直接copy老师的PPT了。

bp神经网络数据分类 bp神经网络数据集_bp神经网络数据分类_02

bp神经网络数据分类 bp神经网络数据集_数据集_03


有个误差和最大训练次数的概念,如果误差小于某个值(防止过拟合)或者达到最大训练次数就结束,然而我设的误差小于0.1就跳出,实际上每次都会达到最大训练次数再结束。

2.归一化问题

(1)数据初始化归一

我采用的是对每一列的特征进行最大值最小值归一化。

最大值最小值的归一化公式:

X*=(X-Xmin)/(Xmax-Xmin)

把数据卡到0-1范围内。

(2)前向传播进入sigmoid前进行Batch Normalization

之前拿MNIST当数据集的时候(后来换鸢尾花是因为MNIST跑一轮太慢了),就是输入层隐藏层等数据量太大导致梯度消失,所以用Batch Normalization来把数据集调整到较小范围,使sigmoid可以激活。

Batch Normalization的公式:

按我理解是这样的。

X*=(X-E(X))/sqrt(D(X))

就是减去期望,除以方差开方,和概率论里求高斯分布的概率一样。

三、神经网络结构

大把时间调参。。

1.神经网络层数

三层四层都建过,结论是四层并不比三层好。

2.隐藏层节点数

隐藏层也不是越大也好,在合理的范围比较好。目前我是100还比较好,10-20不是太理想,其他的话还有待有空接着调参。

3.学习率和最大训练次数

也是适中比较好。理论上是学习率的话太大震荡问题,太小速度太慢,试下来太大太小是根本达不到很高的准确率。最大训练次数是太小欠拟合,太大过拟合,是一个准确率先增后减的过程。目前我是0.003,900-1100次的时候(误差仿佛是个摆设)可以稳在80%以上。

之前有看到过4x10x3的网络,学习率0.9(???)能达到98%准确率。我试着这样操作过,但是并不能做到,对我来说好像0.01这个数量级就挺大的了。。

四、完整代码

等lab due了更新。

Over.