📄 somnet.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 + -