简单的神经网络模型java版本

代码参考http://blog.csdn.net/luxiaoxun/article/details/7649945,原文是个c++,输入二进制输出对应的十进制;学习后,用java重写了下。

程序描述:输入小写的abcdefghi,会输出它的大写形式

代码中每行第一次出现//后的内容是原c++程序的注释,

eg:在void main()中定义char m='a',会输出A;

package cn.kelaile.ocr;


public class Bpneuralnettest {


public staticint innode= 4 ;//输入结点数

public staticinthidenode= 10;//隐含结点数

public staticint outnode= 1 ;//输出结点数

public staticint trainsample=8;//BP训练样本数

public staticdouble [][]w=newdouble [innode][hidenode];//隐含结点权值

public staticdouble [][]w1=newdouble[hidenode][outnode];//输出结点权值

public staticdouble []b1=newdouble[hidenode];//隐含结点阀值

public staticdouble []b2=newdouble[outnode];//输出结点阀值


public staticdoublerate_w;//权值学习率(输入层-隐含层)

public staticdoublerate_w1;//权值学习率 (隐含层-输出层)

public staticdoublerate_b1;//隐含层阀值学习率

public staticdoublerate_b2;//输出层阀值学习率


public staticdoublee;//误差计算

public staticdoubleerror;//允许的最大误差

public staticdouble []result=newdouble[outnode];//Bp输出


public staticdouble [] pattern(charpp){

 

if(pp=='a'){

double []p={0,0,0,0};

returnp;

}else if(pp=='b'){

double []p={0,0,1,0};

returnp;

}else if(pp=='c'){

double []p={0,1,0,0};

returnp;

}else if(pp=='d'){

double []p={0,1,1,0};

returnp;

}else if(pp=='e'){

double []p={1,0,0,0};

returnp;

}else if(pp=='f'){

double []p={1,0,1,0};

returnp;

}else if(pp=='g'){

double []p={1,1,0,0};

returnp;

}else if(pp=='h'){

double []p={1,1,1,0};

returnp;

}else if(pp=='i'){

double []p={1,1,1,1};

returnp;

}else{

System.out.println("参数为abcdefgh");

returnnull;

}

}

public staticdouble [] recognize(charpp)

{

    double []x=newdouble [innode];//输入向量

    double []x1=newdouble[hidenode];//隐含结点状态值

    double []x2=newdouble[outnode];//输出结点状态值

    double []o1=newdouble[hidenode];//隐含层激活值

    double []o2=newdouble[hidenode];//输出层激活值

    

   double []p=pattern(pp);

    for(inti=0;i<innode;i++)

        x[i]=p[i];

    

    for(intj=0;j<hidenode;j++)

    {

        o1[j]=0.0;

        for(inti=0;i<innode;i++)

            o1[j]=o1[j]+w[i][j]*x[i];//隐含层各单元激活值

        x1[j]=1.0/(1.0+Math.pow(Math.E, -o1[j]-b1[j]));//隐含层各单元输出

        //if(o1[j]+b1[j]>0) x1[j]=1;

        //    else x1[j]=0;

    }

    

    for(intk=0;k<outnode;k++)

    {

        o2[k]=0.0;

        for(intj=0;j<hidenode;j++)

            o2[k]=o2[k]+w1[j][k]*x1[j];//输出层各单元激活值

        x2[k]=1.0/(1.0+Math.pow(Math.E, (-o2[k]-b2[k])));//输出层各单元输出

        //if(o2[k]+b2[k]>0) x2[k]=1;

        //else x2[k]=0;

    }

    

    for(intk=0;k<outnode;k++)

    {

        result[k]=x2[k];

    }

    return result;

}

public staticvoid train(double [][]p,double [][]t)

{

    double []pp=newdouble[hidenode];//隐含结点的校正误差

    double []qq=newdouble[outnode];//希望输出值与实际输出值的偏差

    double []yd=newdouble[outnode];//希望输出值

    

    double []x=newdouble[innode];//输入向量

    double []x1=newdouble[hidenode];//隐含结点状态值

    double []x2=newdouble[outnode];//输出结点状态值

    double []o1=newdouble[hidenode];//隐含层激活值

    double []o2=newdouble[hidenode];//输出层激活值

    

    for(intisamp=0;isamp<trainsample;isamp++)//循环训练一次样品

    {

        for(inti=0;i<innode;i++)

            x[i]=p[isamp][i];//输入的样本

        for(inti=0;i<outnode;i++)

            yd[i]=t[isamp][i];//期望输出的样本

        

        //构造每个样品的输入和输出标准

        for(intj=0;j<hidenode;j++)

        {

            o1[j]=0.0;

            for(inti=0;i<innode;i++)

                o1[j]=o1[j]+w[i][j]*x[i];//隐含层各单元输入激活值

            x1[j]=1.0/(1+Math.pow(Math.E, (-o1[j]-b1[j])));//隐含层各单元的输出

            //    if(o1[j]+b1[j]>0) x1[j]=1;

            //else x1[j]=0;

        }

        

        for(intk=0;k<outnode;k++)

        {

            o2[k]=0.0;

            for(intj=0;j<hidenode;j++)

                o2[k]=o2[k]+w1[j][k]*x1[j];//输出层各单元输入激活值

            x2[k]=1.0/(1.0+Math.pow(Math.E, (-o2[k]-b2[k])));//输出层各单元输出//这里就是用到sigmod函数了

            //    if(o2[k]+b2[k]>0) x2[k]=1;

            //    else x2[k]=0;

        }

        

        for(intk=0;k<outnode;k++)

        {

            qq[k]=(yd[k]-x2[k])*x2[k]*(1-x2[k]);//希望输出与实际输出的偏差//用y表示simod函数,可知道y‘=y(1-y),这个自己推导下就知道了

            for(intj=0;j<hidenode;j++)

                w1[j][k]+=rate_w1*qq[k]*x1[j]; //下一次的隐含层和输出层之间的新连接权

        }

        

        for(intj=0;j<hidenode;j++)

        {

            pp[j]=0.0;

            for(intk=0;k<outnode;k++)

                pp[j]=pp[j]+qq[k]*w1[j][k];

            pp[j]=pp[j]*x1[j]*(1-x1[j]);//隐含层的校正误差

            

            for(inti=0;i<innode;i++)

                w[i][j]+=rate_w*pp[j]*x[i];//下一次的输入层和隐含层之间的新连接权

        }

        

        for(intk=0;k<outnode;k++)

        {

            e+=Math.abs(yd[k]-x2[k])*Math.abs(yd[k]-x2[k]);//计算均方差

        }

        error=e/2.0;

        

        for(intk=0;k<outnode;k++)

            b2[k]=b2[k]+rate_b2*qq[k];//下一次的隐含层和输出层之间的新阈值//这个就是调整权值很常用的求法或者建模方法了,hash映射时候也是这么求的。

        for(intj=0;j<hidenode;j++)

            b1[j]=b1[j]+rate_b1*pp[j];//下一次的输入层和隐含层之间的新阈值

    }

}

//输入样本

public staticdouble [][]X= {

  {0,0,0,0},{0,0,1,0},{0,1,0,0},{0,1,1,0},{1,0,0,0},{1,0,1,0},{1,1,0,0},{1,1,1,0},{1,1,1,1}

};

public static String[]Sample={"ABCDEFGH"


};

//期望输出样本

public staticdouble [][]Y={

  {0},{0.125},{0.250},{0.375},{0.500},{0.625},{0.850},{0.975},{1.0000}

};

public staticvoid winit(doublew[],intn)//权值初始化

{

    for(inti=0;i<n;i++)

        w[i]=(2.0*(double)Math.random())-1;

}

public staticvoid winit(doublew[][],intn)//权值初始化

{

for(intj=0;j<w.length;j++){


    for(inti=0;i<w[j].length;i++){

        w[j][i]=(2.0*(double)Math.random())-1;

        }

    }

}



public staticvoid init(){

winit(w,innode*hidenode);

    winit(w1,hidenode*outnode);

    winit(b1,hidenode);

    winit(b2,outnode);

}


public static void main(String[]args) {

// TODO Auto-generated method stub

error= 1.0;

    e=0.0f;

   

    rate_w= 0.9; //权值学习率(输入层--隐含层)

    rate_w1= 0.9;//权值学习率 (隐含层--输出层)

    rate_b1= 0.9; //隐含层阀值学习率

    rate_b2= 0.9; //输出层阀值学习率

    init();

    int times=0;

    while(error>0.0001)

    {

        e=0.0;

        times++;

        train(X,Y);

        System.out.println("Times="+times+" error="+error);

       

    }

    System.out.println("trainning complete...");

   

    char m='f';

    double[] r=recognize(m);

    for(inti=0;i<outnode;++i){

       

    System.out.println(result[i]+" ");

    }

    double [][]cha=newdouble[trainsample][outnode];

    double mi=100;

    int index=99999;

    for(inti=0;i<trainsample;i++)

    {

        for(intj=0;j<outnode;j++)

        {

            //找差值最小的那个样本

            cha[i][j]=(double)(Math.abs(Y[i][j]-result[j]));

            if(cha[i][j]<mi)

            {

                mi=cha[i][j];

                index=i;

            }

        }

    }

   

        System.out.println(m);

   

    String res="ABCDEFGHI";

    char[] ch = res.toCharArray();

   

    System.out.println(" is "+ch[index]);

   

   


}


}


posted on 2014-11-18 19:11  决心1119  阅读(304)  评论(0编辑  收藏  举报

导航