您的当前位置:首页正文

BP实验报告

2024-10-18 来源:威能网


BP实验报告

学生姓名 程战战 专业/班级 计算机91 学 号 09055006 所在学院 电信学院 指导教师 鲍军鹏 提交日期 2012/6/15

1 实验目的

用java语言实现BP网络,解决一个简单的曲线拟合(预测)问题。要求训练数据不少于400个点,测试数据不少于100个点。在神经网络训练过程中要记录下误差,最后画出整个学习过程中的网络误差变化曲线。

2 实验原理

基本思想是:

样本集:S={(X1,Y1),(X2,Y2),…,(Xs,Ys)}

逐一地根据样本集中的样本(Xk,Yk)计算出实际输出Ok及其误差E1,然后对各层神经元的权值W(1),W(2),…,W(L)各做一次调整,重复这个循环,直到∑Ep<ε(所有样本的误差之和)。

用输出层的误差调整输出层权矩阵,并用此误差估计输出层的直接前导层的误差,再用输出层前导层误差估计更前一层的误差。如此获得所有其它各层的误差估计,并用这些估计实现对权矩阵的修改。形成将输出端表现出的误差沿着与输入信号相反的方向逐级向输入端传递的过程。 基本过程是:

样本:(输入向量,理想输出向量)

1、权初始化:“小随机数”与饱和状态;“不同”的权值保证网络可以学。 2、向前传播阶段:

(1)从样本集中取一个样本(Xp,Yp),将Xp输入网络;

(2)计算相应的实际输出Op:Op=FL(…(F2(F1(XpW(1))W(2))…)W(L)) 3、向后传播阶段——误差传播阶段:

(1)计算实际输出Op与相应的理想输出Yp的差。 (2)按极小化误差的方式调整权矩阵。 (3)累计网络关于整个样本集的误差。

4、如果网络误差足够小,则停止训练。否则重复第2、3步。 算法伪码:

样本:(输入向量,理想输出向量)

1、权初始化:“小随机数”与饱和状态;“不同”的权值保证网络可以学。 2、向前传播阶段:

(1)从样本集中取一个样本(Xp,Yp),将Xp输入网络;

(2)计算相应的实际输出Op:Op=FL(…(F2(F1(XpW(1))W(2))…)W(L)) 3、向后传播阶段——误差传播阶段:

(1)计算实际输出Op与相应的理想输出Yp的差。 (2)按极小化误差的方式调整权矩阵。 (3)累计网络关于整个样本集的误差。

4、如果网络误差足够小,则停止训练。否则重复第2、3步。

本次实验采用的是三层感知器模型,如下图;其中有40个权值需要初始化,在这里,每个

权值都各不相同。 固定权

x1 x2

x3

固定权可调权y1y2输入层隐层输出层3 实验结果

其中,纵轴代表误差,横轴代表样本的次数。可以看到,随着训练次数的增加,误差逐渐靠近x轴,逐渐减小。

4 实验源代码

主程序:

//package BackPropagation;

import java.util.Vector;

public class BackPropagation {

double leaning_rate = 0.7;//表示学习速率 double min_error = 0.0001;//足够小的误差 double weight[];//用于存放生成的所有权值

Vector> vc1,vc2,vc3;//用于存放不同层的权值 double ep[] = new double[400];//用于存放每个训练样本的误差 double ep2[] = new double[100];//用于存放每个学习样本的误差 Sample sa = new Sample();//学习样本的初始化

double input[] = new double[4];//用于存放输入层每个神经元总的输入 double in_output[] = new double[4];//用于存放输入层的输出结果 double hidden_in[] = new double[3];//用于存放隐层每个神经元总的输入 double hidden_output[] = new double[3];//用于存放隐层的输出结果 double o_in[] = new double[2];//用于存放输出层每个神经元总的输入 double o_put[] = new double[2];//用于存放输出层输出结果 BackPropagation(){ }

public boolean isInarr(double arr[],int n,double a){//判断a是否在数组arr }

public void init_weight(){//初始化各层神经元的权值

int i,j=0,k;

weight = new double[30]; for(i=0;i<30;i++){ }

vc1 = new Vector>(4);//向量 vc2 = new Vector>(3); vc3 = new Vector>(2); for(i=0;i<4;i++){//存放第一层的权值

Vector vc11 = new Vector(3); weight[i] = Math.random();

while(isInarr(weight,i,weight[i])){//使初始化的各个权值各不相同 }

weight[i] = Math.random();

int temp = 0;

for(int i=0;iif(temp == 1) return true;//如果在则返回true else return false;

if(arr[i] == a){ }

temp = 1; break;

init_weight(); practice(400); study(100);

的前n个元素中

}

}

for(k=0;k<3;k++){ }

vc1.add(vc11);//增加向量

vc11.add(weight[j++]);//末尾增加double

for(i=0;i<3;i++){//存放第二层的权值 }

for(i=0;i<2;i++){//存放第三层的权值 }

Vector vc33 = new Vector(3); for(k=0;k<3;k++){ }

vc3.add(vc33);

vc33.add(weight[j++]);

Vector vc22 = new Vector(4); for(k=0;k<4;k++){ }

vc2.add(vc22);

vc22.add(weight[j++]);

public void output(double aa[]){//根据输入向量aa产生最后的输出,三层的输出

in_output[1]*(((Vector)vc2.get(j)).get(1)).doubleValue()+

in_output[2]*(((Vector)vc2.get(j)).get(2)).doubleValue()+

in_output[3]*(((Vector)vc2.get(j)).get(3)).doubleValue();

}

hidden_output[j] = 1/(1+Math.pow(Math.E, -hidden_in[j])); double x1,x2,x3; int j=0; x1 = aa[0]; x2 = aa[1]; x3 = aa[2];

for(j=0;j<4;j++){//计算input[],in_output[]//三个输入乘以权值的相加 }

for(j=0;j<3;j++){//计算hidden_in[],hidden_output[]

hidden_in[j] = input[j] =

x2*(((Vector)vc1.get(j)).get(1)).doubleValue()+ x3*(((Vector)vc1.get(j)).get(2)).doubleValue(); in_output[j] = 1/(1+Math.pow(Math.E, -input[j]));//s形函数

x1*(((Vector)vc1.get(j)).get(0)).doubleValue()+

in_output[0]*(((Vector)vc2.get(j)).get(0)).doubleValue()+

for(j=0;j<2;j++){

o_in[j] =

hidden_output[0]*(((Vector)vc3.get(j)).get(0)).doubleValue()+

hidden_output[1]*(((Vector)vc3.get(j)).get(1)).doubleValue()+

hidden_output[2]*(((Vector)vc3.get(j)).get(2)).doubleValue(); }

public double calculate_ep(double output1[],int n){//根据第n个样本的实际输

double expect[] = (double[]) double ep1; ep1 = }

o_put[j] = 1/(1+Math.pow(Math.E, -o_in[j]));

出output1[]计算输出误差

(((Vector)sa.hashmap.get(n)).get(1));

(Math.pow(output1[0]-expect[0],2)+Math.pow(output1[1]-expect[1],2))/2;//7-13公式

}

public double[] adjust_outputlevel_weight(int n){//根据第n个样本来调整输出 }

public double [] adjust_secondlevel_weight(int n){//根据第n个样本来调整隐

double output_error[] = new double[2];//用于存放输出层每个神经元的输出double temp[] = (double

Vector vctemp = new Vector(); double increment = 0.0;//表示权值的增量 double weight_temp;

output((double [])((Vector)sa.hashmap.get(n)).get(0));//得for(int i=0;i<2;i++){//对于第i个神经元 }

return output_error;

vctemp = (Vector)vc3.get(i);

output_error[i] = o_put[i]*(1-o_put[i])*(temp[i]-o_put[i]); for(int j=0;j<3;j++){ }

increment = leaning_rate*output_error[i]*hidden_output[j]; weight_temp =((Double) vctemp.add(j, weight_temp);

return ep1;

层的权值 根据7-15 误差

[])((Vector)sa.hashmap.get(n)).get(1);//得到期望输出

到实际输出

vctemp.get(j)).doubleValue()+increment;

层的权值 根据7-16 7-17 差

(((Double)((Vector)vc3.get(0)).get(i)).doubleValue()*temp[0]+ }

public void adjust_firstlevle_weight(int n){//根据第n个样本来调整输入层的权

(((Double)((Vector)vc2.get(0)).get(i)).doubleValue()*temp[0]+

((Double)((Vector)vc2.get(1)).get(i)).doubleValue()*temp[1]+

((Double)((Vector)vc2.get(2)).get(i)).doubleValue()*temp[2]);

}

Vector vctemp; double increment; double num[]; int i=0,j=0;

double output_error[] = new double[4];//用于存放输入层每个神经元的输出double temp[] = adjust_secondlevel_weight(n);//得到隐层每个神经元的输for(i=0;i<4;i++){

output_error[i] = in_output[i]*(1-in_output[i])* }

Vector vctemp; double increment; for(i=0;i<3;i++){ }

return output_error;

}

vctemp = (Vector)vc2.get(i); for(j=0;j<4;j++){

increment = leaning_rate*output_error[i]*in_output[j];

((Double)((Vector)vc3.get(1)).get(i)).doubleValue()*temp[1]);

double temp[] = adjust_outputlevel_weight(n);//得到输出层每个神经元的for(i=0;i<3;i++){

output_error[i] = hidden_output[i]*(1-hidden_output[i])*

输出误差

int i=0,j=0;

double output_error[] = new double[3];//用于存放隐层每个神经元的输出误

vctemp.add(j,((Double)vctemp.get(j)).doubleValue()+increment);

值 7-16和7-17

误差 出误差

}

}

for(i=0;i<4;i++){ }

//return output_error;

}

vctemp = (Vector)vc1.get(i); for(j=0;j<3;j++){

num = (double

increment = leaning_rate*output_error[i]*num[j];

[])((Vector)sa.hashmap.get(n)).get(0);

vctemp.add(j,((Double)vctemp.get(j)).doubleValue()+increment);

public void practice(int n){//n表示样本数量 训练过程 }

public void study(int n){//测试 }

for(int i=0;ioutput(((Vector)sa.hashmap2.get(i)).get(0)); ep2[i] = calculate_ep(o_put,i); System.out.println(ep2[i]); int i = 0;

int t = 0;//临时变量,用于select_small()的返回值,表示第t个样本 double sum = 1;//表示样本集误差总和 int s=0; double temp =0; while(sum>min_error){ }

/*for(i=0;i<400;i++){

System.out.println(ep[i]); }*/

sum = 0;

for(i=0;ioutput(((Vector)sa.hashmap.get(i)).get(0)); temp = calculate_ep(o_put,i); sum += temp; if(s==0){ }

adjust_firstlevle_weight(i);

ep[i] = temp;

样本和测试程序:

//package BackPropagation;

import java.util.HashMap; import java.util.Map; import java.util.Vector;

public class Sample { Vector z; double x[],y[]; Map> hashmap; Map> hashmap2; Sample(){ x = new double[3]; y = new double[2]; z = new Vector(2); hashmap = new HashMap>(400);//400个训练样本 hashmap2 = new HashMap>(100);//100个测试样本 for(int i=0;i<400;i++){//400个样本 for(int j=0;j<3;j++){ x[j] = Math.random()*100; } for(int k=0;k<2;k++){ y[k] = Math.random()*100; } z.add(x); z.add(y); hashmap.put(i,z); } for(int i=0;i<100;i++){ for(int j=0;j<3;j++){ x[j] = Math.random(); } for(int k=0;k<2;k++){ y[k] = Math.random(); } z.add(x); z.add(y); hashmap2.put(i,z); } } }

作图程序:

//package BackPropagation;

import java.awt.Color; import java.awt.Frame; import java.awt.Graphics;

public class Curve extends Frame{ BackPropagation bp = new BackPropagation(); double temp[] = bp.ep; public void paint(Graphics g){ this.setBackground(Color.GRAY); g.setColor(Color.BLACK); for(int i=0;i<100;i++){ g.drawLine(i*10,(int)(temp[i]*10000),(i+1)*10,(int)(temp[i+1]*10000)); //System.out.println((int)(temp[i]*10000)); } //g.drawLine(0,325,600,125); } public static void main(String[] args) { Curve curve = new Curve(); curve.setSize(600,600); curve.setLocation(100,100); curve.setVisible(true); } }

因篇幅问题不能全部显示,请点此查看更多更全内容