前言
今天下决心开始写博客,这篇文档是我大约半年前做的一个小实验,完全出于好玩的目的搞的,当时总结了一下自己写了篇文档,现在稍微整理一下就发出来了。由于时间久远(好吧其实也没那么久远,只是记性太差),并且我本身不是做机器学习这块的,水平也很有限,很多地方难免有错误,希望能谅解和指出(求轻喷~~orz)。
在这里要特别感谢http://bbs.csdn.net/topics/390717623 一文,我参考了很多,给了我很大的启发。
BP神经网络简介
人工神经网络
人工神经网络(ArtificialNeuralNetworks,ANN)提供了一种普遍、实用并且健壮性很强的方法从样例中学习值为实数、离散值或向量的函数。人工神经网络的研究在一定程度上受到了生物学的启发,因为生物的学习系统是由相互连接的神经元组成的异常复杂的网络。而人工神经网络与此大体相似,它是由一系列简单的单元相互密集连接构成的,其中每个单元有一定数量的输入,并产生单一的实数值输出。
上述介绍摘自《机器学习》一书,下面谈谈我自己的理解。基于我本来就不丰富的生物学知识来看,一个神经细胞有树突和轴突(那一条很长的延伸)。树突有很多个但轴突只有一个(但每个树突和轴突末端都有很多分叉),树突接收其他神经细胞的脉冲输入,而轴突向其他神经细胞发送脉冲输出。神经细胞只有两种状态,即激活和抑制。人工神经网络借鉴了这一些特点:单个人工神经细胞可以有来自外界或上一层神经细胞的N个输入(多个树突),但对下一层神经细胞只能有一个输出(单个轴突),但这个输出可以被连接到多个下层神经细胞(轴突上的多个分叉);当输入的信号加权和大于一个阈值则输出1(激活态),否则输出0(抑制态)。
反向传播算法
BP神经网络中的BP指的就是反向传播算法(backpropagation algorithm),又称逆推学习算法,1986年由D.E.Rumelhard和W.S.McClelland提出。
反向传播算法是一种利用训练样例集学习各个神经细胞内权重的方法。在上一节有提到,单个神经细胞内的对于多个输入,可以看作是一个向量,每个向量都有对应的权值,然后进行求加权和的运算,即进行输入向量和权向量的点积运算。当输入一个训练样例后,逐层计算得到输出,这是在进行一个正向传播;反向传播算法是利用这个输出与期望输出之间的误差,逐层计算各层误差并利用某种方式对权向量进行修正(例如梯度下降法等),在进行多次迭代后完成训练。
使用Storm进行实现
storm是时下最流行的流式计算框架,关于storm的介绍可以看技术分享-storm下的文章,这里就不再赘述了。
我认为storm的计算模型是非常适合实现人工神经网络的,理由有一下几点:
-
计算模型相符合。storm的各个节点组成了一个有向无环图,这跟人工神经网络中细胞的逐层分布十分相似。
-
丰富的功能支持。storm提供了数据传输安全保障以及丰富的数据路由方法,这帮助我们在实现神经网络时能减少对于底层数据传输的关注,并且丰富的数据传输方式可以适应不同种类的神经网络的开发。
-
分布式支持。storm首先是一个分布式流式计算框架,当用storm实现人工神经网络时,直接就能运行在集群之上,从而大大提高计算能力以及神经网络的扩展能力,从而使其能够处理更加复杂的业务。
-
DRPC支持。storm支持drpc(分布式rpc),这就允许了业务开发人员将已实现的神经网络当成是一个本地方法来使用。配合良好的设计,去除神经网络与具体业务之间的耦合,就能真正实现一个通用的计算工具。
所以我在进行评估之后,并参考网络上的一个demo,对两层BP神经网络进行了实现。原有demo在实现上存在强耦合,并且有些设计比较粗糙,我会在自己的实现上对其进行改良和优化。
Storm的DRPC
上一节有提到,storm支持实现drpc,并且实现起来十分方便。在集群配置上,需要在storm.yaml中添加一个配置drpc.servers,指定一个drpc服务器,再在这个服务器上启动一个stormdrpc服务,这样集群就搭建完毕了。
在代码层面上,用DRPCSpout替代普通的spout。在构建DRPCSpout中需要传入一个字符串来指明这个drpc方法的方法名。在topology末尾需要加入一个ReturnResult作为返回值bolt,中间其他部分完全和普通topology的开发一样。
调用drpc时,首先需要实例化一个DRPCClient对象,构建时传入drpc服务器地址和端口号(默认3772),然后调用其execute方法即可。execute方法接受两个参数,第一个参数指明方法名,第二个参数是一个字符串。storm的drpc方法输入参数和返回值都是字符串,所以如果要传入复杂对象需要先进行序列化,得到结果进行反序列化(比如用json)。