最近对机器学习方面的知识有点感兴趣,所以特别的对神经网络方面的知识进行了了解。然而,发现大部分的人都是通过Python或者R语言及其Matlab来进行实验的,而自己却还没有时间进行学习,而且对Java语言有一种情有独钟的感觉,所以特别的就用Java语言实现BP神经网络。PS:这个内容其实在Python和Matlab中都有已经封装好的库,直接调用就可以了的,而且效率也还不错。而我只是尝试试着用Java进行写写而已(最后的效果还不如已经封装好的代码),自己并没有进行过多的优化。
下面就介绍一个简单的例子,就是对手写的数字通过BP神经网络进行识别,我也刚接触机器学习,所以有不足的地方欢迎大家进行指正,共同学习。
在这里就不再对BP神经网络的原理进行过多的阐述了,如果大家对于这个方面不懂的话,可以自行百度的进行了解。
例子简介:
该问题解决的是把28x28像素的灰度手写数字图片识别为相应的数字,其中数字的范围从0到9.
训练样本:训练集中包括60000个样本,因为所有数据集中28x28像素的灰度图片的尺寸为784,所以训练
集输出的格式为[60000, 784]。
一:训练数据和测试数据的格式
训练数据的格式如图所示:
这只是部分显示的效果,在这里进行讲解一下:其中每一行一共是784个输入,因为这是由一个28*28的图片进行像素转换过来的,而且每一列的数值都是在0-255之间。
标签结果:
当然,这也只是部分训练集的结果,其对应的就是上面训练集的识别结果,所以主要的作用也就是标签。
二:实验思路
(1):构建神经网络层次结构
由训练集数据可知,手写输入的数据维数为784维,而对应的输出结果为分别为0-9的10个数字,所以根据训练集的数据可知,在构建的神经网络的输入层的神经元的节点个数为784个,而对应的输出层的神经元个数为10个。由于在神经网络的隐层可以有一层或者多层,对此自己在本实验中,采取的是只采用了一层隐层结构。
(2):确定隐层中的神经元的个数
因为对于隐层的神经元个数的确定目前还没有什么比较完美的解决方案,所以对此经过自己查阅书籍和上网查阅资料,有以下的几种经验方式来确定隐层的神经元的个数,方式分别如下所示:
1) 一般取(输入+输出)/2
2) 隐层一般小于输入层
3)(输入层+1)/2
4) log(输入层)
5) log(输入层)+10
由于上述的也是由经验而得来的,所以自己在实验过程中分别的测试了一下,最后得到以第五种的方式得到的测试结果相对较高。
(3):设置神经元的激活函数
在《机器学习》的书中介绍了两种比较常用的函数,分别是阶跃函数和Sigmoid函数。最后自己采用了后者函数。
(4):初始化输入层和隐层之间神经元间的权值信息
采用的是使用简单的随机数分配的方法,并且两层之间的神经元权值是通过二维数组进行保留,数组的索引就代表着两层对应的神经元的索引信息
(5):初始化隐层和输出层之间神经元间的权值信息
采用的是使用简单的随机数分配的方法,并且两层之间的神经元权值是通过二维数组进行保留,数组的索引就代表着两层对应的神经元的索引信息
(6):读取CSV测试集表格信息,并加载到程序用数据保存,其中将每个维数的数据都换成了0和1的二进制数进行处理。
(7):读取CSV测试集结果表格信息,并加载到程序用数据保存
(8):计算输入层与隐层中隐层神经元的阈值
这里主要是采用了下面的方法:
Sum=sum+weight[i][j] * layer0[i];
参数的含义:将每个输入层中的神经元与神经元的权值信息weight[i][j]乘以对应的输入层神经元的阈值累加,然后再调用激活函数得到对应的隐层神经元的阈值。