手记

亚马逊计算机工程师分享:神经网络的优化和自适应

神经网络真正令人惊叹的是其从周围环境中学习的能力,就像那些有天赋的人能做的一样。我们人类通过观察和重复练习来体验学习过程,直到某些任务或者概念被完全掌握。从生理学的角度来说,在人脑中的学习过程是对节点(神经元)之间的神经连接进行重新设置,这个过程导致了一个新思维定式的产生。

分享人:Alan M.F. Souza是来自亚马逊高级研究所的计算机工程师。他拥有软件项目管理的研究生学位以及帕拉联邦大学的工业过程硕士学位。自2009年以来,他一直从事神经网络方面的工作,并从2006年开始与巴西的IT公司合作进行Java、PHP、SQL和其他编程语言的开发。他热衷于编程和计算智能。

今天将分享有助于优化神经网络的技术,从而使其达到最佳性能。例如输入选择、数据集分离和过滤等任务以及隐藏层神经元的数量选择的任务都是可以被调整以提高神经网络性能的例子。另外,本文中还关注让神经网络适应实时数据的方法。

9.1 神经网络实现中的常见问题

当开发一个神经网络应用时,经常会面对关于结果准确性的问题。这些问题的源头是多样的:

不良的输入数据;

噪声数据;

非常大的数据集;

不合适的结构;

不合适的隐藏层神经元;

不合适的学习率;

不良的数据分段。

神经网络应用的设计有时需要很多耐心和试错方法。不存在一种方法论可以特别指出隐藏单元的数量应该是多少或者应该用哪种架构,但是对于如何正确选择这些参数还是有一些推荐项的。程序员可能会面对的另一个问题是训练时间过长,这经常引起神经网络无法学习数据。无论训练过程运行了多长时间,神经网络都不会收敛。

提示:

设计一个神经网络需要程序员或者设计者按需多次测试和重新设计结构,直到得到一个可以接受的结果。

另一方面,人们希望提高结果质量。直到学习算法达到停止条件,即迭代次数或者均方误差(译者注,指达到这两个条件的预设值),神经网络才停止学习过程。即便这样,有时结果还是不够准确或者不够泛化,那就需要对神经网络结构和数据集进行重新设计。

9.2 输入选择

设计神经网络应用的关键任务之一是选择合适的输入。对于无监督学习的例子来说,人们希望只使用与结果有关的变量,这样神经网络将在其基础上找到某种模式。对于监督学习的例子来说,需要将输出和输入映射起来,所以人们需要选择能适当影响输出的输入变量。

在监督学习的例子中有助于选择优质输入的一个策略是数据序列之间的相关性。数据之间的相关性是度量一个数据序列如何作用或者影响其他序列的方式。假设我们有一个数据集包含了若干数据序列,从中选择一个作为输出。现在,我们需要从剩下的变量中选择输入。

然后,我们会一次评估一个变量对输出的影响,以便决定是否将其包括为输入。相关系数是最常用的变量之一:

其中Sx(k)y(k)表示x和y变量的协方差:

相关系数的取值范围?1~1,当值接近于1就说明正相关,值接近于?1就说明负相关,并且值接近于0说明完全没有相关性。

举例说明,下面关于两个变量X和Y的3个图表,如图9-1所示。

图9-1

在左边的第一个图表里,很显然地能够发现一个变量下降而另一个变量则上升(相关系数:?0.8)。中间的图表显示了两个变量以相同的趋势在变化,所以它们的相关系数为正(相关系数:+0.7)。在右边的第三个图,显示了变量之间没有相关性(相关系数:?0.1)。

没有关于限制使用哪个相关系数这样的阈值规则,它取决于应用。相关系数绝对值大于0.5可能适合某个应用,而其他情况,绝对值在0.2左右也是一个显著的指标。

另一个有趣的点是减少冗余数据。有时,当在无监督学习和监督学习中存在大量可用数据时,这就需要减少冗余数据了。举例说明,来看看图9-2中的两个变量。

图9-2

可以看到X和Y两个变量形状相同,所以这就可以理解为冗余,这是由于两个变量因为高度相关都携带了几乎相同的信息。因此,人们就会想到一种称为主成分分析(principal component analysis,PCA)的技术,它是处理这类例子的好方法。

主成分分析的结果将是总结了前面两个(或者更多)变量的新变量。基本上,原始数据序列会减去平均值并乘以协方差矩阵的特征向量的转置:

其中SXY代表了变量X和Y的协方差。

计算出来的新数据如下:

让我们现在来看看与原始变量相比新变量在图9-3中是什么样子。

图9-3

噪声数据和糟糕的数据也是神经网络应用的问题源头,这也是我们需要过滤数据的原因。通用数据过滤技术是指排除掉那些超过通常范围的记录。例如,温度值通常在?40~40之间,所以温度值为50就会被认为是异常值并被移除。

3 sigma原则是良好且有效的过滤数据的措施。它指的是过滤掉超过均值 3 倍标准差的数据。

为神经网络选择一个合适的结构也是一个非常重要的步骤。但是,这通常根据经验来完成,这是因为没有关于一个神经网络应该有多少个隐藏层单元的规则。唯一关于多少个单元更合适的度量当时就是神经网络的性能。然而,这样可能会存在一个能产生相同结果的更小一些的结构。

关于这点,大体上有两种方法论:建造型和剪枝型。建造型方法指的是一开始只确定输入层和输出层,接着开始往隐藏层增加新的神经元,直到得到一个好的结果。而破坏型方法,也称为剪枝型,它基于较大结构工作,在之上取出对输出贡献较小的神经元。

建造型方法如图9-4所示。

图9-4

剪枝型方法反其道而行之。当消费社区神经元数量有很多时,“剪掉”那些敏感度很低的神经元,这意味着它对于误差的贡献最小,如图9-5所示。

图9-5

在训练过程期间,重要的是设计如何执行训练。两个基本方法是批量学习和增量学习。

在批量学习中,所以记录都被提供给神经网络,这样神经网络就能评估误差并更新权值,如图9-6所示。

图9-6

在增量学习中,更新操作在每条记录发送给神经网络之后执行,如图9-7所示。

图9-7

两种方式都很好,并各有其利弊。批量学习可以用于虽然较不频繁但更具方向性的权值更新,而增量学习提供了一种对权值精雕细琢的调整方式。在这种情况下,可以设计一种能使神经网络持续学习的模式。

离线学习意味着神经网络在没有“运行”时学习。每一个神经网络应用都假设在某个特定环境下工作,为了达到生产要求,神经网络应该被正确训练。由于离线训练的输出值变化范围很大,这会在系统运行时损害系统,所以离线训练不适合在网络运行时工作。但是,当使用在线学习的方式时,会有一些限制。当使用离线学习的方式时,可以使用交叉验证和bootstrap重采样法来预测误差。而在在线学习中,这是不可能完成的,因为不再有“训练集”了。但是,人们想要神经网络性能得到一些提升时,会需要在线学习。

在运行在线学习时,会用到一种随机方法。这种改进神经网络训练的算法由两个主要特征组成:训练样本的随机选择和运行时(在线)学习率的变化。当在目标函数中发现噪声时就使用该算法。它有助于避免局部最小(最佳解决方案之一)并达到全局最小(最佳解决方案)。

伪算法如下:

Initialize the weights.  Initialize the learning rate.  Repeat the following steps:   Randomly select one (or possibly more) case(s)     from the population.   Update the weights by subtracting the gradient

times the learning rate.   Reduce the learning rate according to an

appropriate schedule.

提示:

伪算法的源代码可以在“ftp://ftp.sas/ pub/neural/FAQ2.html#A_styles”找到。

在Java项目中,已经在learn包中创建了BackpropagationOnline类。该算法和经典反向传播算法的不同之处在于train()方法有变化,并增加了两个方法——generateIndexRandomList()和reduceLearningRate()。第一个方法生成了一个索引的随机集合,在训练步骤中会用到,第二个方法根据以下启发式算法来执行学习率的在线变化:

private double reduceLearningRate(NeuralNet n, double percentage) {  double newLearningRate=n.getLearningRate() *          ((100.0 - percentage) / 100.0);  if(newLearningRate < 0.1) {   newLearningRate=1.0;  }  return newLearningRate; }

train()方法也根据前面介绍的伪算法进行了修改,该方法主要部分的代码如下:

ArrayList indexRandomList=generateIndexRandomList(rows);while(getMse() > n.getTargetError()) { if ( epoch >=n.getMaxEpochs() ) break;  double sumErrors=0.0;  for (int rows_i=0; rows_i < rows; rows_i++) {   n=forward( n, indexRandomList.get(rows_i) );   n=backpropagation( n, indexRandomList.get(rows_i) );   sumErrors=sumErrors + n.getErrorMean();   n.setLearningRate( reduceLearningRate( n, n.getLearningRatePercentage Reduce() ) );  }  setMse( sumErrors / rows );  n.getListOfMSE().add( getMse() );  epoch++;  }

我们使用了前面章节的数据来测试这种训练神经网络的新方法。本章使用与第5章和第8章定义相同的神经网络拓扑。第一个是天气预测问题,第二个是OCR。表9-1显示了结果对比。

表9-1

天气预测

OCR

经典反向传播学习率

0.5

0.5

经典反向传播MSE值

0.2877786584

0.0011981712

在线反向传播学习

得到:≌≌0.15

得到:≌≌0.40

在线反向传播MSE值

0.4618623052

9.977909980E-6

图9-8显示了在使用新训练方法之后发现的MSE演变,它考虑了天气预测数据。曲线有一个锯齿形状是因为学习率的变化。另外,这与第5章中展示的曲线很相似。

图9-8

另一方面,图9-9所示是用OCR数据生成的,这时训练过程变得更快了并且在第900次迭代就停止了,这是因为它的MSE值已经很小了。重要的是,在第8章中,训练过程更加缓慢并持续到了第6000次迭代。

图9-9

我们还进行了其他实验:用反向传播算法训练神经网络,考虑用在线方法找到学习率。在这两个问题中的MSE值都下降了。

天气预测的MSE大约为0.206,而原始的MSE是0.287(第5章中得到的),如图9-10所示。

图9-10

OCR的MSE大约在8.663E-6,而原始的MSE是0.001(第8章中得到的),在图9-11中可以看到这一点。

图9-11

另一个重要的观察是基于以下事实:图9-11中所示的训练过程几乎在第3000次迭代终止。因此,它比使用相同算法的第8章中讨论的训练过程更快更好。

本文摘自《神经网络算法与实现 基于Java语言》

编辑推荐

神经网络已成为从大量原始的,看似无关的数据中提取有用知识的强大技术。 Java语言是用于实现神经网络的zui合适的工具之一,也是现阶段非常流行的编程语言之一,包含多种有助于开发的API和包,具有“一次编写,随处运行”的可移植性。

本书完整地演示了使用Java开发神经网络的过程,既有非常基础的实例也有高级实例。首先,你将学习神经网络的基础知识、感知机及其特征。 然后,你将使用学到的概念来实现自组织映射网络。 此外,你还会了解一些应用,如天气预报、疾病诊断、客户特征分析和光学字符识别(OCR)等。 zui后,你将学习实时优化和自适应神经网络的方法。

首先,你将学习神经网络的基础知识和它们的学习过程。 然后我们关注感知机及其特征。 接下来,您将使用您学到的概念实现自组织映射。 此外,您将了解一些应用,如天气预报,疾病诊断,客户特征分析和光学字符识别(OCR)。 zui后,您将学习优化和适应实时神经网络的方法。

本书所有的示例都提供了说明性的源代码,这些源代码综合了面向对象编程(OOP)概念和神经网络特性,以帮助你更好的学习。

0人推荐
随时随地看视频
慕课网APP