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

📄 som.cpp

📁 人工神经网络基本模型:BP、ART、Hopfield、SOM
💻 CPP
字号:
// Som.cpp: implementation of the Som class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
//#include "ANN.h"
#include "Som.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

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

Som::Som()
{

}

Som::~Som()
{

}

Som::Som(int S, int N, int m, int **sampleBins, CString sampleWords[], double beta, int time ){
	this->S=S;
	this->N=N;
	this->m=m;
	this->M=m*m;
	//this->sampleBins=sampleBins;
	//this->sampleWords=sampleWords;
	this->beta=beta;
	this->beta0=beta;
	this->time=time;
	this->SetSamples(sampleBins,sampleWords);
	this->Study();////
}

Som::Som(int S, int N, int m, int **sampleBins, CString sampleWords  , double beta, int time ){
	this->S=S;
	this->N=N;
	this->m=m;
	this->M=m*m;
	//this->sampleBins=sampleBins;
	//this->sampleWords=sampleWords;
	this->beta=beta;
	this->beta0=beta;
	this->time=time;
	this->SetSamples(sampleBins,sampleWords);
	this->Study();

}

void Som::SetSamples(int **sampleBins, CString sampleWords[]){
	int i,j;
	this->sampleBins= (int**) calloc(S, sizeof(int*));
	this->sampleWords= (CString**) calloc(S, sizeof(CString*));
	for (i=0; i<S; i++) {
		this->sampleBins[i]=(int*) calloc(N, sizeof(int));
	}
	for(i=0; i<S; i++){
		for(j=0; j<N; j++){
			this->sampleBins[i][j]=sampleBins[i][j];
		}
		//this->sampleWords[i]=sampleWords[i];
		this->sampleWords[i]=new CString(sampleWords[i]);
	/*
	*/
	}
}

void Som::SetSamples(int **sampleBins, CString sampleWords){
	int i,j;
	this->sampleBins= (int**) calloc(S, sizeof(int*));
	this->sampleWords= (CString**) calloc(S, sizeof(CString*));
	for (i=0; i<S; i++) {
		this->sampleBins[i]=(int*) calloc(N, sizeof(int));
	}
	for(i=0; i<S; i++){
		for(j=0; j<N; j++){
			this->sampleBins[i][j]=sampleBins[i][j];
		}
	}

	int	begin,end;
	CString	sWord;
	sampleWords.TrimLeft();
	sampleWords.TrimRight();
	i=0;
	begin=0;
	while( (i<S)&& ( (end=sampleWords.Find(",",begin))!=-1 ) ){
		sWord="";
		for(j=begin; j<end; j++)
			sWord+=sampleWords[j];
		if(sWord=="")
			sWord=" ";
		//this->sampleWords[i]=sWord;
		this->sampleWords[i]=new CString(sWord);
		begin=end+1;
		i++;
	}
	for(j=i; j<S; j++){
		this->sampleWords[i]=new CString("?");
	}
}

void Som::Study(){
	/*****************************************************
	初始化连接权、学习率、邻域大小、总学习次数;
	给网络提供一个输入样本;
	计算输入样本与到输出层的连接权向量之间的距离;
	选择最小距离对应的输出层神经元为获胜神经元;
	调整到获胜神经元及其邻域内的神经元的连接权;
	给网络提供下一个输入样本,直至S个样本全部学习一遍;
	全部学习一遍之后,更新学习率、邻域大小学;
	进入下一轮学习,直至学习time回。
	*****************************************************/
	int	i,j;
	this->InitNet();
	for(i=0; i<time; i++){
		for(j=0; j<S; j++){
			this->CalDiatances(this->sampleBins[j]);
			this->SetGains(j);
			this->ChangeGainsWeight(this->sampleBins[j]);
		}
		this->beta=beta0*(1-i/(double)time);
		this->neighbor=(int)( neighbor0*(1-i/(double)time) );
	}
}

void Som::InitNet(){
	//初始化连接权、(学习率)、邻域大小、(总学习次数);
	srand(1253);//time(0)4711
	int i,j;
	this->weight= (double**) calloc(M, sizeof(double*)); //以竞争层神经元为发射点
	for (i=0; i<M; i++) {
		weight[i]=(double*) calloc(N, sizeof(double));
	}
	for(i=0; i<M; i++){
		for(j=0; j<N; j++){
			weight[i][j]=rand()/(double)RAND_MAX;
		}
	}
	this->neighbor0=(M/S>4)? M/S: 4;
	this->neighbor=neighbor0;
	this->distance= (double*) calloc(M, sizeof(double));
	this->output= (int*) calloc(M, sizeof(int));
	this->gains= (int*) calloc(neighbor0, sizeof(int));
	for(i=0; i<M; i++){
		output[i]=0;
	}


}

void Som::CalDiatances(int input[]){
	int j,i;
	for(j=0; j<M; j++){
		distance[j]=0;
		for(i=0; i<N; i++){
			distance[j]+=( (input[i]-weight[j][i])*(input[i]-weight[j][i]) );	
		}
		distance[j]=sqrt(distance[j]);
	}
}

void Som::SetGains(int sample){
	int i,j,n;
	int	r,n0;
	int g,gNeighbor;
	int	x,y;
	
	//获取获胜神经元
	g=0;
	for(j=1; j<M; j++){
		if(this->distance[j]<distance[g])
			g=j;
	}

	int	gI=rand()%M;
	for(j=0; j<M; j++){
		if(this->distance[j]=distance[g] && ( abs(j-gI)<abs(g-gI) ))
			g=j;
	}
	//获取获胜神经元邻域内的神经元
	gains[0]=g;
	output[g]=sample;
	n=1; r=1; y=g/m; x=g%m;
	while(n<this->neighbor){
		n0=n;
		for(i=-r; i<r; i++){
			gNeighbor=(y-r)*m+(x+i);
			if( gNeighbor>=0 && gNeighbor<M ){
				gains[n++]=gNeighbor;
				output[gNeighbor]=sample;
			}
			if( n>=neighbor )
				return;
		}
		for(j=-r; j<r; j++){
			gNeighbor=(y+j)*m+(x+r);
			if( gNeighbor>=0 && gNeighbor<M ){
				gains[n++]=gNeighbor;
				output[gNeighbor]=sample;
			}
			if( n>=neighbor )
				return;
		}
		for(i=r; i>-r; i--){
			gNeighbor=(y+r)*m+(x+i);
			if( gNeighbor>=0 && gNeighbor<M ){
				gains[n++]=gNeighbor;
				output[gNeighbor]=sample;
			}
			if( n>=neighbor )
				return;
		}
		for(j=r; j>-r; j--){
			gNeighbor=(y+j)*m+(x-r);
			if( gNeighbor>=0 && gNeighbor<M ){
				gains[n++]=gNeighbor;
				output[gNeighbor]=sample;
			}
			if( n>=neighbor )
				return;
		}
		if(n==n0)
			break;
		r++;

	}
	for(j=n; j<neighbor; j++){
		gains[j++]=-1;
	}
}

void Som::ChangeGainsWeight(int input[]){
	int i,j;
	for(j=0; j<neighbor; j++){
		if (gains[j]<0)
			break;
		for(i=0; i<N; i++){
			weight[ gains[j] ][i]=
			weight[ gains[j] ][i]+beta*(input[i]-weight[ gains[j] ][i]);
		}
	}
}

void Som::GetSample(int sampleNum, int sampleBin[]){
	int i;
	for(i=0; i<N; i++){
		sampleBin[i]=this->sampleBins[sampleNum][i];
	}
}

void Som::WeightsToFile(CString fileName){
	int i,j;
	CString	s,sWeight="Som网络的连接权:\n";
	for(i=0; i<M; i++){
		for(j=0; j<N; j++){
			s.Format("%f\t",weight[i][j]);
			sWeight+=s;
		}
		sWeight+="\n";
	}

	CStdioFile out;
	out.Open(fileName, CFile::modeCreate | CFile::modeWrite);
	out.WriteString(sWeight);
	out.Close();
}

void Som::GainsToFile(CString fileName){
	int i,j;
	CString	s,
	sGain="Som网络的获胜神经元对应的记忆模式:\n";
	for(i=0; i<M; i++){
		s.Format("%6d\t",output[i]);
		sGain+=s;
		if(i%m==(m-1))
			sGain+="\n";
	}

	CStdioFile out;
	out.Open(fileName, CFile::modeCreate | CFile::modeWrite);
	out.WriteString(sGain);
	out.Close();
}

int Som::GetOutput(int input[]){
	CalDiatances(input);
	int j;
	int g;
	
	//获取获胜神经元
	g=0;
	for(j=1; j<M; j++){
		if(this->distance[j]<distance[g])
			g=j;
	}

	return g;
}

void Som::GetResult(int g, int Bin[]){
	int i;
	for(i=0; i<N; i++){
		Bin[i]=this->sampleBins[ output[g] ][i];
	}
}

CString	Som::GetOutputWord(int input[]){
	CalDiatances(input);
	int j;
	int g;
	
	//获取获胜神经元
	g=0;
	for(j=1; j<M; j++){
		if(this->distance[j]<distance[g])
			g=j;
	}
	return *sampleWords[ output[g] ];
}

⌨️ 快捷键说明

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