C均值聚類
阿新 • • 發佈:2020-12-04
C均值聚類
演算法步驟
- 在樣本集合中選擇C個點作為初始類中心;
- 在剩下的樣本點中選擇一個,計算其到各個中心點的距離,選取距離最短者將其歸為那個類別;
- 選擇下一個樣本,重複2直到計算完所有樣本,若集合不發生變化或達到迭代上限則轉5否則轉4;
- 根據當前的類劃分情況重新計算中心點,重複步驟2;
- 結束演算法。
C實現
/* @Time : 2020/12/4 0:04 @Author : Li Canghao @Name : C_means.py @Software : C-Free */ #include<stdio.h> #include<math.h> const long long maxn = 10005; typedef struct twoD{ double x,y; }twoD; double Distance(twoD a,twoD b){ //計算距離 return fabs(sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y))); } void InitCenters(twoD trains[],int c,twoD centers[]){ //初始化類中心 for(int i = 0; i < c; i++){ centers[i].x = trains[i].x; centers[i].y = trains[i].y; //printf("%lf %lf\n",centers[i].x,centers[i].y) ; } } void SearchMinDistance(int index,twoD train,int c,twoD centers[],int belong[],int cnt[]){ //尋找距離最短 double mindistance = 1e6; int minindex = 0; for(int i= 0; i < c; i++){ if(Distance(train,centers[i])<mindistance){ mindistance = Distance(train,centers[i]); minindex = i; } } belong[index] = minindex; //該模式屬於minindex類 cnt[minindex]++; //該類模式數增加 //printf("belong[%d] = %d cnt[%d] = %d\n",index,minindex,minindex,cnt[minindex]); } void C_mean(int n,twoD trains[],int c){ //C均值主程式 twoD centers[maxn]; //存放類心 twoD avg[c]; //用於計算類心 int belong[n]; //儲存集合關係 int cnt[c]; //儲存一個類有多少模式 int counts = 0; //判斷集合是否不再變化 InitCenters(trains,c,centers); while(counts < c){ for(int i = 0; i < c; i++)cnt[i] = 0; for(int i = 0; i < n; i++){ //每一模式與類心距離按照最小距離歸類 SearchMinDistance(i,trains[i],c,centers,belong,cnt); } for(int i = 0; i < c; i++){ //為計算新的類心初始化 avg[i].x = 0; avg[i].y = 0; } for(int i = 0; i < n; i++){ //準備計算每一類的類心 avg[belong[i]].x += trains[i].x; avg[belong[i]].y += trains[i].y; } counts = 0; for(int i = 0;i < c; i++){ avg[i].x /= cnt[i]; //計算類心 avg[i].y /= cnt[i]; if(((centers[i].x-avg[i].x)<1e-6)&&((centers[i].y-avg[i].y)<1e-6)){ //如果新的類心與原類心差距十分小,就認為沒有更新 counts++; } //printf("count = %d\n",counts); centers[i].x = avg[i].x; //更新類心 centers[i].y = avg[i].y; } } printf("\n-----處理完畢,展示結果-----\n"); for(int i = 0; i < c; i++){ printf("當前第%d類,聚類中心為:(%lf,%lf) 共有%d個模式,其中的集合為:\n",i+1,centers[i].x,centers[i].y,cnt[i]); for(int j = 0; j < n; j++){ if(belong[j] == i)printf("\t%d:(%lf,%lf)\n",j+1,trains[j].x,trains[j].y); } } } int main(){ //測試 twoD trains[maxn]; int n,c; printf("請輸入需要分成多少類:"); scanf("%d",&c); printf("請輸入模式總個數:(n > c)"); scanf("%d",&n); printf("請輸入各模式的特徵值(二維):\n"); for(int i = 0; i < n; i++){ scanf("%lf%lf",&trains[i].x,&trains[i].y); } printf("-----開始C均值聚類-----\n"); C_mean(n,trains,c); printf("-----C均值聚類結束-----\n"); return 0; }
測試資料 少量樣本
1 2
4 5
7 3
100 20
90 50
-5 6
50 89
2000 414
2000 808
2020 124