模式识别导论大作业
一、 K均值聚类
1. 功能描述:
利用K-均值算法将150个模式样本分成3类别。分别计算最后算法所用的迭代次数,最终聚类中心以及每个类别中对应模式样本的序号。
2. 带注释的源代码
#include "stdio.h"
#include "math.h"
typedef struct mydata{
float data[4]; //保存原始数据
int index;
}MyData;
MyData myData[150];
float classdata[3][150][4];
int saveindex[3][150]; //保存下表
float center[3][4]; //保存三个聚类中心
float newcenter[3][4];//保存三个新的聚类中心
int findMinCenter(float*temp){//找到当前数据的类别
float dis[3]={0,0,0};
float min = 100000;
int returnk=0;
for(int k=0;k<3;k++){
float mytemp = 0;
for(int m=0;m<4;m++)
mytemp += (temp[m]-center[k][m])*(temp[m]-center[k][m]);
dis[k] = sqrt(mytemp);
//printf("%f\n",dis[k]);
if(dis[k]<min){
min = dis[k];
returnk = k;
}} return returnk;
}
void counterNewCenter(floattempdata[][4],int len,int num){
float temp[4] = {0,0,0,0}; //计算新的聚类中心方法
for(int j=0;j<len;j++){
for(int i=0;i<4;i++){
temp[i] += tempdata[j][i];
} }
for(int k=0;k<4;k++){
newcenter[num][k] = temp[k]/len;
printf("k = %f\n",newcenter[num][k]);
}}
int main(){
int k=0;
int kt[3] = {0,0,0};
int i=0,u=0;
FILE *fp;
if ((fp = fopen("D:\\Iris.txt", "r")) ==NULL){ //打开文件
printf("打开文件失败\n");
return 0;
} float numtemp;
while (!feof(fp)){ //读取数据
fscanf(fp, "%f", &numtemp);
myData[u].data[i++] = numtemp;
if(i==4){
u++;
i=0;} }
fclose(fp);//关闭文件
for(k=0;k<4;k++){
center[0][k] = myData[0].data[k];
center[1][k] = myData[1].data[k];
center[2][k] = myData[2].data[k];
}//设置初始聚类中心
int s=0;int num = 0;i=0;//聚类所用的迭代次数
while(i<150){
i++;
k = findMinCenter(myData[i].data);
//printf("k = %d\n",k);
saveindex[k][kt[k]] = i;
for(s=0;s<4;s++){
classdata[k][kt[k]][s] = myData[i].data[s];}//每次将数据分到不同的类中
kt[k]++;if (i == 150){
printf("******************");
for (int m = 0; m<3; m++)//计算新的聚类中心
counterNewCenter(classdata[m],kt[m],m);
bool flag = true;//标示前后聚类中心是否相等的布尔类型
for(int n=0;n<3;n++){
for(int t=0;t<4;t++){
if(newcenter[n][t] != center[n][t]){
flag = false; break;}//if
if(!flag) break;}//for
}//for
if(!flag){ i = 0;num++; //如果前后两次的聚类中心不相等,则继续分类
for(int y=0;y<3;y++){
kt[y] = 0;
for(int w=0;w<4;w++)
center[y][w] = newcenter[y][w];//构建新的聚类中心
}//for
}//if(!flag)
}//if (i == 150)
}//while
printf("%d\n",num); //输出聚类所用的迭代次数
if ((fp = fopen("D:\\result.txt", "wr")) ==NULL){ //创建result.txt文件
printf("创建文件失败\n");
return 0; }
for(i=0;i<3;i++){
for(u=0;u<kt[i];u++){
printf("%d ",saveindex[i][u]);//将3组数据的下标写入文件保存
fprintf(fp,"%d ",saveindex[i][u]); }
fprintf(fp,"\n\n\n");
}fclose(fp);
return 0;
}