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