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

📄 somnet.cpp

📁 网上关于自组织映射som的代码一般都是解决极点平衡的
💻 CPP
字号:
#include "Somnet.h"
#include <fstream.h>
#include <iomanip.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


CSomnet::~CSomnet()
{
  int i ;
  for(i=0;i<layernumber;i++)
  {
  	delete *(inputMode+i);
  }
  delete []inputMode;
  for(i=0;i<OutputLayerColumn*OutputLayerRow;i++)
  {
  	delete weight[i];
  }
  delete []weight;
}


/****************************************************************/
//该函数初始化输入数组
/****************************************************************/
CSomnet::CSomnet(int layer,int nd)
{
	 current_iteration_num=0;
	 min_distance=Min_distance;
	 study_efficiency=efficiency;
	 neighbor_width=OutputLayerColumn;
   neighbor_height=OutputLayerRow;
	 winner_row=OutputLayerRow/2;
	 winner_column=OutputLayerColumn/2;
	 distance=0.0;
	
	int i;
	layernumber=layer;/*layernumber为共有多少个训练样本*/
	ndnumber=nd;/*nd为每一个向量元素的个数*/
	inputMode=new double*[layernumber];
	for(i=0;i<layernumber;i++)/*为每一层分配节点*/
	{
		*(inputMode+i)=new double[ndnumber];
	}

	weight=new double*[OutputLayerColumn*OutputLayerRow];
	for(i=0;i<OutputLayerRow*OutputLayerColumn;i++)
	{
		weight[i]=new double[ndnumber];
	}

}


/****************************************************************/
//该函数用于计算欧氏距离,并找到获胜神经元
/****************************************************************/
void CSomnet::eula_distance(int z)
{
	int i,j,n;
	int ttLow,ttUp,ppLow,ppUp;
	ttLow=winner_column-neighbor_width/2;
	ttUp=winner_column+neighbor_width/2;
	ppLow=winner_row-neighbor_height/2;
	ppUp=winner_row+neighbor_height/2;
	if(ttLow<0)
		ttLow=0;
	if(ttUp>=OutputLayerColumn)
		ttUp=OutputLayerColumn-1;
	if(ppLow<0)
		ppLow=0;
	if(ppUp>=OutputLayerRow)
		ppUp=OutputLayerRow-1;
	for( i=ppLow;i<=ppUp;i++)/*计算获胜节点周围节点距离*/
	for( j=ttLow;j<=ttUp;j++)
	{
		if(!(flag[i][j]==1))                       //用一个变化的外部变量控制循环的方法
		{  distance=0.0;
				for(n=0;n<ndnumber;n++) /*ndnumber为输入向量的元素个数*/
				distance+=
				pow((inputMode[z][n]-weight[i*OutputLayerColumn+j][n]),2);
			if(distance<min_distance)/*计算获胜节点周围的最小距离*/
			{
				min_distance=distance;
				temp_row=i;
				temp_column=j;
			}
		}
		
	}

	if(current_iteration_num>0)
	{
		if(min_distance<=error_limit)                     
		{
			flag[temp_row][temp_column]=1;
		}
	}	
}

/****************************************************************/
//调整权值
/****************************************************************/
void CSomnet::weight_change(int z)/*z表示向量z*/
{
	int i,j,n;
	int ttLow,ttUp,ppLow,ppUp;
	winner_row=temp_row;
	winner_column=temp_column;
	ttLow=winner_column-neighbor_width/2;
	ttUp=winner_column+neighbor_width/2;
	ppLow=winner_row-neighbor_height/2;
	ppUp=winner_row+neighbor_height/2;
	if(ttLow<0)
		ttLow=0;
	if(ttUp>=OutputLayerColumn)
		ttUp=OutputLayerColumn-1;
	if(ppLow<0)
		ppLow=0;
	if(ppUp>=OutputLayerRow)
		ppUp=OutputLayerRow-1;
	for(i=ppLow;i<=ppUp;i++)
	for(j=ttLow;j<=ttUp;j++)
	{
		if(!(flag[i][j]==1))
		{
			for(n=0;n<ndnumber;n++)
			weight[i*OutputLayerColumn+j][n]+=
				study_efficiency*(inputMode[z][n]-weight[i*OutputLayerColumn+j][n]);
		}
		
	}
	normalized_weight();
}

/****************************************************************/
//归一化输入向量
/****************************************************************/
void CSomnet::normalized_input()
{
	int i,j;
	double temp;
	for(i=0;i<layernumber;i++)
	{
		temp=0.0;
	  for(j=0;j<ndnumber;j++)
	  {
		  temp+=inputMode[i][j]*inputMode[i][j];
	  }
	  for(j=0;j<ndnumber;j++)
	  {
		  inputMode[i][j]/=sqrt(temp);
	  }
	}
}

/****************************************************************/
//归一化权值
/****************************************************************/
void CSomnet::normalized_weight()
{
	int i,j,k;
	double temp;
	for(i=0;i<OutputLayerRow;i++)
	{
		 for(j=0;j<OutputLayerColumn;j++)
	   {
		   temp=0.0;
	     for(k=0;k<ndnumber;k++)
		     temp+=weight[i*OutputLayerColumn+j][k]*weight[i*OutputLayerColumn+j][k];
		   for(k=0;k<ndnumber;k++)
	       weight[i*OutputLayerColumn+j][k]/=sqrt(temp);
	   }  
	 }
}
/****************************************************************/
//调整学习效率以及获胜节点的邻域大小
/****************************************************************/
void CSomnet::paraChange()
{
	
	study_efficiency=
		study_efficiency*(1.0-((double)current_iteration_num)/total_iteration_Num);
	neighbor_width=
		int(neighbor_width*(1.0-((double)current_iteration_num)/total_iteration_Num));
	neighbor_height=
		int(neighbor_height*(1.0-((double)current_iteration_num)/total_iteration_Num));
}
/*****************************************************************/
//该函数用于将所有输入模式从文件中读入,并存放到数组inputMode中;
//同时进行权值的初始化,采用随机赋值的方法;
/*****************************************************************/
void CSomnet::initialize()
{
	srand((unsigned)time(NULL));
	FILE *pinit_sample=fopen("相关数据\\输出数据\\init_sample.txt","w+");
	int i,j,k;
	for(i=0;i<OutputLayerRow;i++)
	for(j=0;j<OutputLayerColumn;j++)
		flag[i][j]=0;
		
	/*从文件中将所有输入模式读入,并存放到数组inputMode中*/
	FILE *pf=fopen("相关数据\\输入数据\\input.txt","a+");
	if(pf==NULL)
	{
		cout<<"Can not open input file!\n";
		exit(0);
	}
	
	for(i=0;i<layernumber;i++)/*layernumber是向量个数*/
	for(k=0;k<ndnumber;k++)/*ndnumber是一个向量的元素个数*/
	  fscanf(pf,"%lf",&inputMode[i][k]);
	normalized_input();
	
	/*用于测试是否能够正确读入输入模式*/	
	for(i=0;i<layernumber;i++)
	{
		fprintf(pinit_sample,"\n\n%d\n",i);
		for(k=0;k<ndnumber;k++)
		{
			if(k%5==0)
				fprintf(pinit_sample,"\n");
			fprintf(pinit_sample,"%f  ",inputMode[i][k]);		
		}
	}
	fclose(pinit_sample);

	/*权值初始化,采用随机赋值的方法*/
	for(i=0;i<OutputLayerRow;i++)
	for(j=0;j<OutputLayerColumn;j++)
	for(k=0;k<ndnumber;k++)
		weight[i*OutputLayerColumn+j][k]=(double(rand()%101))/100.0;
	normalized_weight();

/*用于测试是否能够正确初始化权值*/
FILE *pinit_weight=fopen("相关数据\\输出数据\\init_weight.txt","w+");

	for(i=0;i<OutputLayerRow;i++)
	for(j=0;j<OutputLayerColumn;j++)
		{
			fprintf(pinit_weight,"\n\nNode[%d][%d]",i+1,j+1);
			for(k=0;k<ndnumber;k++)/*ndnumber是输入向量的元素个数*/
			{
				if(k%5==0)
				  fprintf(pinit_weight,"\n");
				fprintf(pinit_weight,"%f   ",weight[i*OutputLayerColumn+j][k]);
			}
	
		}
		fclose(pinit_weight);
	fclose(pf);
}
/*****************************************************************/
//对网络进行训练
/*****************************************************************/

void  CSomnet::Treatnet()
{
	
	FILE *pw=fopen("相关数据\\输出数据\\wincode.txt","w+");
	FILE *pwinner_weight=fopen("相关数据\\输出数据\\winner_weight.txt","w+");
	int l,i,j,k;
	int *iteration_numbers=(int*)malloc(sizeof(int)*layernumber);
	int total_num=0;
	for(l=0;l<layernumber;l++)
	{
		iteration_numbers[l]=0; 
	}
	initialize();
	for(l=0;l<layernumber;l++)     
	{
		current_iteration_num=0;
		winner_row=OutputLayerRow/2;
		winner_column=OutputLayerColumn/2;
		while(current_iteration_num<total_iteration_Num)
		{
		  distance=0.0;
			eula_distance(l);
			
			if((current_iteration_num>0)&&(min_distance<=error_limit))
				{
				  fprintf(pw,"第%d个样本达到预定精度\n",l+1);
				  break;
				}
			weight_change(l);
			++current_iteration_num;
			paraChange();
		};
		
		fprintf(pw,"第%d个样本的获胜节点是:%d, %d\n\n",l+1,temp_row+1,temp_column+1);
			fprintf(pwinner_weight,"\n\n第%d个样本的获胜节点Node[%d][%d]的权值是:",l+1,temp_row+1,temp_column+1);
			for(k=0;k<ndnumber;k++)
			{
				if(k%5==0)
				{	
					fprintf(pwinner_weight,"\n");			
				}			
				fprintf(pwinner_weight,"%f   ",weight[temp_row*OutputLayerColumn+temp_column][k]);
			}
				
		iteration_numbers[l]=current_iteration_num+1;
		neighbor_width=OutputLayerColumn;
		neighbor_height=OutputLayerRow;
		study_efficiency=efficiency;
		min_distance=Min_distance;
	}
	
  FILE *pflag=fopen("相关数据\\输出数据\\flag.txt","w+");
  for(i=0;i<OutputLayerRow;i++)
	for(j=0;j<OutputLayerColumn;j++)
	{
		if(flag[i][j]==1)
		{
			fprintf(pflag,"\nNode[%d][%d]\n",i+1,j+1);
		}
		
	}
  fclose(pflag);
	for(l=0;l<layernumber;l++)
		total_num+=iteration_numbers[l];
		
	FILE *piteration_num=fopen("相关数据\\输出数据\\iteration_num.txt","w+");
	for(l=0;l<layernumber;l++)
	{
		fprintf(piteration_num,"第%d个样本迭代%d次\n",l,iteration_numbers[l]);
		if(l==(layernumber-1))
		fprintf(piteration_num,"整个训练过程共迭代%d次",total_num);
	}
	
	FILE *all_weight=fopen("相关数据\\输出数据\\all_weight.txt","w+");
	for(i=0;i<OutputLayerRow;i++)
	for(j=0;j<OutputLayerColumn;j++)
	{
		
		fprintf(all_weight,"\n\nNode[%d][%d]\n",i+1,j+1);
		for(k=0;k<ndnumber;k++)
		{
			if(k%5==0)
			{
				fprintf(all_weight,"\n");
			}	
			fprintf(all_weight,"%f   ",weight[i*OutputLayerColumn+j][k]);
		}
	}
	
	free (iteration_numbers);
	fclose(piteration_num);
	fclose(pwinner_weight);
	fclose(pw);
}

void CSomnet::initialaze_test(int test_layernum)
{
	int i,j,k,n	;	
	double temp,dis;
	double **test_input=new double*[test_layernum];
	for(i=0;i<test_layernum;i++)/*为每一层分配节点*/
	{
		*(test_input+i)=new double[ndnumber];
	}
	
	
	FILE *pt=fopen("相关数据\\输入数据\\test.txt","a+");
	if(pt==NULL)
	{
		cout<<"Can not open input file!\n";
		exit(0);
	}
	
	for(i=0;i<test_layernum;i++)/*layernumber是向量个数*/
	for(k=0;k<ndnumber;k++)/*ndnumber是一个向量的元素个数*/
	  fscanf(pt,"%lf",&test_input[i][k]);
	  
/*归一化测试样本*/
	for(i=0;i<test_layernum;i++)
	{
		temp=0.0;
	  for(j=0;j<ndnumber;j++)
	  {
		  temp+=test_input[i][j]*test_input[i][j];
	  }
	  for(j=0;j<ndnumber;j++)
	  {
		  test_input[i][j]/=sqrt(temp);
		 
	  }
	}
	
	/*计算最小距离和获胜节点*/
	FILE *ptestwincode=fopen("相关数据\\输出数据\\testwincode.txt","w+");
  dis=0.0;
	for(k=0;k<test_layernum;k++)
  { min_distance=Min_distance;
  	for( i=0;i<OutputLayerRow;i++)/*计算获胜节点周围节点距离*/
	  for( j=0;j<OutputLayerColumn;j++)
	  {	dis=0.0;	
		  for(n=0;n<ndnumber;n++) /*ndnumber为输入向量的元素个数*/
			 
			  dis+=pow((test_input[k][n]-weight[i*OutputLayerColumn+j][n]),2);
			  if(dis<min_distance)/*计算获胜节点周围的最小距离*/
			  {
				  min_distance=dis;
				  temp_row=i;
				  temp_column=j;
			  }	
	   }

	   fprintf(ptestwincode,"\n第%d个测试样本的获胜节点是Node[%d][%d]\n",k+1,temp_row+1,temp_column+1);	
	   
	}
	for(i=0;i<test_layernum;i++)
  {
  	delete *(test_input+i);
  }
  delete []test_input;
  fclose(ptestwincode);
}

⌨️ 快捷键说明

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