JOONE
一、什么是JOONE?
1、Joone是一个免费的神经网络框架来创建,训练和测试人造神经网络。目标是为最热门的Java技术创造一个强大的环境,为热情和专业的用户。
2、Joone由一个*引擎组成,这是Joone开发的所有应用程序的支点。Joone的神经网络可以建立在本地机器上,在分布式环境中进行培训,并在任何设备上运行。
3、每个人都可以编写新的模块来实现从核心引擎分发的简单组件开始的新算法或新架构。主要思想是为围绕核心框架推出数百万个人工智能应用的基础。
二、JOONE分类
JOONE主要有三个大的模块:
1、joone-engine:joone的核心模块。
2、joone-editor:joone的gui开发环境。不用编写一行代码就建立神经网络模型,并可以进行训练和验证。Joone中提供了一个用joone-editor建立xor网络模型的例子,
本文中的神经网络就是参考这个例子所完成的。
3、joone-distributed-environment :joone用于支持分布式计算的模块。
三、应用
使用JOONE来解决一个很简单的模式识别问题。模式识别是神经网络中的最普遍的应用之一。
模式识别提供给神经网络一种模式,判断是否该神经网络能够识别出该模式。这种模式应该能够在某种程度上被扭曲而该神经网络仍然能够识别它。
这很像人类识别东西(如一个交通标志)的能力。人类应该能够识别在下雨天,晴天或者晚上的交通标志。即使这些图像看上去可能相当不同,但人类的大脑仍能够判断出它们是一样的图像。
当进行JOONE编程时,你一般要使用两种类型的对象。你要使用神经原层对象,用于描述一层的一个或多个的具有相似特征的神经原。神经网络经常有一层或两层神经元。
这些神经元层通过触角联系在一起。这些触角把这种待识别的模式,从一个神经元层传输到另一个神经元层。
触角不仅把这种模式从一个神经元层传输到另一个神经元层。触角还将生成一些指向这种模式的元素的斜线。
这些斜线将导致这种模式的某些元素在被传输到下一个神经元层时不如通过其它方式传递更有效些。这些斜线通常称为权重,它们形成神经网络的存储系统。
通过调整存储在触角中的这些权重,可以更改神经网络的行为。
触角在JOONE中还承担着另外一个角色。在JOONE中,可以把触角看作是数据导管。正如触角把模式从一个神经元层传输到另一个神经元层,指定版本的触角用于把模式传入和传出神经网络。
下面将给你展示一个简单的单层的神经网络是怎样被构建并进行模式识别的。
四、训练神经网络-----java测试类-----程序解释
1、从main方法开始说起,首先第一步新建一个对象--------XOR_using_NeuralNet xor = new XOR_using_NeuralNet();
2、然后初始化神经网络--------xor.initNeuralNet();
初始化神经网络的方法中:
input = new LinearLayer();
hidden = new SigmoidLayer();
output = new SigmoidLayer();
input.setRows(2);
hidden.setRows(3);
output.setRows(1);
input.setLayerName(" L.input ");
hidden.setLayerName(" L.hidden ");
output.setLayerName(" L.output ");
解释:input=new LinearLayer()是新建一个输入层,因为神经网络的输入层并没有训练参数,所以使用的是线性层;
hidden = new SigmoidLayer();这里是新建一个隐含层,使用sigmoid函数作为激励函数,当然你也可以选择其他的激励函数,
如softmax激励函数
output则是新建一个输出层
之后的三行代码是建立输入层、隐含层、输出层的神经元个数,这里表示输入层为2个神经元,隐含层是3个神经元,
输出层是1个神经元
最后的三行代码是给每个输出层取一个名字。
// Now create the two Synapses
FullSynapse synapse_IH = new FullSynapse(); /* input -> hidden conn. */
FullSynapse synapse_HO = new FullSynapse(); /* hidden -> output conn. */
// Connect the input layer whit the hidden layer
input.addOutputSynapse(synapse_IH);
hidden.addInputSynapse(synapse_IH);
// Connect the hidden layer whit the output layer
hidden.addOutputSynapse(synapse_HO);
output.addInputSynapse(synapse_HO);
解释:上面代码的主要作用是将三个层连接起来,synapse_IH用来连接输入层和隐含层,synapse_HO用来连接隐含层和输出层
// the input to the neural net
inputSynapse = new MemoryInputSynapse();
input.addInputSynapse(inputSynapse);
// The Trainer and its desired output
desiredOutputSynapse = new MemoryInputSynapse();
TeachingSynapse trainer = new TeachingSynapse();
trainer.setDesired(desiredOutputSynapse);
解释:上面的代码是在训练的时候指定输入层的数据和目的输出的数据,
inputSynapse = new MemoryInputSynapse();这里指的是使用了从内存中输入数据的方法,指的是输入层输入数据,当然还有从文件输入的方法,这点在文章后面再谈。
同理,desiredOutputSynapse = new MemoryInputSynapse();也是从内存中输入数据,指的是从输入层应该输出的数据
// Now we add this structure to a NeuralNet object
nnet = new NeuralNet();
nnet.addLayer(input, NeuralNet.INPUT_LAYER);
nnet.addLayer(hidden, NeuralNet.HIDDEN_LAYER);
nnet.addLayer(output, NeuralNet.OUTPUT_LAYER);
nnet.setTeacher(trainer);
output.addOutputSynapse(trainer);
nnet.addNeuralNetListener(this);
解释:这段代码指的是将之前初始化的构件连接成一个神经网络,NeuralNet是JOONE提供的类,主要是连接各个神经层,
最后一个nnet.addNeuralNetListener(this);这个作用是对神经网络的训练过程进行监听,因为这个类实现了NeuralNetListener这个接口,这个接口有一些方法,
可以实现观察神经网络训练过程,有助于参数调整。
3、然后我们来看一下train这个方法:xor.train();
// set the inputs
inputSynapse.setInputArray(inputArray);
inputSynapse.setAdvancedColumnSelector(" 1,2 ");
// set the desired outputs
desiredOutputSynapse.setInputArray(desiredOutputArray);
desiredOutputSynapse.setAdvancedColumnSelector(" 1 ");
解释:inputSynapse.setInputArray(inputArray);这个方法是初始化输入层数据,也就是指定输入层数据的内容,inputArray是程序中给定的二维数组,
这也就是为什么之前初始化神经网络的时候使用的是MemoryInputSynapse,表示从内存中读取数据
inputSynapse.setAdvancedColumnSelector(" 1,2 ");
这个表示的是输入层数据使用的是inputArray的前两列数据。
desiredOutputSynapse这个也同理
!
// get the monitor object to train or feed forward
Monitor monitor = nnet.getMonitor();
// set the monitor parameters
monitor.setLearningRate(0.8);
monitor.setMomentum(0.3);
monitor.setTrainingPatterns(inputArray.length);
monitor.setTotCicles(5000);
monitor.setLearning(true);
解释:这个monitor类也是JOONE框架提供的,主要是用来调节神经网络的参数,monitor.setLearningRate(0.8);是用来设置神经网络训练的步长参数,步长越大,
神经网络梯度下降的速度越快,monitor.setTrainingPatterns(inputArray.length);这个是设置神经网络的输入层的训练数据大小size,这里使用的是数组的长度;
monitor.setTotCicles(5000);这个指的是设置迭代数目;monitor.setLearning(true);这个true表示是在训练过程。
long initms = System.currentTimeMillis();
// Run the network in single-thread, synchronized mode
nnet.getMonitor().setSingleThreadMode(singleThreadMode);
nnet.go(true);
System.out.println(" Total time= "+ (System.currentTimeMillis() - initms) + " ms ");
解释:nnet.getMonitor().setSingleThreadMode(singleThreadMode);这个指的是是不是使用多线程,nnet.go(true)表示的是开始训练。
4、最后来看一下interrogate方法:xor.interrogate();
解释:这个方法相当于测试方法,这里的inputArray是测试数据,
注意这里需要设置monitor.setLearning(false);,因为这不是训练过程,并不需要学习,monitor.setTrainingPatterns(4);
这个是指测试的数量,4表示有4个测试数据(虽然这里只有一个)。这里还给nnet添加了一个输出层数据对象,这个对象mmOut是初始测试结果,
注意到之前我们初始化神经网络的时候并没有给输出层指定数据对象,因为那个时候我们在训练,而且指定了trainer作为目的输出。
接下来就是输出结果数据了,pattern的个数和输出层的神经元个数一样大,这里输出层神经元的个数是1,所以pattern大小为1.
5、测试结果
解释:表示输出结果为0.01,根据sigmoid函数特性,我们得到的输出是0,和预期结果一致。如果输出层神经元个数大于1,那么输出值将会有多个,
因为输出层结果是0|1离散值,所以我们取输出最大的那个神经元的输出值取为1,其他为0
6、监听函数
解释: cicleTerminated:每个循环结束后输出的信息
errorChanged:神经网络错误率变化时候输出的信息
netStarted:神经网络开始运行的时候输出的信息
netStopped:神经网络停止的时候输出的信息