kmeans演算法c語言實現,能對不同維度的數據進行聚類

来源:http://www.cnblogs.com/LCcnblogs/archive/2016/10/26/6000934.html
-Advertisement-
Play Games

最近在苦於思考kmeans演算法的MPI並行化,花了兩天的時間先把串列版本實現了。 聚類問題就是給定一個元素集合V,其中每個元素具有d個可觀察屬性,使用某種演算法將V劃分成k個子集,要求每個子集內部的元素之間相異度儘可能低,而不同子集的元素相異度儘可能高。 下麵是google到該演算法的一個流程圖,表意清 ...


  最近在苦於思考kmeans演算法的MPI並行化,花了兩天的時間先把串列版本實現了。

 

  聚類問題就是給定一個元素集合V,其中每個元素具有d個可觀察屬性,使用某種演算法將V劃分成k個子集,要求每個子集內部的元素之間相異度儘可能低,而不同子集的元素相異度儘可能高。

  下麵是google到該演算法的一個流程圖,表意清楚:

  1、隨機選取數據集中的k個數據點作為初始的聚類中心:

  

  2、計算每個數據點對應的最短距離的聚類中心::

  

  3、利用目前得到的聚類重新計算中心點:

  

  4、重覆步驟2和3直到收斂(達到最大迭代次數或聚類中心移動距離極小): 

   

  code:

  1 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <math.h>
  5 #include <time.h>
  6 
  7 int K,N,D;  //聚類的數目,數據量,數據的維數
  8 float **data;  //存放數據
  9 int *in_cluster;  //標記每個點屬於哪個聚類
 10 float **cluster_center;  //存放每個聚類的中心點
 11 
 12 float **array(int m,int n);
 13 void freearray(float **p);
 14 float **loadData(int *k,int *d,int *n);
 15 float getDistance(float avector[],float bvector[],int n);
 16 void cluster();
 17 float getDifference();
 18 void getCenter(int in_cluster[N]);
 19 
 20 int  main()
 21 {
 22     int i,j,count=0;
 23     float temp1,temp2;
 24     data=loadData(&K,&D,&N);
 25     printf("Data sets:\n");
 26     for(i=0;i<N;i++)
 27         for(j=0;j<D;j++){
 28             printf("%-8.2f",data[i][j]);
 29             if((j+1)%D==0)    putchar('\n');
 30         }
 31     printf("-----------------------------\n");
 32 
 33     srand((unsigned int)(time(NULL)));  //隨機初始化k個中心點
 34     for(i=0;i<K;i++)
 35         for(j=0;j<D;j++)
 36             cluster_center[i][j]=data[(int)(N*rand()/(RAND_MAX+1.0))][j];
 37 
 38     cluster();  //用隨機k個中心點進行聚類
 39     temp1=getDifference();  //第一次中心點和所屬數據點的距離之和
 40     count++;
 41     printf("The difference between data and center is: %.2f\n\n", temp1);
 42 
 43     getCenter(in_cluster);
 44     cluster();  //用新的k個中心點進行第二次聚類
 45     temp2=getDifference();
 46     count++;
 47     printf("The difference between data and center is: %.2f\n\n",temp2);
 48 
 49     while(fabs(temp2-temp1)!=0){   //比較前後兩次迭代,若不相等繼續迭代
 50         temp1=temp2;
 51         getCenter(in_cluster);
 52         cluster();
 53         temp2=getDifference();
 54         count++;
 55         printf("The %dth difference between data and center is: %.2f\n\n",count,temp2);
 56     }
 57 
 58     printf("The total number of cluster is: %d\n\n",count);  //統計迭代次數
 59     system("pause");
 60     return 0;
 61 }
 62 
 63 
 64 //動態創建二維數組
 65 float **array(int m,int n)
 66 {
 67     float **p;
 68     p=(float **)malloc(m*sizeof(float *));
 69     p[0]=(float *)malloc(m*n*sizeof(float));
 70     for(int i=1;i<m;i++)    p[i]=p[i-1]+n;
 71     return p;
 72 }
 73 
 74 //釋放二維數組所占用的記憶體
 75 void freearray(float **p)
 76 {
 77     free(*p);
 78     free(p);
 79 }
 80 
 81 //從data.txt導入數據,要求首行格式:K=聚類數目,D=數據維度,N=數據量
 82 float **loadData(int *k,int *d,int *n)
 83 {
 84     float **arraydata;
 85     FILE *fp;
 86     if((fp=fopen("data.txt","r"))==NULL)    fprintf(stderr,"cannot open data.txt!\n");
 87     if(fscanf(fp,"K=%d,D=%d,N=%d\n",k,d,n)!=3)        fprintf(stderr,"load error!\n");
 88     arraydata=array(*n,D);  //生成數據數組
 89     cluster_center=array(*k,D);  //聚類的中心點
 90     in_cluster=(int *)malloc(*n * sizeof(int));  //每個數據點所屬聚類的標誌數組
 91     for(int i=0;i<*n;i++)
 92         for(int j=0;j<D;j++)
 93             fscanf(fp,"%f",&arraydata[i][j]);  //讀取數據點
 94     return arraydata;
 95 }
 96 
 97 //計算歐幾裡得距離
 98 float getDistance(float avector[],float bvector[],int n)
 99 {
100     int i;
101     float sum=0.0;
102     for(i=0;i<n;i++)
103         sum+=pow(avector[i]-bvector[i],2);
104     return sqrt(sum);
105 }
106 
107 //把N個數據點聚類,標出每個點屬於哪個聚類
108 void cluster()
109 {
110     int i,j;
111     float min;
112     float **distance=array(N,K);  //存放每個數據點到每個中心點的距離
113     //float distance[N][K];  //也可使用C99變長數組
114     for(i=0;i<N;++i){
115         min=9999.0;
116         for(j=0;j<K;++j){
117             distance[i][j] = getDistance(data[i],cluster_center[j],D);
118             //printf("%f\n", distance[i][j]);
119             if(distance[i][j]<min){
120                 min=distance[i][j];
121                 in_cluster[i]=j;
122             }
123         }
124         printf("data[%d] in cluster-%d\n",i,in_cluster[i]+1);
125     }
126     printf("-----------------------------\n");
127     free(distance);
128 }
129 
130 //計算所有聚類的中心點與其數據點的距離之和
131 float getDifference()
132 {
133     int i,j;
134     float sum=0.0;
135     for(i=0;i<K;++i){
136         for(j=0;j<N;++j){
137             if(i==in_cluster[j])
138                 sum+=getDistance(data[j],cluster_center[i],D);
139         }
140     }
141     return sum;
142 }
143 
144 //計算每個聚類的中心點
145 void getCenter(int in_cluster[N])
146 {
147     float **sum=array(K,D);  //存放每個聚類中心點
148     //float sum[K][D];  //也可使用C99變長數組
149     int i,j,q,count;
150     for(i=0;i<K;i++)
151         for(j=0;j<D;j++)
152             sum[i][j]=0.0;
153     for(i=0;i<K;i++){
154         count=0;  //統計屬於某個聚類內的所有數據點
155         for(j=0;j<N;j++){
156             if(i==in_cluster[j]){
157                 for(q=0;q<D;q++)
158                     sum[i][q]+=data[j][q];  //計算所屬聚類的所有數據點的相應維數之和
159                 count++;
160             }
161         }
162         for(q=0;q<D;q++)
163             cluster_center[i][q]=sum[i][q]/count;
164     }
165     printf("The new center of cluster is:\n");
166     for(i = 0; i < K; i++)
167         for(q=0;q<D;q++){
168             printf("%-8.2f",cluster_center[i][q]);
169             if((q+1)%D==0)    putchar('\n');
170     }
171     free(sum);
172 }

  

  該程式支持不同維度的數據集,一個示例的數據集: data.txt如下:

  K=3,D=3,N=15

  -25 22.2 35.34
  31.2 -14.4 23
  32.02 -23 24.44
  -25.35 36.3 -33.34
  -20.2 27.333 -28.22
  -15.66 17.33 -23.33
  26.3 -31.34 16.3
  -22.544 16.2 -32.22
  12.2 -15.22 22.11
  -41.241 25.232 -35.338
  -22.22 45.22 23.55
  -34.22 50.14 30.98
  15.23 -30.11 20.987
  -32.5 15.3 -25.22
  -38.97 20.11 33.22 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一。開發的準備 1.jdk的安裝(window) (1)根據自己的電腦下載對應的jdk,並安裝 (推薦安裝在沒有中文的目錄中)。 網站 http://www.oracle.com/technetwork/cn/java/javase/downloads/jdk7-downloads-1880260. ...
  • 一、AbstractCollection 提供了集合的最大實現 繼承該類,必須實現size()和iterator(),因為該類操作集合都是通過iterator 二、fail-fast策略 該策略在集合框架中多次被應用 一種多線程對同一集合操作的保護措施,確保操作目標沒有被其他線程操作過,與cas思想 ...
  • macOS Sierra 已經幫我們預裝了 Ruby、PHP(5.6)、Perl、Python 等常用的腳本語言,以及 Apache HTTP 伺服器。由於 nginx 既能作為 HTTP 伺服器也能作為反向代理伺服器,且配置簡單,這裡我們用 nginx 代替 Apache 作為我們預設的 HTTP ...
  • 最近自學了一下NodeJS,然後做了一個小demo,實現歌曲的添加、修改、播放和刪除的功能,其中自然要實現音樂和圖片的上傳功能。於是上網查找資料,找到了一個formidable插件,該插件可以很好的實現文件的上傳功能。該小demo用到了MySQL資料庫,所有的數據都存放到了資料庫中。下麵簡單說一些如... ...
  • 可以在Index.php文件下 <?php 之前添加<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> ...
  • REST是一種架構風格,其核心是面向資源,REST專門針對網路應用設計和開發方式,以降低開發的複雜性,提高系統的可伸縮性。REST提出設計概念和準則為: REST是一種架構風格,其核心是面向資源,REST專門針對網路應用設計和開發方式,以降低開發的複雜性,提高系統的可伸縮性。REST提出設計概念和準 ...
  • 監聽器的原理: 被監聽對象→對象擁有的事件→捕獲到事件變化→監聽器捕捉事件→監聽器處理該事件 Web伺服器上有4個範圍,拋開page範圍,還有request範圍,session範圍,application範圍。這些範圍的對象什麼時候創建,什麼時候銷毀,什麼時候往範圍中存放了數據,什麼時候替換了存放的 ...
  • 位元組流與和字元流的使用非常相似,兩者除了操作代碼上的不同之外,是否還有其他的不同呢?實際上位元組流在操作時本身不會用到緩衝區(記憶體),是文件本身直接操作的,而字元流在操作時使用了緩衝區,通過緩衝區再操作文件,如圖12-6所示。下麵以兩個寫文件的操作為主進行比較,但是在操作時位元組流和字元流的操作完成之後 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...