📄 采用ga优化的bp神经网络程序.txt
字号:
/*************************************************
程序名: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 + -