BP神经网络实现(Java代码)神经网络的原理虽然理解起来不难,但是要是想实现它,还是需要做一些工作的,并且有很多细节性的东西需要注意。
通过参阅各种相关资料,以及参考网络上已有的资源,自己写了一个含有一个隐含层,且只能有一个输出单元的简单的BP网络,经过测试,达到了预期的效果。
需要说明的是,神经网络的每个输入都在[0,1]中,输出也在[0,1]中,在使用神经网络解决实际问题的时候,还需要对实际问题的输入输出进行归一化处理。
另外,尽量不要使得神经网络的输入或输出接近于0或1,这样会影响拟合效果。
我用正弦函数进行了一次测试,效果如图所示:以下是相关的代码:1.神经网络代码[java]view plaincopy1.package pkg1;2.3.import java.util.Scanner;4.5./*6.*7.*/8.public class TestNeuro{9.10.private int INPUT_DIM=1;11.private int HIDDEN_DIM=20;12.private double LEARNING_RATE=0.05;13.double[][]input_hidden_weights=new double[INPUT_DIM][HIDDEN_DIM];14.double[]hidden_output_weights=new double[HIDDEN_DIM];15.double[]hidden_thresholds=new double[HIDDEN_DIM];16.double output_threshold;17.18.public static void main(String[]args){19.Scanner in=new Scanner(System.in);20.TestNeuro neuro=new TestNeuro(1,5);21.neuro.initialize();22.for(int i=0;i<10000;i++){23.double[]input=new double[1];24.input[0]=Math.random();25.double expectedOutput=input[0]*input[0];26.//System.out.println("input:"+input[0]+"\t\texpectedOutput:"+expectedOutput);27.//System.out.println("predict before training:"+neuro.predict(input));28.neuro.trainOnce(input,expectedOutput);29.//System.out.println("predict after training:"+neuro.predict(input));30.//in.next();31.}32.while(true){33.//neuro.printLinks();34.double[]input=new double[1];35.input[0]=in.nextDouble();36.double expectedOutput=in.nextDouble();37.System.out.println("predict before training:"+neuro.predict(input));38.neuro.trainOnce(input,expectedOutput);39.System.out.println("predict after training:"+neuro.predict(input));40.41.}42.}43.44.public TestNeuro(int input_dimension,int hidden_dimension){45.this.INPUT_DIM=input_dimension;46.this.HIDDEN_DIM=hidden_dimension;47.this.initialize();48.}49.50.51./**52.*打印出本神经元网络各层之间的连接权重,以及各个神经元上的阈值的信息。
53.*/54.void print(){55.System.out.println("隐含层阈值:");56.for(int i=0;i<HIDDEN_DIM;i++){57.System.out.print(hidden_thresholds[i]+"");58.}System.out.println();59.System.out.println("输出层阈值:");60.System.out.println(output_threshold);61.62.System.out.println("连接权重:*********************");63.System.out.println("输入层与隐含层的连接");64.for(int i=0;i<INPUT_DIM;i++){65.for(int j=0;j<HIDDEN_DIM;j++){66.System.out.print(input_hidden_weights[i][j]+"");67.}System.out.println();68.}69.System.out.println("隐含层到输出层的连接");70.for(int i=0;i<HIDDEN_DIM;i++){71.System.out.print(hidden_output_weights[i]+"");72.}System.out.println();73.System.out.println("*********************************");74.}75.76./**77.*初始化,对所有的权值产生一个(0,1)之间的随机double型值78.*/79.void initialize(){80.81.//输入层到隐含层的连接权重82.for(int i=0;i<INPUT_DIM;i++){83.for(int j=0;j<HIDDEN_DIM;j++){84.input_hidden_weights[i][j]=Math.random();85.}86.}87.//隐含层到输出层的连接权重88.for(int i=0;i<HIDDEN_DIM;i++){89.hidden_output_weights[i]=Math.random();90.}91.//隐含层的阈值92.for(int i=0;i<HIDDEN_DIM;i++){93.hidden_thresholds[i]=Math.random();94.}95.//输出层的阈值96.output_threshold=Math.random();97.}98.99./**100.*激励函数101.*@param x102.*@return103.*/104.double function(double x){105.return1/(1+Math.pow(Math.E,-x));106.}107.108./**109.*给定一个输入,进行预测110.*@param input111.*@return112.*/113.double predict(double[]input){114.double[]hiddenValues=new double[HIDDEN_DIM]; 115.for(int i=0;i<hiddenValues.length;i++){116.double sum=0;117.for(int j=0;j<input.length;j++){118.sum+=input[j]*input_hidden_weights[j][i]; 119.}120.sum+=hidden_thresholds[i];//再加上本神经元的阈值121.hiddenValues[i]=function(sum);122.}123.124.125.double sum=0;126.for(int i=0;i<HIDDEN_DIM;i++){127.sum+=hiddenValues[i]*hidden_output_weights[i]; 128.}129.sum+=output_threshold;//输出层神经元的阈值130.return function(sum);131.}132.133./**134.*进行一次训练135.*@param input136.*@param expectedOutput137.*/138.void trainOnce(double[]input,double expectedOutput){139.double[]hiddenValues=new double[HIDDEN_DIM];140.double[]hiddenParams=new double[HIDDEN_DIM];141.142.for(int i=0;i<hiddenValues.length;i++){143.double sum=0;144.for(int j=0;j<input.length;j++){145.sum+=input[j]*input_hidden_weights[j][i];146.}147.sum+=hidden_thresholds[i];//148.hiddenValues[i]=function(sum);149.hiddenParams[i]=sum;150.}151.152.double sum=0;153.for(int i=0;i<HIDDEN_DIM;i++){154.sum+=hiddenValues[i]*hidden_output_weights[i];155.}156.sum+=output_threshold;//157.double outputValue=function(sum);158.double outputParam=sum;159.//System.out.println("实际输出");160.161./*162.*调整权值和阈值163.*/164.165.for(int i=0;i<input.length;i++){166.double factor=(expectedOutput-outputValue)*outputValue*(1-outpu tValue)*LEARNING_RATE*input[i];167.for(int j=0;j<HIDDEN_DIM;j++){168.double delta=factor*hidden_output_weights[j]*hiddenValues[j] *(1-hiddenValues[j]);169.//System.out.println("输入层到隐含层连接的权重调整:delta="+delta+"\t\t weight="+input_hidden_weights[i][j]);170.input_hidden_weights[i][j]+=delta;171.}172.}173.double factor=(expectedOutput-outputValue)*outputValue*(1-outputVal ue)*LEARNING_RATE;174.for(int i=0;i<hidden_thresholds.length;i++){175.double delta=factor*hidden_output_weights[i]*hiddenValues[i]*(1 -hiddenValues[i]);176.hidden_thresholds[i]+=delta;177.}178.179.//System.out.println("hidden_output_weights:"+hidden_output_weigh ts.length);180.for(int i=0;i<hidden_output_weights.length;i++){181.//w+=(exp-act)*df/dw182.//df/dw=x(1-x)*hiddenj183.double delta=factor*hiddenValues[i];184.//System.out.println("隐含层到输出层连接的权值调整:delta="+delta+"\t\t weight="+hidden_output_weights[i]);185.hidden_output_weights[i]+=delta;186.187.}188.double delta=(expectedOutput-outputValue)*outputValue*(1-outputValue)*LEARNING_RATE;189.output_threshold+=delta;190.if(Math.abs(outputValue-expectedOutput)>0.1){191.//System.out.println(input[0]+"\t\t"+outputValue+"\t\t"+expecte dOutput);192.}193.194.195.196.}197.198.}2.测试代码[java]view plaincopy1.package pkg1;2.3.import java.awt.Graphics;4.import java.util.Scanner;5.6.import javax.swing.JFrame;7.8.public class DisplayNeuro extends javax.swing.JPanel{9.10.public static final int SIDE_LENGTH=200;11.12.TestNeuro neuro;//=new TestNeuro();13./**14.*@param args15.*/16.public static void main(String[]args){17.//TODO Auto-generated method stub18.DisplayNeuro dn=new DisplayNeuro();19.JFrame jFrame=new JFrame();20.jFrame.setBounds(100,100,300,300);21.jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);22.jFrame.add(dn);23.jFrame.setVisible(true);24.25.TestNeuro neuro=new TestNeuro(1,20);26.dn.neuro=neuro;27.Scanner in=new Scanner(System.in);28.dn.repaint();29.for(int i=0;i<100000000;i++){30.double[]input=new double[1];31.input[0]=Math.random()/2+0.25;32.double expectedOutput=(Math.sin(3.14*(input[0]-0.25)*2*4)+1)/8*3+0.125;33.//System.out.println("input:"+input[0]+"\t\texpectedOutput:"+expectedOutput);34.//System.out.println("predict before training:"+neuro.predict(input));35.neuro.trainOnce(input,expectedOutput);36.//System.out.println("predict after training:"+neuro.predict(input));37.38.if(i%100000==0){39.40.System.out.println("input please");41.//in.next();42.//neuro.initialize();43.dn.repaint();44.}45.46.}47.}48.49.50.@Override51.public void paint(Graphics arg0){52.//TODO Auto-generated method stub53.super.paint(arg0);54.55.for(double x=0.25;x<0.75;x+=0.005){56.double[]input=new double[1];57.input[0]=x;58.double y=neuro.predict(input);59.arg0.fillRect((int)(x*SIDE_LENGTH),(int)((1-y)*SIDE_LENGTH),1,1);60.}61.62.63.}64.65.66.}。