unit1.cpp

来自「此程序采用K均值的方法对样本数据进行模式分类」· C++ 代码 · 共 302 行

CPP
302
字号
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void TForm1::InitClusters()
{
  /*ClusterMember[0][0]=0;
    ClusterMember[0][0]=50;
    ClusterMember[0][0]=100;
    for(int j=0;j<4;j++)
    {
      ClusterCenter[0][j]=Pattern[0][j];
      ClusterCenter[1][j]=Pattern[50][j];
      ClusterCenter[2][j]=Pattern[100][j];
     }  */

  int i,j;
  for(i=0;i<3;i++)
  {
    ClusterMember[i][0]=i;
    for(j=0;j<4;j++)
      ClusterCenter[i][j]=Pattern[i][j];
  }
}

  //欧式范数计算
double TForm1::EucNorm(int p,int c)
{
   double dist;
   int i;
   dist=0;
   for(i=0;i<4;i++)
       dist+=(Pattern[p][i]-ClusterCenter[c][i])*(Pattern[p][i]-ClusterCenter[c][i]);
   return dist;
}

  //求离样本最近的聚类中心
 int TForm1::FindClosestCluster(int pat)
{
   int i,ClustID;
   double MinDist,d;
   MinDist=9.9e+99;
   ClustID=-1;
   for(i=0;i<3;i++)
   {
     d=EucNorm(pat,i);
     if(d<MinDist)
     {
       MinDist=d;
       ClustID=i;
     }
   }
   return ClustID;
}

 //样本分类
 void TForm1::DistributeSamples()
 {
    int i,pat,Clustid,MemberIndex;
    for(i=0;i<3;i++)
    ClusterNumMembers[i]=0;
    for(pat=0;pat<150;pat++)
    {
      Clustid=FindClosestCluster(pat);
      MemberIndex=ClusterNumMembers[Clustid];
      ClusterMember[Clustid][MemberIndex]=pat;
      ClusterNumMembers[Clustid]++;
    }
  }

  //重新计算各分类中心
  int TForm1::CalcNewClustCenters()
  {
     int ConvFlag,PatternID,i,j,k;
     double Tmp[4];
     ConvFlag=1;
     for(i=0;i<3;i++)
     {
       for(j=0;j<4;j++)
         Tmp[j]=0.0;

       for(j=0;j<ClusterNumMembers[i];j++)
       {
         PatternID=ClusterMember[i][j];
         for(k=0;k<4;k++)
           Tmp[k]+=Pattern[PatternID][k];
        }

        for(j=0;j<4;j++)
        {
          Tmp[j]=Tmp[j]/ClusterNumMembers[i];
          if(Tmp[j]!=ClusterCenter[i][j])
          {
            ConvFlag=0;
            ClusterCenter[i][j]=Tmp[j];
          }
        }
     }
      return ConvFlag;
  }

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  SpeedButton2->Enabled=false;
  for(int i=0;i<150;i++)
      for(int j=0;j<4;j++)
         Pattern[i][j]=0;
  //设置载入文件初始目录
  String InitDir=GetCurrentDir();
  OpenDialog1->InitialDir=InitDir;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
  ListView1->Items->Clear();//列表框清空
  ListView2->Items->Clear();
  ListView3->Items->Clear();
  ListView4->Items->Clear();

  Label1->Caption="共计  0  个样本";
  Label2->Caption="共计  0  个样本";
  Label3->Caption="共计  0  个样本";

  StatusBar1->Panels->Items[0]->Text="分类迭代次数:0 次";

  int SampleSN=0;//模式样本序号
  //ListView1->Visible=false;
  int iFileHandle,iFileLength,iBytesRead;
  char *PatternBuffer;
  if(OpenDialog1->Execute())
  {
    try
    {
      iFileHandle=FileOpen(OpenDialog1->FileName,fmOpenRead);
      iFileLength=FileSeek(iFileHandle,0,2);
      FileSeek(iFileHandle,0,0);
      PatternBuffer=new char[iFileLength+1];
      iBytesRead=FileRead(iFileHandle,PatternBuffer,iFileLength);
      FileClose(iFileHandle);
      bool ReadFlag=false;  //数据加入与否标志
      AnsiString EData="";  //读入有效数据
      TListItem *p;
      int DataDim=0;  //样本的维
      for(int i=0;i<iBytesRead;i++)
      {
         if((PatternBuffer[i]>='0'&&PatternBuffer[i]<='9')||PatternBuffer[i]=='.')
            {ReadFlag=true;EData+=PatternBuffer[i];}
         else
            {
              if(ReadFlag)
                 {
                   if(DataDim==0)
                   {
                     p=ListView1->Items->Add();
                     p->Caption=EData;
                   }
                   else{
                        p->SubItems->Add(EData);
                        Pattern[SampleSN][DataDim-1]=atof(EData.c_str());
                        }
                   EData="";
                   ReadFlag=false;
                   DataDim++;
                   if(DataDim==5)
                   {
                     DataDim=0;
                     SampleSN++;
                   }
                   
                 }
            }
      }
      
  delete[] PatternBuffer;
    }
    catch(...)
    {
      Application->MessageBox("不能进行以下文件操作:打开、寻找、读取和关闭。", "File Error", IDOK);
    }
  }

  /* //用加权系数调整样本各维(特征)数据大小
 for(int j=0;j<150;j++)
 {
  Pattern[j][0]=Pattern[j][0]*1.0;
  Pattern[j][1]=Pattern[j][1]*1.0;
  Pattern[j][2]=Pattern[j][2]*10.0;
  Pattern[j][2]=Pattern[j][2]*10.0;
 }  */

/* //样本各维(特征)数据标准化
 double sum[4];
 for(int i=0;i<4;i++)
 {
   sum[i]=0.0;
   for(int j=0;j<150;j++)sum[i]+=Pattern[j][i];
   sum[i]=sum[i]/150.0;
   for(int k=0;k<150;k++)Pattern[k][i]=Pattern[k][i]/ sum[i];
 }  */


 ListView1->Visible=true;
 SpeedButton2->Enabled=true;        
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
{
  Screen->Cursor=crHourGlass;

  //清空上次分类结果
  ListView2->Items->Clear();
  ListView3->Items->Clear();
  ListView4->Items->Clear();

  InitClusters(); //初始化

  //K-Means方法计算
  int Converged; //收敛标志
  int IterNum;  //分类迭代次数
  IterNum=1;
  Converged=0;
  while(Converged==0)
  {
    IterNum++;
    StatusBar1->Panels->Items[0]->Text="分类迭代次数:"+IntToStr(IterNum)+"次";
    DistributeSamples();
    Converged=CalcNewClustCenters();
   }

  // 显示分类后各类样本数量
  Label1->Caption="共计"+IntToStr(ClusterNumMembers[0])+"个样本";
  Label2->Caption="共计"+IntToStr(ClusterNumMembers[1])+"个样本";
  Label3->Caption="共计"+IntToStr(ClusterNumMembers[2])+"个样本";

  //显示第一类中心
  TListItem *p;
  p=ListView2->Items->Add();
  p->Caption="中心";
  for(int k=0;k<4;k++)
    p->SubItems->Add(String(int(ClusterCenter[0][k]*10)/10.0));
  //显示第一类各样本数据
  for(int i=0;i<ClusterNumMembers[0];i++)
  {
   p=ListView2->Items->Add();
   p->Caption=String(ClusterMember[0][i]+1);
   for(int k=0;k<4;k++)
      p->SubItems->Add(String(Pattern[(ClusterMember[0][i])][k]));
   }

  // 显示第二类中心
  p=ListView3->Items->Add();
  p->Caption="中心";
  for(int k=0;k<4;k++)
    p->SubItems->Add(String(int(ClusterCenter[1][k]*10)/10.0));
  //  显示第二类各样本数据
  for(int i=0;i<ClusterNumMembers[1];i++)
  {
   p=ListView3->Items->Add();
   p->Caption=String(ClusterMember[1][i]+1);
   for(int k=0;k<4;k++)
      p->SubItems->Add(String(Pattern[(ClusterMember[1][i])][k]));
   }
  //显示第三类中心
  p=ListView4->Items->Add();
  p->Caption="中心";
  for(int k=0;k<4;k++)
    p->SubItems->Add(String(int(ClusterCenter[2][k]*10)/10.0));
  //显示第三类各样本数据
  for(int i=0;i<ClusterNumMembers[2];i++)
  {
   p=ListView4->Items->Add();
   p->Caption=String(ClusterMember[2][i]+1);
   for(int k=0;k<4;k++)
      p->SubItems->Add(String(Pattern[(ClusterMember[2][i])][k]));
   }
   Screen->Cursor=crDefault;        
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
{
  Close();         
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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