BP神经网络实现(Java代码)

来源:互联网 发布:mac版wow怎么安装插件 编辑:程序博客网 时间:2024/05/17 07:32

神经网络的原理虽然理解起来不难,但是要是想实现它,还是需要做一些工作的,并且有很多细节性的东西需要注意。通过参阅各种相关资料,以及参考网络上已有的资源,自己写了一个含有一个隐含层,且只能有一个输出单元的简单的BP网络,经过测试,达到了预期的效果。

需要说明的是,神经网络的每个输入都在[0,1]中,输出也在[0,1]中,在使用神经网络解决实际问题的时候,还需要对实际问题的输入输出进行归一化处理。另外,尽量不要使得神经网络的输入或输出接近于0或1,这样会影响拟合效果。

我用正弦函数进行了一次测试,效果如图所示:


以下是相关的代码:

1.神经网络代码

package pkg1;import java.util.Scanner;/* *  */public class TestNeuro {private int INPUT_DIM=1;private int HIDDEN_DIM=20;private double LEARNING_RATE=0.05;double [][] input_hidden_weights=new double[INPUT_DIM][HIDDEN_DIM];double [] hidden_output_weights=new double[HIDDEN_DIM];double[] hidden_thresholds=new double[HIDDEN_DIM];double output_threshold;public static void main(String[]args){Scanner in=new Scanner(System.in);TestNeuro neuro=new TestNeuro(1,5);neuro.initialize();for(int i=0;i<10000;i++){double[] input=new double[1];input[0]=Math.random();double expectedOutput=input[0]*input[0];//System.out.println("input : "+input[0]+"\t\texpectedOutput : "+expectedOutput);//System.out.println("predict before training : "+neuro.predict(input));neuro.trainOnce(input, expectedOutput);//System.out.println("predict after training : "+neuro.predict(input));//in.next();}while(true){//neuro.printLinks();double[] input=new double[1];input[0]=in.nextDouble();double expectedOutput=in.nextDouble();System.out.println("predict before training : "+neuro.predict(input));neuro.trainOnce(input, expectedOutput);System.out.println("predict after training : "+neuro.predict(input));}}public TestNeuro(int input_dimension,int hidden_dimension){this.INPUT_DIM=input_dimension;this.HIDDEN_DIM=hidden_dimension;this.initialize();}/** * 打印出本神经元网络各层之间的连接权重,以及各个神经元上的阈值的信息。 */void print(){System.out.println("隐含层阈值:");for(int i=0;i<HIDDEN_DIM;i++){System.out.print(hidden_thresholds[i]+" ");}System.out.println();System.out.println("输出层阈值:");System.out.println(output_threshold);System.out.println("连接权重:*********************");System.out.println("输入层与隐含层的连接");for(int i=0;i<INPUT_DIM;i++){for(int j=0;j<HIDDEN_DIM;j++){System.out.print(input_hidden_weights[i][j]+" ");}System.out.println();}System.out.println("隐含层到输出层的连接");for(int i=0;i<HIDDEN_DIM;i++){System.out.print(hidden_output_weights[i]+" ");}System.out.println();System.out.println("*********************************");}/** * 初始化,对所有的权值产生一个(0,1)之间的随机double型值 */void initialize(){//输入层到隐含层的连接权重for(int i=0;i<INPUT_DIM;i++){for(int j=0;j<HIDDEN_DIM;j++){input_hidden_weights[i][j]=Math.random();}}//隐含层到输出层的连接权重for(int i=0;i<HIDDEN_DIM;i++){hidden_output_weights[i]=Math.random();}//隐含层的阈值for(int i=0;i<HIDDEN_DIM;i++){hidden_thresholds[i]=Math.random();}//输出层的阈值output_threshold=Math.random();}/** * 激励函数 * @param x * @return */double function(double x){return 1/(1+Math.pow(Math.E, -x));}/** * 给定一个输入,进行预测 * @param input * @return */double predict(double[]input){double[] hiddenValues=new double[HIDDEN_DIM];for(int i=0;i<hiddenValues.length;i++){double sum=0;for(int j=0;j<input.length;j++){sum+=input[j]*input_hidden_weights[j][i];}sum+=hidden_thresholds[i];//再加上本神经元的阈值hiddenValues[i]=function(sum);}double sum=0;for(int i=0;i<HIDDEN_DIM;i++){sum+=hiddenValues[i]*hidden_output_weights[i];}sum+=output_threshold;//输出层神经元的阈值return function(sum);}/** * 进行一次训练 * @param input * @param expectedOutput */void trainOnce(double[] input, double expectedOutput){double[] hiddenValues=new double[HIDDEN_DIM];double[] hiddenParams=new double[HIDDEN_DIM];for(int i=0;i<hiddenValues.length;i++){double sum=0;for(int j=0;j<input.length;j++){sum+=input[j]*input_hidden_weights[j][i];}sum+=hidden_thresholds[i];//hiddenValues[i]=function(sum);hiddenParams[i]=sum;}double sum=0;for(int i=0;i<HIDDEN_DIM;i++){sum+=hiddenValues[i]*hidden_output_weights[i];}sum+=output_threshold;//double outputValue=function(sum);double outputParam=sum;//System.out.println("实际输出");/* * 调整权值和阈值 */for(int i=0;i<input.length;i++){double factor=(expectedOutput-outputValue)*outputValue*(1-outputValue)*LEARNING_RATE*input[i];for(int j=0;j<HIDDEN_DIM;j++){double delta=factor*hidden_output_weights[j]*hiddenValues[j]*(1-hiddenValues[j]);//System.out.println("输入层到隐含层连接的权重调整:delta = "+delta+"\t\t weight = "+input_hidden_weights[i][j]);input_hidden_weights[i][j]+=delta;}}double factor=(expectedOutput-outputValue)*outputValue*(1-outputValue)*LEARNING_RATE;for(int i=0;i<hidden_thresholds.length;i++){double delta=factor*hidden_output_weights[i]*hiddenValues[i]*(1-hiddenValues[i]);hidden_thresholds[i]+=delta;}//System.out.println("hidden_output_weights : "+hidden_output_weights.length);for(int i=0;i<hidden_output_weights.length;i++){//w+=(exp-act)*df/dw//df/dw=x(1-x)*hiddenjdouble delta=factor*hiddenValues[i];//System.out.println("隐含层到输出层连接的权值调整:delta = "+delta+"\t\t weight = "+hidden_output_weights[i]);hidden_output_weights[i]+=delta;}double delta=(expectedOutput-outputValue)*outputValue*(1-outputValue)*LEARNING_RATE;output_threshold+=delta;if(Math.abs(outputValue-expectedOutput)>0.1){//System.out.println(input[0]+"\t\t"+outputValue+"\t\t"+expectedOutput);}}}


2.测试代码


package pkg1;import java.awt.Graphics;import java.util.Scanner;import javax.swing.JFrame;public class DisplayNeuro extends javax.swing.JPanel{public static final int SIDE_LENGTH=200;TestNeuro neuro;//=new TestNeuro();/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubDisplayNeuro dn=new DisplayNeuro();JFrame jFrame=new JFrame();jFrame.setBounds(100, 100, 300, 300);jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jFrame.add(dn);jFrame.setVisible(true);TestNeuro neuro=new TestNeuro(1,20);dn.neuro=neuro;Scanner in=new Scanner(System.in);dn.repaint();for(int i=0;i<100000000;i++){double[] input=new double[1];input[0]=Math.random()/2+0.25;double expectedOutput=(Math.sin(3.14*(input[0]-0.25)*2*4)+1)/8*3+0.125;//System.out.println("input : "+input[0]+"\t\texpectedOutput : "+expectedOutput);//System.out.println("predict before training : "+neuro.predict(input));neuro.trainOnce(input, expectedOutput);//System.out.println("predict after training : "+neuro.predict(input));if(i%100000==0){System.out.println("input please ");//in.next();//neuro.initialize();dn.repaint();}}}@Overridepublic void paint(Graphics arg0) {// TODO Auto-generated method stubsuper.paint(arg0);for(double x=0.25;x<0.75;x+=0.005){double[] input=new double[1];input[0]=x;double y=neuro.predict(input);arg0.fillRect((int)(x*SIDE_LENGTH), (int)((1-y)*SIDE_LENGTH), 1, 1);}}}