⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 采用ga优化的bp神经网络程序.txt

📁 程序名:ga_bp_predict.cpp 描述: 采用GA优化的BP神经网络程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
/*************************************************
程序名:ga_bp_predict.cpp
描述:  采用GA优化的BP神经网络程序,用于单因素时间
    序列的预测,采用了单步与多步相结合预测
说明:  采用GA(浮点编码)优化NN的初始权值W[j][i],V[k][j],然后再采用BP算法
    优化权值  
日期:  April 14,2005
修改记录:

**************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*************************************************
        变量申明
*************************************************/

/*************NN Paraments***********************/
#define  InNum      4      //输入层神经元个数
#define  HiddenNum    7      //隐层神经元个数
#define  OutNum      2      //输出层神经元个数,即所需要预测的步数

#define  N_SAMPLE    50      //原样本个数
#define  P        (N_SAMPLE-InNum+1)  //采用滑动预测时NN的开始样本

double  I[InNum];      //输入层节点数据
double  T[OutNum];      //输出层教师数据
double  U[HiddenNum];    //隐层输入值
double  H[HiddenNum];    //隐层输出值
double  S[OutNum];      //输出层输入
double  O[OutNum];      //输出层输出值
double  W[HiddenNum][InNum];//输入到隐层权值
double WSave[HiddenNum][InNum];
double V[OutNum][HiddenNum];//隐层到输出的权值
double VSave[OutNum][HiddenNum];
double  theta[HiddenNum];  //隐层层阈值
double  theta_save[HiddenNum];
double  gama[OutNum];    //输出层阈值
double  gama_save[OutNum];
double  Error[OutNum];      //第i个样本的输出误差
double alpha;        //学习率
double  beta;        //动量项

double predict_out[OutNum];    //单步输出
double Max;        //样本时间序列中的最大值,供还原用
double Min;
double  CheckError;      //检验误差限

FILE  *nn_fp;        //写入文件指针
FILE  *fp;

/****************GA Paraments**********************************/

#define POP_SIZE  20        //种群的规模,即GA中初始权值的个数
#define  MAX_GEN    100        //最大进化代数
#define  P_XOVER    0.80      //交叉概率
#define P_MUTATE  0.01      //变异概率

#define  P1_XOVER  0.80      //用于自适应的交叉变异概率
#define  P2_XOVER  0.85
#define  P1_MUTATE  0.01
#define  P2_MUTATE  0.015
#define  NUM_SELECT 2        //竞争选择法时随即选择的个数,这里为3,不要太多,否则种群过早成熟

#define FALSE 0
#define TRUE 1
FILE  *ga_fp;

int    generation;
int    NumGATestSample=30;

/***************Problem Paraments****************************/
double NewSeries[N_SAMPLE];
double Series[N_SAMPLE]={
    100.000, 103.007, 96.785, 89.289, 90.915, 95.174 ,
     90.753, 82.537, 82.532, 87.546, 85.125, 76.693 ,
     74.908, 80.133, 79.762, 71.646, 68.087, 72.972 ,
     74.550, 67.267, 62.092, 66.125, 69.403, 63.416 ,
     56.919, 59.664, 64.271, 59.946, 52.538, 53.671 ,
     59.136, 56.715, 48.888, 48.221, 54.013, 53.597 ,
     45.881, 43.378, 48.947, 50.483, 43.409, 39.185 ,
     44.008, 47.293, 41.346, 35.662, 39.278, 43.977, 
     39.558, 32.797 
};

//染色体的构造
struct chromo_type
{
  double  upper;
  double lower;              //变量的上限下限值,这里是0-1
  double  fitness;            //种群的适应值
  double  rfitness;            //个体的适应度
  double total_fitness;          //个体的总体相对适应度,在选择算子(轮盘赌策略)中用到
  double   gene1[HiddenNum][InNum];    //染色体的编码
  double  gene2[OutNum][HiddenNum];
};

struct chromo_type population[POP_SIZE];    //种群
struct chromo_type newpopulation[POP_SIZE]; //新种群
struct chromo_type BestIndividual;      //当前最佳个体
struct chromo_type WorstIndividual;      //最差个体,这里没有采用,如果稳定态策略的话有用

/*********************************************************************/
/*        所用函数申明                     */
/*********************************************************************/
double  Weight_Fitness(int );
void  RecordOptimizedWeight();
void  InputLayerToHiddenLayer();
void  HiddenLayerToOutputLayer();
void  GetSample(int );

/*********************************************************
      Initialize the Network
*********************************************************/
void GetMaxMin()    //得到序列的最值
{
  int    i;
  Max=Min=Series[0];
  for(i=0;i<N_SAMPLE;i++)
  {
    if(Series[i]>Max)
      Max=Series[i];
    if(Series[i]<Min)
      Min=Series[i];
  }
}

void RenewSeries() //更新序列,可以用于多步预测
{
  int    i;

  for(i=P;i<N_SAMPLE-OutNum;i++)
  {
    Series[i]=Series[i+1];
  }
  for(i=N_SAMPLE-OutNum;i<N_SAMPLE;i++)
  {
    Series[i]=predict_out[i];
  }
}

void DataNormalize()  //归一化输入和输出数据,
{
  int    i;

  GetMaxMin();

  for(i=0;i<N_SAMPLE;i++)
  {
    NewSeries[i]=(Max-Series[i])*0.8/(Max-Min);  //注意最值问题,因为预测后的值可能回会超出当前的最值范围
  }
}

void GetSample(int m)  // 得到第m个样本
{
  int    i;
  int    k;
    
  for(i=m;i<m+InNum;i++)
  {
    I[i]=NewSeries[i];
  }

  for(k=m+InNum;k<m+InNum+OutNum;k++)
  {
    T[k]=NewSeries[k];
  }
}

void randomize()
{
  srand(1000);
}

double randval()              //随机数发生器
{
  double val;
  val=((double)(rand()%1000))/1000.0;
  return val;
}

//初始化权重和阈值函数
void NN_Initialize()      
{
  int i,j,k;

  //初始化I-H层阈值和权重
  for(i=0;i<InNum;i++)
  {
    for(j=0;j<HiddenNum;j++)
    {
      W[j][i]=randval();
    }
  }

  for(j=0;j<HiddenNum;j++)
  {
    theta[j]=randval();
  }

  //初始化I-H层阈值和权重,其实它们的域是不是(0,1)我并不是很清楚
  for(k=0;k<OutNum;k++)
  {
    for(j=0;j<HiddenNum;j++)
    {
      V[k][j]=randval();
    }
  }
  for(k=0;k<OutNum;k++)
  {
    gama[k]=randval(); 
  }
}

//s函数
double sigmoid(double x)
{
  double sval;
  sval=1.0/(1+exp(-x));
  return sval;
}

/********************************************************************/
/*        GA开始优化权值                    */
/********************************************************************/
  
double GetRandVal(double low,double high)      //获得随机数(0,1)
{
  double  val;
  val=(double)(rand()%1000)*(high-low)/1000.0+low;  
  return val;
}

void GA_Initialize()                //GA的初始化
{
  int    pop;
  int    i;
  int    j;
  int    k;

  for(pop=0;pop<POP_SIZE;pop++)              //初始化种群
  {
    population[pop].upper=1;
    population[pop].lower=0;
    population[pop].fitness=0;
    population[pop].rfitness=0;
    population[pop].total_fitness=0;

    for(j=0;j<HiddenNum;j++) 
    {
      for(i=0;i<InNum;i++)
      {
        population[pop].gene1[j][i]=GetRandVal(0,1);  //基因采用实数编码
      }
    }

    for(k=0;k<OutNum;k++)
    {
      for(j=0;j<HiddenNum;j++)
      {
        population[pop].gene2[k][j]=GetRandVal(0,1);  
      }
    }
  }

  BestIndividual=population[0];        //给全局最优,最差变量赋初值
  WorstIndividual=population[0];
}

void Evaluate_Weight()              //评估种群适应度值
{
  int    i;

  for(i=0;i<POP_SIZE;i++)
  {
    population[i].fitness=Weight_Fitness(i);
  }
}

void Convert_GA_NN(int  pop)          //将基因的转换到网络参数
{
  int    i,j,k;

  for(j=0;j<HiddenNum;j++)
  {
    for(i=0;i<InNum;i++)
    {
      W[j][i]=population[pop].gene1[j][i];
    }
  }
  for(k=0;k<OutNum;k++)
  {
    for(j=0;j<HiddenNum;j++)
    {
      V[k][j]=population[pop].gene2[k][j];
    }
  }
}

double ErrorCompute()          //第pop个个体的误差计算
{
  int    k;
  double err;
  double  error;

  err=0;  
  for(k=0;k<OutNum;k++)
  {
    err+=(T[k]-O[k])*(T[k]-O[k])/2.0;
  }
  error=err;    
  return(error);
}

double Weight_Fitness(int pop)          //评价进化误差函数函数,对输入的n个样本求最小均方误差    
{
  int    i;
  double  fitness_val;
  double  error;

  error=0;  
  for(i=0;i<NumGATestSample;i++)
  {
    GetSample(i);
    Convert_GA_NN(pop);
    InputLayerToHiddenLayer();
    HiddenLayerToOutputLayer();
  }
    error+=ErrorCompute();  
    fitness_val=1.0/error;
  return fitness_val;
}

void Select_Roulette() //roulette strategy
{
  int    i;
  int    j;
  int    k;
  int    pop;
  double  sum;
  double  p;  //随即数

  sum=0;

  for(i=0;i<POP_SIZE;i++)
  {
    sum+=population[i].fitness;
  }

  population[0].total_fitness=0;
  for(i=0;i<POP_SIZE;i++)
  {
    population[i].rfitness=population[i].fitness/sum;      
  }
  population[0].total_fitness=population[0].rfitness;
  for(i=1;i<POP_SIZE;i++)
  {
    population[i].total_fitness=population[i-1].total_fitness+population[i].rfitness;
  }
  //得到各个染色体的相对适应值和总体适应值
  //下面进行选择操作
  for(i=0;i<POP_SIZE;i++)
  {
    p=GetRandVal(0,1);
    if(p<population[i].total_fitness)  //如果p小于total_fitness的话,选择第一个
      newpopulation[i]=population[0];
    else
    {
      for(j=0;j<POP_SIZE;j++)
        if(p>population[j].total_fitness && p<population[j+1].total_fitness)
          newpopulation[j+1]=population[j+1];
    }
  }  //选择完毕,下面得到新的种群

  for(pop=0;pop<POP_SIZE;pop++)
  {
    population[pop]=newpopulation[pop];
  }

  fp=fopen("population.dat","w");

  for(pop=0;pop<POP_SIZE;pop++)
  {
    fprintf(fp,"\nthe %d population :\n",pop);
    for(j=0;j<HiddenNum;j++)
      {
        for(i=0;i<InNum;i++)
        {
          fprintf(fp,"%lf ",population[pop].gene1[j][i]);
        }
      }
    fprintf(fp,"\n");
      for(k=0;k<OutNum;k++)
      {
        for(j=0;j<HiddenNum;j++)
        {
          fprintf(fp,"%lf ",population[pop].gene2[k][j]);
        }
      }
  }
}

//竞争选择,随即选择几个母体,然后从中选择
//适应值最大的个体,直到选择的个数达到种群个数为止
void Select_Tournament()    
{
  int    i;
  int    j;
  int    rand_mem;
  int    max_mem;
  double  max_fitness;

  max_mem=0;
  max_fitness=population[0].fitness;

  for(i=0;i<POP_SIZE;i++)
  {
    for(j=0;j<NUM_SELECT;j++)    //选择NUM_SELECT个个体中最大的个体
    {
      rand_mem=rand()%POP_SIZE;  //随即个体
      if(max_fitness<population[rand_mem].fitness)
      {
        max_mem=rand_mem;
        max_fitness=population[rand_mem].fitness;
      }
    }

  newpopulation[i]=population[max_mem];
  }  
  
  //选择完毕,下面得到新的种群
  for(i=0;i<POP_SIZE;i++)
    population[i]=newpopulation[i];
}

void Crossover()                //浮点编码交叉
{
  int    pop;
  int    i;
  int    j;
  int    k;
  int    p1,p2;                //随即选择的两个交叉母体
  double  temp;                //中间存放量
  double  p;

  for(pop=0;pop<POP_SIZE;pop++)
  {
    p=GetRandVal(0,1);
    if(p<P_XOVER)
    {
      temp=GetRandVal(0,1);
      p1=rand()%POP_SIZE;
      p2=rand()%POP_SIZE;
      for(j=0;j<HiddenNum;j++)
      {
        for(i=0;i<InNum;i++)
        {
          if(rand()%2==0)
            population[pop].gene1[j][i]=population[p1].gene1[j][i]*temp+(1-temp)*population[p2].gene1[j][i]; //交叉
          else
            population[pop].gene1[j][i]=population[p1].gene1[j][i]*(1-temp)+temp*population[p2].gene1[j][i]; 
        }
      }
      for(k=0;k<OutNum;k++)
      {
        for(j=0;j<HiddenNum;j++)
        {
          if(rand()%2==0)
            population[pop].gene2[k][j]=population[p1].gene2[k][j]*temp+(1-temp)*population[p2].gene2[k][j]; //交叉
          else
            population[pop].gene2[k][j]=population[p1].gene2[k][j]*(1-temp)+temp*population[p2].gene2[k][j]; 
        }
      }

    }
  }
}

void Mutate()                  //变异,变异时肤随即数
{
  int    pop;
  int    i;
  int    j;
  int    k;
  double  p;

  for(pop=0;pop<POP_SIZE;pop++)
  {
    p=(double)(rand()%1000)/1000.0;
    if(p<P_MUTATE)
    {
      for(j=0;j<HiddenNum;j++)
      {
        for(i=0;i<InNum;i++)
        {
          population[pop].gene1[j][i]=GetRandVal(0,1);
        }
      }
      for(k=0;k<OutNum;k++)
      {
        for(j=0;j<HiddenNum;j++)
        {
          population[pop].gene2[k][j]=GetRandVal(0,1);
        }
      }
    }
  }
}

void KeepBestIndividual()    //记录当前为止最好适应度的个体
{
  int    pop;
  int    i;
  int    j;
  int    k;

  for(pop=0;pop<POP_SIZE;pop++)
  {
    if(population[pop].fitness>BestIndividual.fitness)
    {
      BestIndividual.fitness=population[pop].fitness;    //种群中最好的个体
      for(j=0;j<HiddenNum;j++)
      {
        for(i=0;i<InNum;i++)
        {
          BestIndividual.gene1[j][i]=population[pop].gene1[j][i];
        }
      }
      for(k=0;k<OutNum;k++)
      {
        for(j=0;j<InNum;j++)
        {
          BestIndividual.gene2[k][j]=population[pop].gene2[k][j];
        }
      }
    }
    if(population[pop].fitness<WorstIndividual.fitness)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -