• 构建一个神经网络
•激活函数
• Encog持久化
•在代码里使用Encog Analyst
这章将展示用Encog怎样构造前馈与简单递归神经网络,以及在最后部分怎样保存这些神经网络。创建神经网络类型使用BasicNetwork和BasicLayer这两个类,除了这两个类,还使用了激活函数,激活函数的作用也将讨论。
考虑到神经网络需要花费大量时间去训练,因此保存你的神经网络是很重要的,Encog神经网络能够使用java内置的序列化来持久化,这种持久性能够通过写入神经网络的EG文件来实现,这是一种跨平台的文本文件,这章将介绍这两种持久化方式。
在上一章中,使用EncogAnalyst来自动规范化数据,EncogAnalyst也能够自动化创建基于CSV数据的神经网络。这章将展示怎样从代码中使用Encog Analyst创建神经网络。
4.1构建一个神经网络
能够使用BasicLayer和BasicNetwork对象创建一个简单的神经网络,以下代码创建了几个BasicLayer对象,默认为双曲正切激活函数。
这个神经网络将有两个神经元的输入层,三个神经元的隐藏层和一个单一神经元的输出层,要使用除了双曲正切函数以外的激活函数,可以使用以下类似的代码:
Sigmoid激活函数通过调用AddLayer传递给隐藏层和输出层,True值指定这个BasicLayer应该有一个偏执神经元,输出层没有偏执神经元,以及输入层没有激活函数,这是因为偏执神经元影响下一层,以及激活函数影响来自前一层的数据。
除非Encog使用在一些实验,否则总是需要使用一个偏执神经元,偏执神经元允许激活函数转移原点零点,这使得当输入不是0的时候偏执神经元允许生成一个0值,以下URL提供了更多关于偏执神经元重要的数学原理:
http://www.heatonresearch.com/wiki/Bias
激活函数附加到层以及用来缩放来自一个层的数据,Encog将层的激活函数应用到此层将要输出的数据上。如果在BasicLayer中没有指定激活函数,默认使用双曲正切函数。
还可以创建上下文层,上下文层能够使用来创建一个Elman或者Jordan样式的神经网络,以下代码能够使用来创建一个Elman神经网络。
注意hidden.setContextFedBy这行,这里创建一个从输出层到隐藏层的上下文链接,隐藏层总是传递上一次迭代的输出,这是一个创建Elman样式的神经网络,Elman和Jordan网络将在第七章介绍。
4.2激活函数的作用
上一节介绍了怎样分配激活函数给层,许多神经网络体系结构使用激活函数来缩放层的输出,Encog提供大量不同的激活函数能够使用来构造神经网络,下一节将介绍激活函数。
激活函数附加到层以及用来缩放来自一个层的数据,Encog层的激活函数适用于输出的数据。如果没有为BasicLayer指定一个激活函数,将使用默认的双曲正切激活函数,所有激活函数的类必须实现ActivationFunction接口。
激活函数在训练神经网络任务中起到了非常重要的作用,传播训练,这个将在下一章介绍,对于传播训练,激活函数要求有一个有效的导数,并非所有的激活函数都有有效的导数,确定一个激活函数有一个导数也许是选择一个激活函数的重要因素。
4.3 Encog的激活函数
下一节将介绍encog的每一个激活函数,选择一个激活函数这里有几个因素要考虑,首先,一个很重要的是要考虑如何使用神经网络类型决定所需的激活功能。第二,考虑神经网络使用传播训练的必要性,传播训练要求激活函数提供一个导数。最终,考虑使用的数值范围,一些激活函数仅仅处理正值或者特定范围的数值。
4.3.1 ActivationBiPolar
ActivationBiPolar激活函数使用要求为双极值的神经网络,双极值的值为true或者是false这两种之一,双极值的1代表为true, 双极值的-1代表为false, 双极激活函数确保了传递给它的任何值都为1或者是-1。双极激活函数代码如下:
如上所示,这个激活函数的输出仅限为1或者是-1。这种激活函数是用于神经网络需要从一层到另一层双极输出。这个双极值它没有导数函数,因此这个激活函数不能使用于传播训练。
4.3.2 ActivationCompetitive
ActivationCompetitive函数用于迫使只有一组神经元获胜, 获胜者是产出最高的神经元群。每个神经元的输出被保存在传递给这个函数的数组中,获胜神经元组的大小是可定义的。函数首先决定获胜者。所有非获胜神经元将被设置为0。获奖者都有相同的值,这是获胜产出总和的一个划分。
这个函数首先创建了一个数组,将跟踪每个神经元是否已经被选为获胜者之一。获胜者的数量也计算在内:
首先,循环maxWiners多次已发现获胜者的数量:
现在,获胜者必须确定,循环所有神经网输出已找到最大的输出:
如果这个神经元没有获胜,它已经是最大的输出以及没有其他神经元比这个更高,那这可能是一个获胜者:
保留被发现的获胜者的总和,并标记这个神经元为获胜者,把它标记为胜利者将防止它在此被选中。获胜者产出的总和最终将在优胜者中分配。
现在确定了获胜者的正确数量,必须调整获胜者和非获胜者的值。所有的非获胜者将设置为0,获胜者将分享所有获胜者的值总和。
这类激活函数能够用在竞争型学习神经网络,例如自组织映射,这个激活函数没有导数,因此它不能用于传播训练。
4.3.3 ActivationLinear
ActivationLinear函数实际上没有激活功能,它简单实现了线性函数,线性函数如下公式4.1所示:
图4.1显示了线性函数的简单图像:
线性激活函数的java实现非常简单,它什么也不做:
线性函数主要使用在那些没有激活函数的特定神经网络类型,例如自组织映射,线性激活函数有一个常数导数,因此他能够使用于传播训练,传播训练前馈神经网络的输出层有时使用线性层。
4.3.4 ActivationLOG
ActivationLog激活函数使用的是log函数算法,以下显示了这个激活函数的计算:
产生的这条曲线类似双曲正切激活函数,那个将在本章后面讨论。图4.2显示了对数激活函数的图像。
对数激活函数能够使用在防止饱和。一个神经元的隐藏节点被认为过饱和,在给定的一组输入时候,输出在大多数情况下大约为1或-1。这能够显著放慢训练,当选择双曲正切函数训练不成功的时候,这个对数激活函数是一个合适的选择。
正如图4.2所示,对数激活函数由正和负两种值,这意味着它可以使用于那些期望需要负值输出的神经网络,一些激活函数,例如sigmoid激活函数仅仅只产生正的输出,对数激活函数有一个导数,因此它能够使用于传播训练。
4.3.5 ActivationSigmoid
ActivationSigmoid激活函数应该仅仅使用于当期望输出为正值的时候,因为ActivationSigmoid激活函数仅仅产生正的输出。ActiviationSigmoid激活函数的方程式如下所示:
ActivationSigmoid函数将负的范围变为正的范围。如图4.3所示,显示了sigmoid函数的图像:
ActivationSigmoid函数是前馈和简单递归神经网络很常见的一个选择。然而,非常必要的是训练数据不期望负的输出,如果要求有负的输出,双曲正切激活函数也许是一个最好的解决方式。
4.3.6 ActivationSoftMax
ActivationSoftMax激活函数将缩放所有的输入值让所有之和等于1,ActivationSoftMax有时用于一个隐藏层的激活函数。
激活函数从所有神经元输出的自然指数相加开始:
然后,每个神经元的输出根据这个和,由此产生总和为1 的输出:
ActivationSoftMax通常用于神经网络的输出层分类。
4.3.7 ActivationTANH
ActivationTANH激活函数使用双曲正切函数,双曲正切函数也许是最常用的激活函数,因为它有正负两个范围,双曲正切函数是Encog默认的激活函数,双曲正切函数的公式如下公式4.3所示:
图4.4显示的双曲正切函数图像可以看到双曲正切激活函数事实上接受正负两个值。
双曲正切函数在前馈和简单递归神经网络中是非常常用的选择。双曲正切函数有一个导数,因此他能够用于传播训练。
4.4 Encog持久化
训练一个神经网络需要花费相当长的时间,重要的是采取措施保证你的工作在网络训练完成后保存下来,Encog对于数据的保存提供了几种方式,与两种最主要的存储Encog数据对象的方式,Encog提供了基于文件的持久化或者是java自身的持久化。
Java提供自己序列化对象的方式,称为java序列化,java序列化允许大量不同的对象类型写入到一个流,例如磁盘文件,java序列化Encog和序列化其他java对象一样,每一个重要的Encog对象支持序列化实现Serializable接口。
Java序列化是一种存储Encog对象的快速方式,然而,它有一些重要的局限性,创建java序列化文件只能用于Encog的java平台,它们将不兼容Encog的.Net或者Encog for Silverlight平台。进一步,java序列化直接依赖于对象,因此,未来的Encog版本也许不兼容你的序列化文件。
创建所有Encog平台的通用文件,考虑Encog EG格式,EG格式文件架构神经网络保存为文本文件,文件扩展名为.EG。
这一章将介绍这两种Encog持久化,先开始Encog EG持久化,这章将探索怎样用一个Encog持久化文件保存一个神经网络。
4.5使用Encog EG持久化
Encog EG持久化文件是Encog原生文件格式以及存储在外部的..EG文件,Encog Workbench使用Encog EG处理文件,这种格式能够在不同的操作系统和Encog平台之间进行交换。这是选择Encog应用的一个原因。
这一节开始看一下一个XOR示例使用Encog EG文件,最后,同样的示例将用在java序列化。我们将开始用Encog EG持久化示例。
4.5.1 使用Encog EG持久化
使用Encog EG持久化非常简单,EncogDirectoryPersistence类用来从Encog EG文件中加载和保存对象。以下是关于Encog EG持久化一个好的示例:
这个例子有两个主要的方法组成,第一个方法,trainAndSave, 训练一个神经网络以及保存到一个Encog EG文件。第二个方法,LoadAndEvaluate, 加载Encog EG文件和评价它,这证明了这个Encog EG文件保存正确,main方法简单地按顺序调用这两个方法,我们将开始检测trainAndSave方法。
这个方法开始通过创建一个基本的神经网络来训练这个XOR运算符。它是一个简单三层前馈神经网络。
XOR运算符训练集的创建包含了预期的输出和输入。
这个神经网络将使用弹性传播训练(RPROP)
RPROP迭代执行知道错误里非常小,训练将在下一章讨论,现在,训练是验证网络重新加载后错误率保持不变的一种方式。
一旦网络被训练,显示最终的错误率,想在就可以保存神经网络。
这个神经网络现在能保存到一个文件,每一个文件仅仅保存一个Encog对象,使用EncogDirectoryPersistence类的saveObject方法。
现在这个Encog EG文件已创建,之后使用loadAndEvaluate从这个文件中加载这个神经网络以确保它仍然执行很好。
现在已经构造这个集合,加载之前保存的已命名的网络,重要的是要评估神经网络来证明他仍是训练有素的。要做到这点,为XOR运算符创造一个训练集。
计算给定的训练数据的误差。
这个错误应该和之前的神经网络保存时相同。
4.6使用java序列化
还可以使用标准的java序列化与Encog神经网络训练集。Encog EG持久性比java序列化更加灵活,然而,在某些情况下神经网络可以被保存到一个平台独立的二进制文件,这个例子开始通过调用trainAndSave方法:
这个方法开始通过创建一个基本的神经网络去训练XOR运算。它是一个简单的例子,三层前馈神经网络。
我们将使用弹性传播(RPROP)训练这个网络.
以下代码通过循环迭代训练直到错误率低于1%(<0.01).
最后显示神经网络的错误率。
可以使用普通java序列化代码或者SerializeObject类保存网络。此实用工具类提供了一个保存的方法,将编写任何一个可序列化的对象写入到一个二进制文件。这里的保存方法使用来保存神经网络。
现在这个二进制文件已经创建,之后将从这个文件中加载神经网络看是否仍然很好地执行,这里通过loadAndEvaluate方法执行。
SerializeObject类也提供了加载方法,将从一个二进制序列化文件读取对象。
现在,网络加载完成,给出了误差水平。
此错误级别应与网络最初训练时的错误级别相匹配。
4.7总结
使用BasicNetwork和BasicLayer类创建前馈和简单递归神经网络,使用这些对象,神经网络能够被创建,也能使用上下文连接层,就像简单递归神经网络,例如Elamn神经网络就是这样创建的。
Encog使用激活函数缩放来自神经网络层的输出,Encog默认将使用双曲正切函数,那是一个好的通用的目标激活函数,任何激活函数类必须实现ActivationFunction接口,如果激活函数要使用于传播训练,这个激活函数必须要有能力计算导数。
ActivationBiPolar激活函数类使用一个网络仅仅接受双极值,ActivationCompetitive激活函数类使用在竞争机制的神经网络例如自组织映射,ActivationLinear激活函数类使用在不需要激活功能的时候,ActivationLOG激活函数类工作类似于ActivationTANH激活函数类,除了它不总是作为一个隐藏层饱和,ActivationSigmoid激活函数类类似于ActivationTANH激活函数,除了仅仅返回一个正值,ActivationSoftMax激活函数类缩放输出让其所有之和等于1.
这章讨论了怎样使用两种方法保存Encog对象,也许使用Encog EG格式或者java序列化两者之一保存对象。
对于保存Encog神经网络优先使用Encog EG格式方式,这些对象通过使用他们资源名字,EG文件能在Encog支持的任何平台互换。
Encog也允许java序列化存储对象到磁盘或者流。Java序列化有太多限制性超过了Encog EG文件,因为这二进制文件是直接从对象自动存储,即使是最小的改变,一个Encog对象就会导致不兼容的文件。此外,其他平台也没有能力使用这个文件。
在下一章中阐述神经网络训练中的概念,训练的过程神经网络的初始权值修改为产生所需的输出。这儿有几种神经网络训练的方式,下一章将介绍传播训练。