(); for (int i = 0; i < (); i++) { }buildDecisionTree(nodeName, val, al, selatt);
if (i))[minIndex].equals(val)) { }
(i));
BP神经网络
一、BP神经网络简介
在人工神经网络发展历史中,很长一段时间里没有找到隐层的连接权值调整问题的有效算法。直到误差反向传播算法(BP算法)的提出,成功地解决了求解非线性连续函数的多层前馈神经网络权重调整问题。
BP网络是1986年由Rumelhart和McCelland为首的科学家小组提出,是一种按误差逆传播算法训练的多层前馈网络,是目前应用最广泛的神经网络模型之一。BP网络能学习和存贮大量的输入-输出模式映射关系,而无需事前揭示描述这种映射关系的数学方程。它的学习规则是使用最速下降法,通过反向传播来不断调整网络的权值和阈值,使网络的误差平方和最小。BP神经网络模型拓扑结构包括输入层(input)、隐层(hide layer)和输出层(output layer)。
二、算法原理
由于传统的感知器和线性神经网络有自身无法克服的缺陷,它们都不能解决线性不可分问题,因此在实际应用过程中受到了。而BP网络却拥有良好的繁泛化能力、容错能力以及非线性映射能力。因此成为应用最为广泛的一种神经网络。
BP算法的基本思想是把学习过程分为两个阶段:第一阶段是信号的正向传播过程;输入信息通过输入层、隐层逐层处理并计算每个单元的实际输出值;第二阶段是误差的反向传递过程;若在输入层未能得到期望的输出值,则逐层递归的计算实际输出和期望输出的差值(即误差),以便根据此差值调节权值。这种过程不断迭代,最后使得信号误差达到允许或规定的范围之内。
基于BP算法的多层前馈型网络模型的拓扑结构如上图所示。
BP算法的数学描述:三层BP前馈网络的数学模型如上图所示。三层前馈网中,输入向量为:X(x1,x2,...,xi,...,xn)T;隐层输入向量为:
Y(y1,y2,...,yj,...ym)T;输出层输出向量为:O(o1,o2,...,ok,...ol)T;期望输出向量为:d(d1,d2,...dk,...dl)T。输入层到隐层之间的权值矩阵用V表示,
V(v1,v2,...vj,...vm)Y,其中列向量vj为隐层第j个神经元对应的权向量;隐层到输出层之间的权值矩阵用W表示,W(w1,w2,...wk,...wl),其中列向量wk为输出层第k个神经元对应的权向量。
下面分析各层信号之间的数学关系。 对于输出层,有
yjf(netj),j1,2,...,mnetjvijxi,j1,2,...,m
对于隐层,有
以上两式中,转移函数f(x)均为单极性Sigmoid函数:f(x)f(x)具有连续、可导的特点,且有f'(x)f(x)[1f(x)] 以上共同构成了三层前馈网了的数学模型。
当网络输出和期望输出不相等时,存在输出误差E如下:
11m2E(do)(dkok)2
22j01 1ex将以上误差定义式展开至隐层,有
m1l1l2E[dkf(netj)][dkf(wjkyj)]
2k12k1j02
进一步展开至输入层,有
mnn1l1l2E{dkf[wjkf(netj)]}{dkf[wjkf(vijxi)]}
2k12k1j0i0i02由上式可以看出,网络输入误差是两层权值W和V的函数,因此调整权值可以改变误差E。
显然,调整权值的原则是使误差不断的减小,因此应使权值的调整量与误差的负梯度成正比,即:
wjkvijE,j0,1,2,...m;k1,2,...,lwjkE,i0,1,2,...,n;j1,2,...,mvij
式中负号表示梯度下降,常数(0,1)表示比例系数,在训练中反映了学习速率。
容易看出,BP学习算法中,各层权值调整公式形式上都是一样的,均有3个因素决定,即:学习速率、本层误差信号和本层输入信号X/Y。其中输出层误差信号同网络的期望输出与实际输出之差有关,直接反映了输出误差,而各隐层的误差信号与前面各层的误差信号都有关,是从输出层开始逐层反传过来的。
三、实验 实验输入与输出:
本次实验做的是一个数字分类的实验,目的是对于任意的整数(int型),BPNN在经过训练之后,能够准确地判断出它是奇数还是偶数,正数还是负数。首先对于训练的样本(是随机生成的数字),将它转化为一个32位的向量,向量的每个分量就是其二进制形式对应的位上的0或1。将目标输出视作一个4维的向量,[1,0,0,0]代表正奇数,[0,1,0,0]代表正偶数,[0,0,1,0]代表负奇数,[0,0,0,1]代表负偶数。
训练样本为1000个,学习200次。 实验结果:
如图所示,BPNN在经过训练之后,能够准确地判断出它是奇数还是偶数,正数还是负数。
关键代码:
private void forward(double[] layer0, double[] layer1, double[][] weight) { } /**
* Calculate output error. */
private void outputErr() {
layer0[0] = ;
for (int j = 1, len = ; j != len; ++j) { }
double sum = 0;
for (int i = 0, len2 = ; i != len2; ++i)
sum += weight[i][j] * layer0[i];
layer1[j] = sigmoid(sum);
double errSum = 0;
for (int idx = 1, len = ; idx != len; ++idx) { }
double o = output[idx];
optDelta[idx] = o * (1d - o) * (target[idx] - o); errSum += (optDelta[idx]);
}
optErrSum = errSum;
/**
* Calculate hidden errors. */
private void hiddenErr() { }
double errSum = 0;
for (int j = 1, len = ; j != len; ++j) { }
hidErrSum = errSum;
double o = hidden[j]; double sum = 0;
for (int k = 1, len2 = ; k != len2; ++k)
sum += hidOptWeights[j][k] * optDelta[k];
hidDelta[j] = o * (1d - o) * sum; errSum += (hidDelta[j]);