📄 ukohonennet.cpp
字号:
//---------------------------------------------------------------------------
#include "stdafx.h"
#pragma hdrstop
#include "UKohonenNet.h"
#include "GEO_RasterData.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
//---------------------------------------------------------------------------
//随机选取J,当J大于N时,返回N;
unsigned int Random(int N)
{
unsigned int j;
srand( (unsigned)time( NULL ) );
j= (N*rand())/RAND_MAX;
if ((int)j >= N) j=N;
return j;
}
//---------------------------------------------------------------------------
// 构造函数
// 功能描述:
//
// 初始参数:numPatterns 原始模式数
// sizeVector 每个模式的向量维数。
// **data 原始模式
// Shuffle 各个模式的数目混乱下标。
//---------------------------------------------------------------------------
TKNPattern::TKNPattern(CRasterData *pData)
{
NumPatterns = pData->GetHeight();
SizeVector = pData->GetWidth();
m_pRaster = pData;
Shuffle = new int[NumPatterns];
for (int i=0; i<NumPatterns; i++) Shuffle[i] = i;
}
//---------------------------------------------------------------------------
//功能描述:
//参数说明:
//---------------------------------------------------------------------------
TKNPattern::~TKNPattern(){
delete[] Shuffle;
}
//---------------------------------------------------------------------------
//功能描述:
// 向量归一化。
//参数说明:
// maxValue:归一化后的最大值
//----------------------------------------------------------------------------
int __fastcall TKNPattern::Norm(int maxValue)
{
int i,q;
double *mmin = new double[SizeVector];
double *mmax = new double[SizeVector];
for (q=0; q<SizeVector; q++)
{
mmin[q] = 10;
mmax[q] = 0;
for (i=0; i<NumPatterns; i++)
{
double temp=m_pRaster->GetDoublePixel(q,i);
if(temp < mmin[q])
mmin[q] = temp;
if (temp > mmax[q])
mmax[q] = temp;
}
for (i=0; i<NumPatterns; i++)
m_pRaster->SetPixel(q,i,(float)(maxValue*(m_pRaster->GetDoublePixel(q,i)-mmin[q])/(mmax[q]-mmin[q])- maxValue/2.0));
}
delete[] mmin;
delete[] mmax;
return 0;
}
//---------------------------------------------------------------------------
// 功能说明:
// 从文件获得模式;
// 参数说明:
// fname:存放模式的文件名;
//----------------------------------------------------------------------------
/*int TKNPattern::GetPatterns(char *fname) {
FILE *fp;
int i,j;
double x;
fp=fopen(fname,"r");
if (fp==NULL) return 0; // Test for failure.
fscanf(fp,"%d",&NumPatterns);
fscanf(fp,"%d",&SizeVector);
Shuffle = new int[NumPatterns];
P = new double*[NumPatterns];
for (i=0; i<NumPatterns; i++){
Shuffle[i] = i;
P[i] = new double[SizeVector];
}
for (i=0; i<NumPatterns; i++) { // For each vector
for (j=0; j<SizeVector; j++) { // create a pattern
fscanf(fp,"%lf",&x); // consisting of all elements
P[i][j]=x;
} //* endfor
} //* endfor
fclose(fp);
return 1;
}*/
//-------------------------------------------------------------------------
//功能说明:
// 获得随机模式;
//参数说明:
// n1:模式个数;
// n2:每个模式的向量个数;
//---------------------------------------------------------------------------
int TKNPattern::GetRandPats(int n1,int n2) {
int i,j;
double x;
NumPatterns=n1;
SizeVector=n2;
for (i=0; i<NumPatterns; i++) { // For each vector
for (j=0; j<SizeVector; j++) { // create a pattern
x=(double)rand()/RAND_MAX; // consisting of random elements
//P[i][j]=x; // between 0 and 1
m_pRaster->SetPixel(j,i,(float)x);
} /* endfor */
} /* endfor */
return 1;
}
//---------------------------------------------------------------------------
//功能说明:
// 重新排列Shuffle;
//参数说明:
// N:为Shuffle向量长度;
//---------------------------------------------------------------------------
void TKNPattern::ReShuffle(int N) {
int i,a1,a2,tmp;
for (i=0; i<N ;i++) {
a1=Random(NumPatterns);
a2=Random(NumPatterns);
tmp=Shuffle[a1];
Shuffle[a1]=Shuffle[a2];
Shuffle[a2]=tmp;
}
}
//----------------------------------------------------------------------------
//功能说明:
// 查询当前模式值
//参数说明:
// pat:当前查询模式个数;
// j: 当前查询模式向量维数;
//----------------------------------------------------------------------------
double TKNPattern::Query(int pat,int j)
{
//return P[pat][j];
return m_pRaster->GetDoublePixel(j,pat);
}
//----------------------------------------------------------------------------
//功能说明:
// 查询混乱后模式值
//参数说明;
// pat:模式个数;
// j: 当前查询模式向量维数。
double TKNPattern::QueryR(int pat,int j)
{
//return P[Shuffle[pat]][j];
return m_pRaster->GetDoublePixel(j,pat);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//功能说明:
// 构造函数;
//参数说明:
//
//----------------------------------------------------------------------------
KNET::KNET(){
StochFlg=0;
}
//----------------------------------------------------------------------------
//功能说明:
// 析构函数;
//参数说明:
//
//-----------------------------------------------------------------------------
KNET::~KNET(){
delete[] Label;
}
//-----------------------------------------------------------------------------
//功能说明:
// 设置模式;
//参数说明:
// p:输入模式。
//-----------------------------------------------------------------------------
void KNET::SetPattern(TKNPattern *p) {
m_pPattern=p;
YinSize=p->SizeVector;
Label = new unsigned char[p->NumPatterns];
}
//-----------------------------------------------------------------------------
//功能说明:
// 设置参数;权值参数初始化。
//参数说明:
// X:输出层接点个数,即分类个数;
// LR:learn rate;
//-----------------------------------------------------------------------------
void KNET::SetParms(int X, double LR){
int i,k;
YoutSize=X;
eta=LR;
delta_eta=0.005;
for (i=0; i<YoutSize; i++) {
for (k=0; k<YinSize; k++) {
W[k][i]= (double)rand()/(10.0 * (double)RAND_MAX);
} /* endfor */
} /* endfor */
}
//-------------------------------------------------------------------------------
//功能说明:
// 装载输入层;两种方式,一种是随机,一种非随机;
//参数说明:
// P:模式节点下标;
// StochFlg:当前节点的随机标识;
//--------------------------------------------------------------------------------
int KNET::LoadInLayer(int P){
int i;
for (i=0; i<YinSize; i++){
if (StochFlg){
Yin[i]=m_pPattern->QueryR(P,i);
}
else {
Yin[i]=m_pPattern->Query(P,i);
}
}
return 1;
}
//--------------------------------------------------------------------------
//功能说明:
// 自适应调节学习因子;
//参数说明:
// fid:存放学习因子的文件;
//---------------------------------------------------------------------------
void KNET::AdaptParms(FILE *fid){
eta=eta-delta_eta;
if (eta<ETAMIN)
eta=ETAMIN;
#ifndef DEBUG
fprintf(fid," New eta=%f\n",eta);
#endif
}
//----------------------------------------------------------------------
//功能说明:
// 打印权值矩阵;
//参数说明:
// fid:存放权值的文件名;
//-----------------------------------------------------------------------
void KNET::PrintWeights(FILE *fid) {
int i,k;
for (i=0; i<YoutSize; i++) {
for (k=0; k<YinSize; k++) {
fprintf(fid,"W[%d][%d]=%f ",k,i,W[k][i]);
} /* endfor */
fprintf(fid,"\n");
} /* endfor */
}
//--------------------------------------------------------------------------------
//功能说明:
// 训练网络权值,epoch为迭代次数,当竞争胜利,权值增加。
//参数说明:
//-------------------------------------------------------------------------------
void KNET::RunTrn(){
int i,np;
int Winner;
epoch=0;
np=m_pPattern->NumPatterns;
FILE *fid=NULL;
#ifndef DEBUG
if ((fid = fopen(".//FractalDimension.out","w")) == NULL)
return;
#endif
while (epoch<=MAXEPOCHS){
for (i=0; i<np; i++){
LoadInLayer(i);
Winner=FindWinner();
Train(Winner);
}
#ifndef DEBUG
if(50*(epoch/50)==epoch) {
fprintf(fid,"Epoch=%d\n",epoch);
PrintWeights(fid);
}
#endif
epoch++;
if (StochFlg)
m_pPattern->ReShuffle(np);
AdaptParms(fid);
}
#ifndef DEBUG
fclose(fid);
#endif
}
//------------------------------------------------------------------------------
//功能说明:
// 训练权值,胜利者权值变化。
//参数说明:
// Winner:对应类别数,说明此向量属于Winner定义域中的哪个。
//-------------------------------------------------------------------------------
void KNET::Train(int Winner){
int k;
for (k=0; k<YinSize; k++){
W[k][Winner]=W[k][Winner]+eta*(Yin[k]-W[k][Winner]);
} /*endfor*/
}
//------------------------------------------------------------------------
//功能说明:
// 找出胜利者,衡量标准是权值与输入向量的距离。
//-------------------------------------------------------------------------
int KNET::FindWinner(){
int i;
double d,best;
int Winner;
best=1.0e99;
Winner=-1;
for (i=0; i<YoutSize; i++){
d=EucNorm(i);
if (d<best) {
best=d;
Winner=i;
} // endif
} // endfor
return Winner;
}
//----------------------------------------------------------------------------
//距离函数
//----------------------------------------------------------------------------
double KNET::EucNorm(int x){ // Calc Euclidean norm of vector dif
int i;
double dist;
dist=0;
for (i=0; i< YinSize;i++){
dist += (W[i][x]-Yin[i]) * (W[i][x]-Yin[i]);
} /* endfor */
dist=sqrt(dist);
return dist;
}
//------------------------------------------------------------------
//功能说明:
// 完成聚类
//------------------------------------------------------------------
void KNET::Run()
{
for (int i=0; i<m_pPattern->NumPatterns; i++){
LoadInLayer(i);
Label[i] = FindWinner();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -