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

📄 somsucess.c

📁 欢迎大家学习指正
💻 C
字号:
#include	"stdio.h"
#include	"stdlib.h"
#include	"time.h"
#include	"math.h"
#include	"engine.h"
#include	<string.h>

#define	INPUT_NEURON	2
#define	OUTPUT_COL	5
#define	OUTPUT_ROW	5
#define	STUDY_RATE_START	0.2  //学习速率初值,一般选较大数,0.2为典型值
#define	STUDY_RATE_LAST	0.005     //学习速率最终值,一般在0.001~0.01之间选取一般
#define	STUDY_NUMBER	4000      //学习次数,一般在500~10000之间选取
#define	NEIGHBOR_START	8         //临域半径初值,一般应将整个网络所含神经元全部包括其中

double	WEIGHT[OUTPUT_ROW*OUTPUT_COL][INPUT_NEURON];//存储权值
double	DISTANCE[OUTPUT_ROW*OUTPUT_COL];            //存储距离 
double	STUDY_RATE;                                 //学习速率
double	NEIGHBOR_RADIUS;                            //临域半径

/******************************************************************************************
产生随机数
******************************************************************************************/
void InitializeRandoms()
{
  srand(2559);//设置种子
}      


float RandomEqualREAL(float Low, float High)
{
  return (((float) rand())* (High-Low) / RAND_MAX  + Low);//产生Low到High之间的数
}

/******************************************************************************************
更新学习速率   k代表学习速率已更新次数
******************************************************************************************/

void	updata_study_rate(int k)
{
	STUDY_RATE=(STUDY_RATE_START-STUDY_RATE)*(1-(float) k/STUDY_NUMBER)+STUDY_RATE_LAST;
}

/******************************************************************************************
更新临域     k代表此次临域半径更新为第k次
             由于按照教材中理想的公式临域范围最后无法缩小到1(1后有小数点若干位),
			 所以在计算临域半径时,做四舍五入处理
******************************************************************************************/
int	updata_neighbor(int k)
{
	NEIGHBOR_RADIUS=sqrt(2)*(OUTPUT_ROW-1)+(1-sqrt(2)*(OUTPUT_ROW-1))*k/STUDY_NUMBER;
	
	if(NEIGHBOR_RADIUS-floor(NEIGHBOR_RADIUS)>=0.5)
		NEIGHBOR_RADIUS=ceil(NEIGHBOR_RADIUS); 
	else
		NEIGHBOR_RADIUS=floor(NEIGHBOR_RADIUS);

	return (NEIGHBOR_RADIUS);

}


/******************************************************************************************
初始化权值  根据教材,为了保证SOM有好的收敛性,一般将WEIGHT赋予同一数值
******************************************************************************************/

void	init_weight()
{
	int	counter1,counter2;
	for(counter1=0;counter1<INPUT_NEURON;counter1++)
		for(counter2=0;counter2<OUTPUT_ROW*OUTPUT_COL;counter2++)
		{
			WEIGHT[counter2][counter1]=0.01;
		}
}

/******************************************************************************************
计算权值与输入之间距离     
******************************************************************************************/
void	compute_distance(float *p_in)
{
	int	counter,counter1;
	
	for(counter=0;counter<OUTPUT_ROW*OUTPUT_COL;counter++)
	{
		DISTANCE[counter]=0;
		for(counter1=0;counter1<INPUT_NEURON;counter1++)
		{
			DISTANCE[counter]=DISTANCE[counter]+(*(p_in+counter1)-WEIGHT[counter][counter1]) * (*(p_in+counter1)-WEIGHT[counter][counter1]);
		}
	}
}
/************************************************************************************************
计算获胜者
************************************************************************************************/
int		compute_winner()
{
	int position;
	int counter;
	double	temp;
	position=0;
	temp=DISTANCE[0];
	for(counter=0;counter<OUTPUT_ROW*OUTPUT_COL;counter++)
	{
		if(temp>DISTANCE[counter])
		{
			temp=DISTANCE[counter];
			position=counter;
		}
	}
	return	(position);
}	





main()
{
	int	counter,counter1,counter2,counter3;//一般用计数器
	FILE	*p_data;                       //指向数据文件
	float	input_vector[INPUT_NEURON];    //输入向量
	int		winner;                        //获胜者编号
	double	temp_weight_x[OUTPUT_COL*OUTPUT_ROW];//暂存weight的x坐标
	double	temp_weight_y[OUTPUT_COL*OUTPUT_ROW];//暂存weight的y坐标
	
	
	Engine	*ep;                          //调用MATLAT引擎
	mxArray	*weight_x=NULL,*weight_y=NULL;//所需变量

	
	init_weight();                        //初始化网络
	STUDY_RATE=STUDY_RATE_START;          //   
	NEIGHBOR_RADIUS=NEIGHBOR_START;       // 
	
	p_data=fopen("input space.dat","rb"); //从已建立好的文件中获取输入向量
	fseek(p_data,0,SEEK_SET);             // 
	
	for(counter=0;counter<STUDY_NUMBER;counter++)
	{
		fread(input_vector,1,sizeof(float),p_data);
		fread(input_vector+1,1,sizeof(float),p_data);//从输入空间中去一输入向量
		
		compute_distance(input_vector);		
		winner=compute_winner();
		updata_neighbor(counter);
		updata_study_rate(counter);

			for(counter1=0;counter1<OUTPUT_COL;counter1++)
				for (counter2=0;counter2<OUTPUT_ROW;counter2++)
				{

					if(  (  (counter2-winner/OUTPUT_COL) * (counter2-winner/OUTPUT_COL) + (counter1-winner%OUTPUT_COL) * (counter1-winner%OUTPUT_COL)  )<NEIGHBOR_RADIUS*NEIGHBOR_RADIUS )
					for(counter3=0;counter3<INPUT_NEURON;counter3++)	
						WEIGHT[OUTPUT_ROW*counter2+counter1][counter3]=WEIGHT[OUTPUT_ROW*counter2+counter1][counter3]+STUDY_RATE*(input_vector[counter3]-WEIGHT[OUTPUT_ROW*counter2+counter1][counter3]);
				}
				

			

	}

	fclose(p_data);



/***************************************************************************************
调用matlab引擎作图
******************************************************************************************/

ep = engOpen(NULL);	//启动matlab engine

weight_x = mxCreateDoubleMatrix(1, OUTPUT_ROW*OUTPUT_COL, mxREAL);
weight_y = mxCreateDoubleMatrix(1, OUTPUT_ROW*OUTPUT_COL, mxREAL);

for(counter=0;counter<OUTPUT_ROW*OUTPUT_COL;counter++)
	for(counter1=0;counter1<INPUT_NEURON;counter1++)
	{
		if(counter1==0)
			temp_weight_x[counter]=WEIGHT[counter][counter1];
		else
			temp_weight_y[counter]=WEIGHT[counter][counter1];
	}

memcpy((double *) mxGetPr(weight_x),temp_weight_x,OUTPUT_ROW*OUTPUT_COL*sizeof(double));
memcpy((double *) mxGetPr(weight_y),temp_weight_y,OUTPUT_ROW*OUTPUT_COL*sizeof(double));


engPutVariable(ep, "weight_x", weight_x);
engPutVariable(ep, "weight_y", weight_y);

engEvalString(ep, "plot(weight_x,weight_y,'+r');");

printf("done!\n");

mxDestroyArray(weight_x);
mxDestroyArray(weight_y);


	

}

⌨️ 快捷键说明

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