BP网络之C#实现

    技术2022-05-11  66

     using System;using System.IO;using System.Text;namespace BpANNet{  /// <summary>  /// BpNet 的摘要说明。  /// </summary>  public class BpNet  {    public int inNum;//输入节点数    int hideNum;//隐层节点数    public int outNum;//输出层节点数    public int sampleNum;//样本总数        Random R;    double [] x;//输入节点的输入数据    double [] x1;//隐层节点的输出    double [] x2;//输出节点的输出

        double [] o1;//隐层的输入    double [] o2;//输出层的输入    public double [,] w;//权值矩阵w    public double [,] v;//权值矩阵V    public double [,] dw;//权值矩阵w    public double [,] dv;//权值矩阵V   

        public double rate;//学习率    public double [] b1;//隐层阈值矩阵    public double [] b2;//输出层阈值矩阵    public double [] db1;//隐层阈值矩阵    public double [] db2;//输出层阈值矩阵        double [] pp;//输出层的误差    double [] qq;//隐层的误差    double [] yd;//输出层的教师数据    public double e;//均方误差    double in_rate;//归一化比例系数

        public int computeHideNum(int m,int n)    {      double s=Math.Sqrt(0.43*m*n+0.12*n*n+2.54*m+0.77*n+0.35)+0.51;      int ss=Convert.ToInt32(s);      return ((s-(double)ss)>0.5) ? ss+1:ss;

        }    public BpNet(double [,] p,double [,] t)    {            // 构造函数逻辑      R=new Random();            this.inNum=p.GetLength(1);      this.outNum=t.GetLength(1);      this.hideNum=computeHideNum(inNum,outNum);//      this.hideNum=18;      this.sampleNum=p.GetLength(0);

          Console.WriteLine("输入节点数目: "+inNum);      Console.WriteLine("隐层节点数目:"+hideNum);      Console.WriteLine("输出层节点数目:"+outNum);            Console.ReadLine();

          x=new double[inNum];      x1=new double[hideNum];      x2=new double[outNum];

          o1=new double[hideNum];      o2=new double[outNum];

          w=new double[inNum,hideNum];      v=new double[hideNum,outNum];      dw=new double[inNum,hideNum];      dv=new double[hideNum,outNum];            b1=new double[hideNum];      b2=new double[outNum];      db1=new double[hideNum];      db2=new double[outNum];            pp=new double[hideNum];      qq=new double[outNum];      yd=new double[outNum];

          //初始化w      for(int i=0;i<inNum;i++)      {        for(int j=0;j<hideNum;j++)        {          w[i,j]=(R.NextDouble()*2-1.0)/2;        }      }

          //初始化v      for(int i=0;i<hideNum;i++)      {        for(int j=0;j<outNum;j++)        {          v[i,j]=(R.NextDouble()*2-1.0)/2;        }      }

          rate=0.8;      e=0.0;      in_rate=1.0;        }

        //训练函数    public void train(double [,] p,double [,] t)    {      e=0.0;      //求p,t中的最大值      double pMax=0.0;      for(int isamp=0;isamp<sampleNum;isamp++)      {        for(int i=0;i<inNum;i++)        {          if(Math.Abs(p[isamp,i])>pMax)          {            pMax=Math.Abs(p[isamp,i]);          }        }

            for(int j=0;j<outNum;j++)        {          if(Math.Abs(t[isamp,j])>pMax)          {            pMax=Math.Abs(t[isamp,j]);          }        }

            in_rate=pMax;      }//end isamp

         

          for(int isamp=0;isamp<sampleNum;isamp++)      {        //数据归一化        for(int i=0;i<inNum;i++)        {          x[i]=p[isamp,i]/in_rate;        }        for(int i=0;i<outNum;i++)        {          yd[i]=t[isamp,i]/in_rate;        }

            //计算隐层的输入和输出

            for(int j=0;j<hideNum;j++)        {          o1[j]=0.0;          for(int i=0;i<inNum;i++)          {            o1[j]+=w[i,j]*x[i];          }          x1[j]=1.0/(1.0+Math.Exp(-o1[j]-b1[j]));        }

            //计算输出层的输入和输出        for(int k=0;k<outNum;k++)        {          o2[k]=0.0;          for(int j=0;j<hideNum;j++)          {            o2[k]+=v[j,k]*x1[j];          }          x2[k]=1.0/(1.0+Math.Exp(-o2[k]-b2[k]));        }

            //计算输出层误差和均方差

            for(int k=0;k<outNum;k++)        {          qq[k]=(yd[k]-x2[k])*x2[k]*(1.0-x2[k]);          e+=(yd[k]-x2[k])*(yd[k]-x2[k]);          //更新V          for(int j=0;j<hideNum;j++)          {            v[j,k]+=rate*qq[k]*x1[j];          }        }

            //计算隐层误差

            for(int j=0;j<hideNum;j++)        {          pp[j]=0.0;          for(int k=0;k<outNum;k++)          {            pp[j]+=qq[k]*v[j,k];          }          pp[j]=pp[j]*x1[j]*(1-x1[j]);

              //更新W

              for(int i=0;i<inNum;i++)          {            w[i,j]+=rate*pp[j]*x[i];          }        }

            //更新b2        for(int k=0;k<outNum;k++)        {          b2[k]+=rate*qq[k];        }                //更新b1        for(int j=0;j<hideNum;j++)        {          b1[j]+=rate*pp[j];        }

          }//end isamp      e=Math.Sqrt(e);//      adjustWV(w,dw);//      adjustWV(v,dv);                }//end train

        public void adjustWV(double [,] w,double[,] dw)    {      for(int i=0;i<w.GetLength(0);i++)      {        for(int j=0;j<w.GetLength(1);j++)        {          w[i,j]+=dw[i,j];        }      }

        }

        public void adjustWV(double [] w,double[] dw)    {      for(int i=0;i<w.Length;i++)      {                w[i]+=dw[i];              }

        }

        //数据仿真函数        public double[] sim(double [] psim)    {      for(int i=0;i<inNum;i++)        x[i]=psim[i]/in_rate;

          for(int j=0;j<hideNum;j++)      {        o1[j]=0.0;        for(int i=0;i<inNum;i++)          o1[j]=o1[j]+w[i,j]*x[i];        x1[j]=1.0/(1.0+Math.Exp(-o1[j]-b1[j]));      }      for(int k=0;k<outNum;k++)      {        o2[k]=0.0;        for(int j=0;j<hideNum;j++)          o2[k]=o2[k]+v[j,k]*x1[j];        x2[k]=1.0/(1.0+Math.Exp(-o2[k]-b2[k]));              x2[k]=in_rate*x2[k];

          }

          return x2;    } //end sim

        //保存矩阵w,v    public void saveMatrix(double [,] w,string filename)    {      StreamWriter sw=File.CreateText(filename);      for(int i=0;i<w.GetLength(0);i++)      {        for(int j=0;j<w.GetLength(1);j++)        {          sw.Write(w[i,j]+" ");        }        sw.WriteLine();      }      sw.Close();

        }

        //保存矩阵b1,b2    public void saveMatrix(double [] b,string filename)    {      StreamWriter sw=File.CreateText(filename);      for(int i=0;i<b.Length;i++)      {        sw.Write(b[i]+" ");      }      sw.Close();    }

        //读取矩阵W,V    public void readMatrixW(double [,] w,string filename)    {            StreamReader sr;      try       {                sr = new StreamReader(filename,Encoding.GetEncoding("gb2312"));               String line;        int i=0;                  while ((line = sr.ReadLine()) != null)         {

              string[] s1=line.Trim().Split(' ');          for(int j=0;j<s1.Length;j++)          {            w[i,j]=Convert.ToDouble(s1[j]);          }          i++;        }        sr.Close();            }      catch (Exception e)       {        // Let the user know what went wrong.        Console.WriteLine("The file could not be read:");        Console.WriteLine(e.Message);      }          }

           

        //读取矩阵b1,b2    public void readMatrixB(double [] b,string filename)    {            StreamReader sr;      try       {                sr = new StreamReader(filename,Encoding.GetEncoding("gb2312"));               String line;        int i=0;                  while ((line = sr.ReadLine()) != null)         {          b[i]=Convert.ToDouble(line);          i++;        }        sr.Close();            }      catch (Exception e)       {        // Let the user know what went wrong.        Console.WriteLine("The file could not be read:");        Console.WriteLine(e.Message);      }     

        }

       

      }//end bpnet} //end namespace

     

    namespace BpANNet{  /// <summary>  /// Class1 的摘要说明。  /// </summary>  class Class1  {    /// <summary>    /// 应用程序的主入口点。    /// </summary>    [STAThread]    static void Main(string[] args)    {      //0.1399,0.1467,0.1567,0.1595,0.1588,0.1622,0.1611,0.1615,0.1685,0.1789,0.1790      //      double [,] p1=new double[,]{{0.05,0.02},{0.09,0.11},{0.12,0.20},{0.15,0.22},{0.20,0.25},{0.75,0.75},{0.80,0.83},{0.82,0.80},{0.90,0.89},{0.95,0.89},{0.09,0.04},{0.1,0.1},{0.14,0.21},{0.18,0.24},{0.22,0.28},{0.77,0.78},{0.79,0.81},{0.84,0.82},{0.94,0.93},{0.98,0.99}};//      double [,] t1=new double[,]{{1,0},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{0,1},{0,1},{0,1},{1,0},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{0,1},{0,1},{0,1}};      double [,] p1=new double[,]{{0.1399,0.1467,0.1567,0.1595,0.1588,0.1622},{0.1467,0.1567,0.1595,0.1588,0.1622,0.1611},{0.1567,0.1595,0.1588,0.1622,0.1611,0.1615},{0.1595,0.1588,0.1622,0.1611,0.1615,0.1685},{0.1588,0.1622,0.1611,0.1615,0.1685,0.1789}};      double [,] t1=new double[,]{{0.1622},{0.1611},{0.1615},{0.1685},{0.1789},{0.1790}};      BpNet bp=new BpNet(p1,t1);      int study=0;      do      {        study++;        bp.train(p1,t1);//       bp.rate=0.95-(0.95-0.3)*study/50000;//        Console.Write("第 "+ study+"次学习: ");//        Console.WriteLine(" 均方差为 "+bp.e);              }while(bp.e>0.001 && study <50000);      Console.Write("第 "+ study+"次学习: ");      Console.WriteLine(" 均方差为 "+bp.e);      bp.saveMatrix(bp.w,"w.txt");      bp.saveMatrix(bp.v,"v.txt");      bp.saveMatrix(bp.b1,"b1.txt");      bp.saveMatrix(bp.b2,"b2.txt");

    //      double [,] p2=new double[,]{{0.05,0.02},{0.09,0.11},{0.12,0.20},{0.15,0.22},{0.20,0.25},{0.75,0.75},{0.80,0.83},{0.82,0.80},{0.90,0.89},{0.95,0.89},{0.09,0.04},{0.1,0.1},{0.14,0.21},{0.18,0.24},{0.22,0.28},{0.77,0.78},{0.79,0.81},{0.84,0.82},{0.94,0.93},{0.98,0.99}};      double [,] p2=new double[,]{{0.1399,0.1467,0.1567,0.1595,0.1588,0.1622},{0.1622,0.1611,0.1615,0.1685,0.1789,0.1790}};      int aa=bp.inNum;      int bb=bp.outNum;      int cc=p2.GetLength(0);      double [] p21=new double[aa];      double [] t2=new double[bb];      for(int n=0;n<cc;n++)      {        for(int i=0;i<aa;i++)        {          p21[i]=p2[n,i];        }        t2=bp.sim(p21);

            for(int i=0;i<t2.Length;i++)        {          Console.WriteLine(t2[i]+" ");        }

          }

          Console.ReadLine();    }  }}


    最新回复(0)