?? cluster.cpp
字號:
GetFeature();
int distype;//距離的形式(歐氏、余弦...)
int times;//max loop number
int i,j;
DlgInfor mDlgInfor;
mDlgInfor.ShowInfor(4);
if (mDlgInfor.DoModal()==IDOK)
{
distype=mDlgInfor.m_DisType;
times=mDlgInfor.m_Times;
centernum=mDlgInfor.m_CenterNum;
}
else return;
BOOL change=true;//退出標志,false時表示樣品所屬類別不再變化,中止計算
int counter=0;//記錄當前已經循環的次數
double distance;//到各中心的距離
distance=MAX;
m_center=new Center[centernum];
for ( i=0;i<patternnum;i++)
m_pattern[i].distance=MAX;
for ( i=0;i<centernum;i++)//初始化,前centernum個模版各自分為一類
{
m_pattern[i].category=i+1;
m_pattern[i].distance=0;
for ( j=0;j<N*N;j++)
m_center[i].feature[j]=m_pattern[i].feature[j];
m_center[i].index=i+1;
}
while (change && counter<times)
{
counter++;
change=false;
for( i=0;i<patternnum;i++)//對所有樣品重新歸類
{
//計算第i個模式到各個聚類中心的最小距離,
int index=1;
distance=MAX;
for (int j=0;j<centernum;j++)
if (distance>GetDistance(m_pattern[i],m_center[j],distype))
{
distance=GetDistance(m_pattern[i],m_center[j],distype);
index=j;//找到最小距離,是到第index個聚類中心的距離
}
//比較原中心號與新中心號
//相同:更新距離。
//不同:1,新距離小,則歸入新中心,更新距離,重新計算前后兩個聚類中心模式
//2,新距離大于原距離,不處理;
//counter++
if (m_pattern[i].category==m_center[index].index)//屬于原類
{
m_pattern[i].distance=distance;
}
else//不屬于原類
{
int tpcenter=m_pattern[i].category;//記錄原類號
m_pattern[i].category=m_center[index].index;//歸入新類
m_pattern[i].distance=distance;
if(tpcenter!=0)
{
for (int k=0;k<centernum;k++)
if (m_center[k].index==tpcenter)
CalCenter(&m_center[k]);//計算原屬類中心
}
CalCenter(&m_center[index]);//計算新屬類中心
change=true;
}
}
}//end of while
delete []m_center;
}
/************************************************************
*函數名稱 ISODATA()
*參數 void
*返回值 void
*函數功能 用ISODATA方法對全體樣品進行分類
************************************************************/
void CCluster::ISODATA()
{
GetFeature();
int i,j;
int distype;
int times;//迭代的最多次數,用戶輸入
int precenternum;//當前類數
double T;//兩類中心的最小距離,小于該閾值將合并
double equation;//類內方差閾值
double *avedistance;//avedistance[i]:第i+1類內平均距離,i=0,1,...,centernum.
double allavedis;//全部模式樣本中心平均距離
double minous,maxous,mincos,maxcos,minbcos,maxbcos,mintan,maxtan;
minous=MAX; mincos=MAX; minbcos=MAX; mintan=MAX;
maxous=0; maxcos=0; maxbcos=0; maxtan=0;
//計算四種距離模式的參考值
for ( i=0;i<patternnum-1;i++)
for ( j=i+1;j<patternnum;j++)
{
if (minous>GetDistance(m_pattern[i],m_pattern[j],1))
minous=GetDistance(m_pattern[i],m_pattern[j],1);
if (maxous<GetDistance(m_pattern[i],m_pattern[j],1))
maxous=GetDistance(m_pattern[i],m_pattern[j],1);
if (mincos>GetDistance(m_pattern[i],m_pattern[j],2))
mincos=GetDistance(m_pattern[i],m_pattern[j],2);
if (maxcos<GetDistance(m_pattern[i],m_pattern[j],2))
maxcos=GetDistance(m_pattern[i],m_pattern[j],2);
if (minbcos>GetDistance(m_pattern[i],m_pattern[j],3))
minbcos=GetDistance(m_pattern[i],m_pattern[j],3);
if (maxbcos<GetDistance(m_pattern[i],m_pattern[j],3))
maxbcos=GetDistance(m_pattern[i],m_pattern[j],3);
if (mintan>GetDistance(m_pattern[i],m_pattern[j],4))
mintan=GetDistance(m_pattern[i],m_pattern[j],4);
if (maxtan<GetDistance(m_pattern[i],m_pattern[j],4))
maxtan=GetDistance(m_pattern[i],m_pattern[j],4);
}
//求所有樣品總方差
double cen[N*N],equ[N*N];
for (i=0; i<N*N; i++)
{
cen[i]=0;
equ[i]=0;
}
for (i=0;i<patternnum;i++)//所有樣品特征累加
for (j=0;j<N*N;j++)
cen[j]+=m_pattern[i].feature[j];
for (i=0;i<N*N;i++)//求所有樣品特征均值
cen[i]=cen[i]/(double)patternnum;
for (i=0;i<patternnum;i++)//總方差
for (j=0;j<N*N;j++)
equ[j]+=(m_pattern[i].feature[j]-cen[j])*(m_pattern[i].feature[j]-cen[j]);
for (i=0;i<N*N;i++)//均方差
equ[i]=sqrt(equ[i]/(double)patternnum);
double minequ=MAX;
double maxequ=0.0;
//求均方差中的最大最小值
for (i=0;i<N*N;i++)
{
if (minequ>equ[i])
minequ=equ[i];
if (maxequ<equ[i])
maxequ=equ[i];
}
DlgInfor mDlgInfor;
//輸出到對話框
mDlgInfor.ShowInfor(minous,maxous,mincos,maxcos,minbcos,maxbcos,mintan,maxtan,minequ,maxequ);//OUTPUT EQUATIONOUT!!!
if (mDlgInfor.DoModal()==IDOK)
{
distype=mDlgInfor.m_DisType;
T=mDlgInfor.m_T;
times=mDlgInfor.m_Times;
equation=mDlgInfor.m_EquationIn;
centernum=mDlgInfor.m_CenterNum;
}
else return;
//所有樣品各歸一類
precenternum=centernum;
m_center=new Center[precenternum];
for ( i=0;i<precenternum;i++)
{
m_pattern[i].category=i+1;
for (j=0;j<N*N;j++)
m_center[i].feature[j]=m_pattern[i].feature[j];
m_center[i].index=i+1;
m_center[i].patternnum=1;
}
int counter=0;//循環次數
avedistance=new double[precenternum];
while (++counter<times)
{
for ( i=0;i<patternnum;i++)//把所有樣品重新歸類
{
double td=MAX;
int index=0;
for (int j=0;j<precenternum;j++)
if (td>GetDistance(m_pattern[i],m_center[j],distype))
{
td=GetDistance(m_pattern[i],m_center[j],distype);
index=j;
}
m_pattern[i].category=m_center[index].index;
}
//修正各中心
for (i=0;i<precenternum;i++)
CalCenter(&m_center[i]);
for (i=0; i<precenternum;i++)
{
if (m_center[i].patternnum==0)
{
for(j=i; j<precenternum-1; j++)
m_center[j]=m_center[j+1];
precenternum--;
}
}
//計算各類距中心平均距離
for (i=0;i<centernum;i++)
avedistance[i]=0.0;//初始化
allavedis=0; //全部樣本平均距離
for (i=0;i<precenternum;i++)
{
int num=0;//類中成員個數
double dis;
dis=0.0;
for ( j=0;j<patternnum;j++)
{
if (m_pattern[j].category==i+1)
{
++num;
dis+=GetDistance(m_pattern[j],m_pattern[i],distype);
}
}
allavedis+=dis;
avedistance[i]=(double)(dis/(double)num);
}
allavedis/=patternnum;
if ((precenternum>=2*centernum) || ((counter%2)==0) && (precenternum>(int)(centernum/2+0.5)))//合并
{
//找到距離最近的兩個類
double td=MAX;
int ti,tj;
for( i=0;i<precenternum;i++)
for ( j=i+1;j<precenternum;j++)
{
double tdin;
tdin=GetDistance(m_center[i],m_center[j],distype);
if (td<tdin)
{
td=tdin;
ti=i;
tj=j;
}
}
//判斷是否要合并
if(td<T)//合并
{
for ( i=0;i<patternnum;i++)
{
if (m_pattern[i].category==m_center[tj].index)
m_pattern[i].category=m_center[ti].index;
if (m_pattern[i].category>m_center[tj].index)
m_pattern[i].category--;
}
CalCenter(&m_center[ti]);
for (i=tj;i<precenternum-1;i++)
{
m_center[i]=m_center[i+1];
m_center[i].index--;
}
precenternum--;
}
}//end 合并
else//分裂
{
double **mequation;//標準差
int ti,tj;//記錄最大標準差出現位置,第ti+1號類的第tj+1位。ti=0,1,...,precenternum-1.
mequation= new double *[precenternum];
for (i=0;i<precenternum;i++)
{
mequation[i]=new double[N*N];
mequation[i][j]=0.0;
}
//計算標準差
for ( i=0;i<precenternum;i++)
{
for ( j=0;j<patternnum;j++)
if (m_pattern[j].category==m_center[i].index)
{
for (int k=0;k<N*N;k++)
mequation[i][k]+=(m_pattern[j].feature[k]-m_center[i].feature[k])*(m_pattern[j].feature[k]-m_center[i].feature[k]);
}
for (int k=0;k<N*N;k++)
mequation[i][k]=sqrt(mequation[i][k]/m_center[i].patternnum);
}
//找最大標準差
ti=0;
tj=0;
for (i=0;i<precenternum;i++)
for ( j=0;j<N*N;j++)
if(mequation[i][j]>mequation[ti][tj])
{
ti=i;tj=j;
};
//判斷是否要分裂
if (mequation[ti][tj]>equation)//大于給定閾值
{
if (avedistance[ti]>allavedis )
//類平均距離大于總平均距離 分裂
{
precenternum++;
Center *tempcenter;
tempcenter=new Center [precenternum];
for (i=0;i<precenternum-1;i++)
tempcenter[i]=m_center[i];
tempcenter[precenternum-1].index=precenternum;
for (j=0;j<N*N;j++)
tempcenter[precenternum-1].feature[j]=m_center[ti].feature[j];
tempcenter[precenternum-1].feature[tj]-=0.5*mequation[ti][tj];
tempcenter[ti].feature[tj]+=0.5*mequation[ti][tj];
delete []m_center;
m_center=tempcenter;
}
}
delete []mequation;
}//end 分裂
}//end while(1)*/
delete []avedistance;
delete []m_center;
}
/************************************************************
*函數名稱 Mohujulei()
*參數 void
*返回值 void
*函數功能 用模糊聚類方法對全體樣品進行分類
************************************************************/
void CCluster::FuzzyCluster()
{
GetFeature();//獲得所有樣品特征
double *dis, *tempdis;
double dismax;
int i,j;
int distype;
dismax=0;
dis=new double [patternnum*patternnum];//模糊系數矩陣
tempdis=new double [patternnum*patternnum];
DlgFuzzyDistance dfd;
if (dfd.DoModal()==IDOK)
{
distype=dfd.mfuzzydistance;
}
else
return;
//得到初始模糊距離
for ( i=0; i<patternnum; i++)
for (j=0; j<patternnum; j++)
{
dis[i*patternnum+j]=GetFuzzyDistance(m_pattern[i],m_pattern[j],distype);//distype
}
//構造等價類
bool flag;
flag=true;
while (flag)
{
flag=false;
for ( i=0; i<patternnum; i++)
for ( j=0; j<patternnum; j++)
if (i==j)//對角線為1
tempdis[i*patternnum+j]=1;
else
tempdis[i*patternnum+j]=GetDistance(dis,i,j);
for ( i=0; i<patternnum; i++)
{
for ( j=0; j<patternnum; j++)
if ((tempdis[i*patternnum+j]-dis[i*patternnum+j])*(tempdis[i*patternnum+j]-dis[i*patternnum+j])>0.000001)//(tdis[i][j]!=dis[i][j])
{
flag=true;
break;
}
if (flag)
break;
}
for ( i=0; i<patternnum*patternnum; i++)
dis[i]=tempdis[i];
}
//輸出模糊矩陣
CString ts,sout;
//第一行標號1,2,。。。,patternnum。
sout.Insert(sout.GetLength()," \t");
for (i=1; i<=patternnum; i++)
{
ts.Format("%d \t",i);
sout.Insert(sout.GetLength(),ts);
}
sout.Insert(sout.GetLength(),"\n\n");
for (i=0; i<patternnum; i++)
{
//每列開頭標號
ts.Format("%d \t",i+1);
sout.Insert(sout.GetLength(),ts);
//輸出模糊系數矩陣
for(j=0; j<patternnum; j++)
{
ts.Format("%0.3f\t",dis[i*patternnum+j]);
sout.Insert(sout.GetLength(),ts);
if ((j+1)%patternnum==0)
sout.Insert(sout.GetLength(),"\n\n\n");
}
}
MessageBox(NULL,sout,"模糊矩陣",MB_OK);
delete []tempdis;
double *xishu=new double [patternnum*patternnum];
for(i=0; i<patternnum*patternnum; i++)
xishu[i]=-1;
int pointer=0;
//記錄模糊系數矩陣中不同的系數
for ( i=0; i<patternnum; i++)
for ( j=i; j<patternnum; j++)
{
bool done=false;
for (int k=0; k<pointer; k++)
{
if ((xishu[k]-dis[i*patternnum+j])*(xishu[k]-dis[i*patternnum+j])<0.000001)
{
done=true;
break;
}
}
if (!done)
{
xishu[pointer]=dis[i*patternnum+j];
pointer++;
}
}
for(i=0; i<pointer-1; i++)//對閾值由小到大排序
for (j=0; j<pointer-i-1; j++)
{
if (xishu[j]>xishu[j+1])
{
double temp=xishu[j];
xishu[j]=xishu[j+1];
xishu[j+1]=temp;
}
}
CString s,str;
for (i=0; i<pointer; i++)
{
s.Format("%0.4f ",xishu[i]);
str.Insert(str.GetLength(),s);
}
delete []xishu;
//用戶輸入聚類閾值
double yz;
DlgMohu mohu;
mohu.m_Mohuxishu=str;
if (mohu.DoModal()==IDOK)
{
yz=mohu.m_Mohuyuzhi;
}
else return;
int *result;
//根據閾值輸出聚類結果
result=new int [patternnum*patternnum];
for (i=0; i<patternnum*patternnum; i++)
if (dis[i]>=yz)
result[i]=1;
else
result[i]=0;
//分類后輸出
//第一行標號
sout="";
sout.Insert(-1,"每行中\"1\"對應的列為同一類");
sout.Insert(sout.GetLength(),"\n\n");
sout.Insert(sout.GetLength()," \t");
for (i=1; i<=patternnum; i++)
{
ts.Format("%d \t",i);
sout.Insert(sout.GetLength(),ts);
}
sout.Insert(sout.GetLength(),"\n\n");
for (i=0; i<patternnum; i++)
{
//每列開頭標號
ts.Format("%d \t",i+1);
sout.Insert(sout.GetLength(),ts);
for(j=0; j<patternnum; j++)//首行為原模糊系數
{
ts.Format("%0.3f\t",dis[i*patternnum+j]);
sout.Insert(sout.GetLength(),ts);
if ((j+1)%patternnum==0)
sout.Insert(sout.GetLength(),"\n");
}
sout.Insert(sout.GetLength()," \t");
for(j=0; j<patternnum; j++)//次行為根據閾值修改后的系數“1”或“0”
{
ts.Format("%d\t",result[i*patternnum+j]);
sout.Insert(sout.GetLength(),ts);
if ((j+1)%patternnum==0)
sout.Insert(sout.GetLength(),"\n\n");
}
}
MessageBox(NULL,sout,"分類前后的矩陣對照",MB_OK);
centernum=0;
for (i=0; i<patternnum; i++)//按照閾值分類
for (j=i; j<patternnum; j++)
{
if (result[i*patternnum+j]==1)
{
if (m_pattern[i].category!=0)
m_pattern[j].category=m_pattern[i].category;
else if (m_pattern[j].category!=0)
m_pattern[i].category=m_pattern[j].category;
else
{
centernum++;
m_pattern[j].category=centernum;
m_pattern[i].category=centernum;
}
}
}
delete []dis;
delete []result;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -