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

📄 rbf网络.cpp

📁 利用RBF进行时间序列的预测
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// RBF网络.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "math.h"
#include "stdlib.h"

#define EP    0.01		//中心变化量预设值
#define X_Num 6			//输入层神经元个数       
//#define I    51		//隐含层神经元个数
#define pp    0.85		//分割因子
#define Y_Num 1			//输出层神经元个数
#define T_Num 34		//样本组数
#define STUDY_SPEED 0.01	//学习速率
#define Max	  500		//计算中心时,最大迭代次数

int Ix,N_Max;
int No[T_Num];
int NC[T_Num];
double LL[T_Num];

double *w;		//输出层权值,包含阀值
double *t;		//聚类中心
double *t1;		//训练中前一次的聚类中心
double x[X_Num][T_Num];		//训练样本,即输入
double *G;		//隐含层输出矩阵,包含阀值系数1
double Y[T_Num][1];			//训练时的网络输出值
double g;		//方差——高斯因子

double xx[X_Num][1];		//预测时的输入向量
double *uu;					//预测时隐含层输出
double yy[1][1];			//预测输出值
double *GT,*GM,*GD;			//GT存放G的转置,GM存放(GT*G)及其逆阵,GD存放(GT*G)的逆阵与GT的乘积


//////////**********用到的矩阵运算子程序**********//////////
void multiply(double *A,double *B,double *M,int m,int k,int n)   //求两矩阵A(m行k列)和B(k行n列)相乘,结果为M(m行n列)
{
	int i,j,t;
	
	for(i=0;i<m;i++)               //M矩阵初始化为全0
	{
		for(j=0;j<n;j++)
			//			*(M+i*n+j) = 0.0;      //*******也可以这样表示*******
			M[i*n+j] = 0.0;        //*******这样表示较直观*******
	}
	
	for(i=0;i<m;i++)      
	{
		for(j=0;j<n;j++)
		{
			for(t=0;t<k;t++)
				M[i*n+j] = M[i*n+j]+A[i*k+t]*B[t*n+j];   //获得M中一个元素的算法
		}
	}
}
void transpose(double *A,double *B,int m,int n)     //求矩阵A(n行m列)的转秩,结果为B(m行n列)
{
	int i,j;
	for(i=0;i<m;i++)
	{
		for(j=0;j<n;j++)
			B[i*n+j] = A[j*m+i];       //获得B中一个元素的算法      
	}
}

int reverse(double *a,int n)       //全选主元高斯—约当(Gauss—Jordan)消去法求矩阵a的逆阵
{
	int *is,*js,i,j,k,l,u,v;
    double d,p;
    is=(int *)malloc(n*sizeof(int));
    js=(int *)malloc(n*sizeof(int));
    for (k=0; k<=n-1; k++)
	{ d=0.0;
	for (i=k; i<=n-1; i++)
        for (j=k; j<=n-1; j++)
		{ l=i*n+j; p=fabs(a[l]);
		if (p>d) { d=p; is[k]=i; js[k]=j;}
		}
        if (d+1.0==1.0)
		{ free(is); free(js); printf("err**not inv\n");
		return(0);
		}
        if (is[k]!=k)
			for (j=0; j<=n-1; j++)
            { u=k*n+j; v=is[k]*n+j;
			p=a[u]; a[u]=a[v]; a[v]=p;
            }
			if (js[k]!=k)
				for (i=0; i<=n-1; i++)
				{ u=i*n+k; v=i*n+js[k];
				p=a[u]; a[u]=a[v]; a[v]=p;
				}
				l=k*n+k;
				a[l]=1.0/a[l];
				for (j=0; j<=n-1; j++)
					if (j!=k)
					{ u=k*n+j; a[u]=a[u]*a[l];}
					for (i=0; i<=n-1; i++)
						if (i!=k)
							for (j=0; j<=n-1; j++)
								if (j!=k)
								{ u=i*n+j;
								a[u]=a[u]-a[i*n+k]*a[k*n+j];
								}
								for (i=0; i<=n-1; i++)
									if (i!=k)
									{ u=i*n+k; a[u]=-a[u]*a[l];}
	}
    for (k=n-1; k>=0; k--)
	{ if (js[k]!=k)
	for (j=0; j<=n-1; j++)
	{ u=k*n+j; v=js[k]*n+j;
	p=a[u]; a[u]=a[v]; a[v]=p;
	}
	if (is[k]!=k)
		for (i=0; i<=n-1; i++)
		{ u=i*n+k; v=i*n+is[k];
		p=a[u]; a[u]=a[v]; a[v]=p;
		}
	}
    free(is); free(js);
    return(1);
}


void compose(double *data,int *no,int n)		//快速排序法
{
	int i,j,x,t=0;
	double xx;
	double *data1;
	int *no1;
	data1=(double *)malloc(n*sizeof(double));
	no1=(int *)malloc(n*sizeof(int));
	
	for(i=0;i<n;i++)
		data1[i] = data[i];
	for(i=0;i<n;i++)
		no1[i] = no[i];
	
	for(j=0;j<n-1;j++)
	{
		for(i=t+1;i<n;i++)
		{
			if(data1[i]>data1[t])
			{	
				xx = data1[t];
				data1[t] = data1[i];
				data1[i] = xx;
				
				x = no1[t];
				no1[t] = no1[i];
				no1[i] = x;
			}		
		}
		t++;
	}
	
	for(i=0;i<n;i++)
	{
		data[i] = data1[n-i-1];
		no[i] = no1[n-i-1];
	}
	free(data1);
	free(no1);
}

//////////**********学习中心——K均值聚类算法**********//////////

double interval(double *A,double *B,int n)
{
	int i;
	double sum=0.0;
	
	for(i=0;i<n;i++)
		sum+=pow(fabs(A[i]-B[i]),2);
	
	return (sqrt(sum));		
}
////径向距离/////
int min_juli(int m,int *set_number)      //m为样本序号,*set_number返回输入向量所在的聚类
{   
	int k,jj=0;
	double  sum_max=1000.0;
	double  sum=0.0;
	for(jj=0;jj<Ix;jj++)
	{
		for (k=0;k<X_Num;k++)
			sum+=pow(fabs(x[k][m]-t[k*Ix+jj]),2);

		if(sum==0)                    //若样本即为所选的初始中心,则直接跳出
		{
			*set_number = jj;
			break;
		}			
		else
			if(sum<sum_max) 
			{
				*set_number = jj;
				sum_max = sum;
			}
			sum=0;
	}
    return (*set_number);
}


//////////////k均值算法//////////////////////
void k_means()
{
	int i,j;
	int set_number=0;               //聚类序号
	int set_member_number = 0;      //某一个聚类中输入向量序号
	double min_distance;          
	double sum;	
	double max_change=10.0;         //对应中心最大的变化量

	N_Max = 0;                 //迭代次数初始化为0	
	
////////******主循环******////////
	while (max_change>EP&&N_Max<Max)       //循环条件:中心误差未满足要求,并且未达到最大迭代次数(设为500)
	{  
		for(i=0;i<X_Num;i++)                     //聚类前先记录原来的中心
				for(j=0;j<Ix;j++)
					t1[i*Ix+j] = t[i*Ix+j];

		set_member_number = 0;                  //每次都是从第 0 组样本开始聚类
		while(set_member_number<T_Num)
		{
			min_juli(set_member_number,&set_number); //返回一个距离最小的聚类序号			
			
			for (i=0;i<X_Num;i++)                    //调整中心
				t[i*Ix+set_number]+=STUDY_SPEED*(x[i][set_member_number]-t[i*Ix+set_number]);
			
			set_member_number++;
		}

		sum = 0.0;
		min_distance=0.0;
		for(j=0;j<Ix;j++)           //计算中心的变化
		{
			for(i=0;i<X_Num;i++)
				sum+=pow(fabs(t[i*Ix+j]-t1[i*Ix+j]),2);
			if(sqrt(sum)>=min_distance) 
				min_distance = sqrt(sum);
			sum = 0.0;
		}
		max_change = min_distance;		//得到此次迭代中心的最大变化量
		
		N_Max++; 
	}

//////////主循环结束////////////	

}
//////////**********学习中心结束**********//////////

//////////**********确定方差**********//////////

void getError()
{
	int i,j,n;
	double dsum=0,dmax=0.0;
	
	for(n=0;n<Ix-1;n++)          //求所选中心之间的最大距离
		for(j=n+1;j<Ix;j++)
			for(i=0;i<X_Num;i++)
				dsum+=pow(fabs(t[i*Ix+n]-t[i*Ix+j]),2);
			if(dsum>dmax) 	
				dmax=dsum;

	dmax = sqrt(dmax);            
	g = dmax/sqrt(2*Ix);          //求方差——高斯因子
}

//////////**********学习权值——用伪逆的方法求解**********//////////

void wStudy()             
{
	int i,j,n;
	double q,sum=0;

	for (i=0;i<T_Num;i++)           //隐含层输出矩阵G初始化(全置1)
		for (j=0;j<Ix+1;j++)
			G[i*(Ix+1)+j] = 1.0;  
		
	for (j=0;j<Ix;j++)               //计算隐含层输出矩阵G
		for (i=0;i<T_Num;i++)
		{
			for (n=0;n<X_Num;n++)
				sum+=pow(fabs(x[n][i]-t[n*Ix+j]),2);
			q = sum/((-2.0)*g*g);
			G[i*(Ix+1)+j] = exp(q);
			sum = 0.0;
		}
////////********以下用伪逆的方法求解w[][]********////////
	transpose(G,GT,Ix+1,T_Num);
	multiply(GT,G,GM,Ix+1,T_Num,Ix+1);
	i = reverse(GM,Ix+1);
	multiply(GM,GT,GD,Ix+1,Ix+1,T_Num);
	multiply(GD,*Y,w,Ix+1,T_Num,1);

}

////////********预测输出值********////////

////****计算隐藏层输出——需要输入数据xx[X_Num][1]****////
void compute_uu()
{
	int i,j;
	double q,sum=0.0;

	for(i=0;i<=Ix;i++)
		uu[0*Ix+i] = 1.0;

	for(j=0;j<Ix;j++)
	{
		for(i=0;i<X_Num;i++)
			sum+=pow(fabs(xx[i][0]-t[i*Ix+j]),2);		
		q = sum/((-2.0)*g*g);
		uu[0*Ix+j] = exp(q);
		sum = 0.0;
	}
}

void ones(double *A,double *range,int m,int n)	//A为待归一化的矩阵(m行n列),range为矩阵每列上下限(2行n列)
{
	int i,j;
	
	for(j=0;j<n;j++)
	{
		for(i=0;i<m;i++)
			A[i*n+j] = (A[i*n+j]-range[n+j])/(range[j]-range[n+j]); 
	}
}

void main()
{
	int i,j,n,mm,jj=0,p=2;
	
	FILE *fp;
	char file[] = "0000.dat";

	if((fp=fopen(file,"a+"))==NULL)
	{
		printf("can not open this file!\n");
	}	

	double data[X_Num+T_Num];
	double XX[308][2]={{30.9,	28.5},
					{31.3,	28.6},
					{31.1,	27.8},
					{31.3,	29.1},
					{31.3,	28.1},
					{32.0,	29.5},
					{30.2,	28.3},
					{30.2,	29.0},
					{30.8,	28.6},
					{30.1,	28.6},
					{30.2,	28.6},
					{30.1,	28.6},
					{30.9,	28.6},
					{30.6,	29.1},
					{31.0,	29.3},
					{30.1,	29.1},
					{30.5,	28.9},
					{30.3,	28.7},
					{30.5,	28.8},
					{30.5,	28.8},
					{32.3,	27.0},
					{30.3,	25.2},
					{28.9,	25.1},
					{27.6,	25.2},
					{26.9,	25.2},
					{26.9,	24.8},
					{34.7,	35.7},
					{37.6,	38.0},
					{41.4,	40.9},
					{45.4,	46.9},
					{49.2,	49.5},
					{52.2,	52.6},
					{55.9,	55.9},
					{58.5,	59.6},
					{61.3,	61.9},
					{64.8,	65.8},
					{68.4,	67.4},
					{70.4,	70.1},
					{73.4,	74.6},
					{75.4,	76.2},
					{77.4,	79.5},
					{80.0,	79.8},
					{81.7,	82.5},
					{84.5,	84.9},
					{85.8,	86.8},
					{87.0,	90.0},
					{87.4,	86.6},
					{86.0,	84.5},
					{84.1,	83.7},
					{84.1,	82.7},
					{82.4,	81.8},
					{81.9,	79.1},
					{81.0,	78.3},
					{78.3,	79.3},

⌨️ 快捷键说明

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