Kmeans聚類算法原理與實現


Kmeans聚類算法

1 Kmeans聚類算法的基本原理

K-means算法是最為經典的基於划分的聚類方法,是十大經典數據挖掘算法之一。K-means算法的基本思想是:以空間中k個點為中心進行聚類,對最靠近他們的對象歸類。通過迭代的方法,逐次更新各聚類中心的值,直至得到最好的聚類結果。

假設要把樣本集分為k個類別,算法描述如下:

  (1)適當選擇k個類的初始中心,最初一般為隨機選取;

  (2)在每次迭代中,對任意一個樣本,分別求其到k個中心的歐式距離,將該樣本歸到距離最短的中心所在的類;

  (3)利用均值方法更新該k個類的中心的值;

  (4)對於所有的k個聚類中心,重復(2)(3),類的中心值的移動距離滿足一定條件時,則迭代結束,完成分類。

Kmeans聚類算法原理簡單,效果也依賴於k值和類中初始點的選擇。

2 算法結構與實現方法

Kmeans算法相對比較簡單,本次算法實現采用C++語言,作為面向對象設計語言,為保證其良好的封裝性以及代碼重用性。軟件包含三個部分,即kmeans.hkmeans.cppmain.cpp

kmeans.h中,首先定義一個類,class KMeans,由於本算法實現需要對外部數據進行讀取和存儲,一次定義了一個容器Vector,其中數據類型為結構體st_point,包含三維點坐標以及一個char型的所屬類的ID。其次為函數的聲明。

4.1 程序基本機構與對應函數

kmeans.cpp中具體給出了不同功能的公有函數,如圖_1中所示,函數比較細化,便於后期應用的擴展,比較具體是聚類函數:cluster,其中嚴格根據kmeans基本原理,聚類的相似度選用的是最簡單的歐式距離,而迭代的結束判定條件選用兩次中心值之間的偏差是否大於給定Dist_near_zero值。具體參見程序源代碼。

3 數據描述

本次算法實驗采用數據為三維點雲數據,類似於實驗室中三維激光掃描儀器所采得數據,形式上更為簡單,整齊有規律,在cloudcompare中顯示出來,如下圖:

4.2 數據原始圖

數據為三維坐標系下的三個點雲集,分別為球體,園面以及正方體,而test.txt文件中是一組三維的點集,是混亂的,聚類算法要做的便是將其中分類存儲起來。很自然的,聚類中K值選擇了3

在軟件實現時,建立了一個含有結構體類型的容器,對原始數據進行讀取。

typedef struct st_point

{ st_pointxyz pnt; //st_pointxyz 為三維點結構類型數據 stru st_pointxyz

int groupID;

    st_point () { }

    st_point(st_pointxyz &p, int id)

    {pnt = p;

     groupID = id;

    }

}st_point;

該數據結構類型中包含三維點數據以及所分類的ID,數據容器為vector<st_point>

4 算法描述與源碼分析

本節重點分析項目中culster聚類函數的具體代碼,由於C++語言較適用於大型程序編寫,本算法又相對簡單,因此未免冗長,具體完整程序見項目源程序。下面只分析Kmeans原理中(2)(3)步驟的程序實現。

如下面程序源代碼:

 

 1 bool KMeans::Cluster()
 2 {
 3     std::vector<st_pointxyz> v_center(mv_center.size());
 4 
 5     do
 6     {
 7         for (int i = 0, pntCount = mv_pntcloud.size(); i < pntCount; ++i)
 8         {
 9             double min_dist = DBL_MAX;
10             int pnt_grp = 0;
11             for (int j = 0; j < m_k; ++j)
12             {
13                 double dist = DistBetweenPoints(mv_pntcloud[i].pnt, mv_center[j]);
14                 if (min_dist - dist > 0.000001)
15                 {
16                     min_dist = dist;
17                     pnt_grp = j;
18                 }
19             }
20             m_grp_pntcloud[pnt_grp].push_back(st_point(mv_pntcloud[i].pnt, pnt_grp));
21         }
22 
23         //保存上一次迭代的中心點
24         for (size_t i = 0; i < mv_center.size(); ++i)
25         {
26             v_center[i] = mv_center[i];
27         }
28 
29         if (!UpdateGroupCenter(m_grp_pntcloud, mv_center))
30         {
31             return false;
32         }
33         if (!ExistCenterShift(v_center, mv_center))
34         {
35             break;
36         }
37         for (int i = 0; i < m_k; ++i){
38             m_grp_pntcloud[i].clear();
39         }
40 
41     } while (true);
42 
43     return true;
44 }

5 算法結果分析

原數據文件test.txt中的數據被分為三類,分別存儲在文件k_1k_2k_3中,我們對三個聚類后所得數據點雲進行顏色添加后顯示在cloudcompare上,得下面的顯示圖:

4.3 Kmeans聚類結果

上圖是在給定的初始三個聚類中心點為{ 0, 0, 0 }{ 2.5, 2.5, 2.5 }{ 3, 3, -3 }的情況下得到的結果。這是比較理想的,再看下圖:

4.4 改變初始聚類中心后的結果

本結果對應的初始三個中心點為{ 2, 2, 2 }{ -2.5, 2.5, 2.5 }{ 3, -3, -3 },很明顯,數據聚類並不理想,這說明K-Means算法一定程度上初始聚類種子點,這個聚類種子點太重要,不同的隨機種子點會有得到完全不同的結果。

上面改動了初始點,下面給出當k=4的聚類結果,分別取了兩組不同的初始點集:

4.5.1 k=4聚類結果1

4.5.2 k=4聚類結果

由上述聚類結果可知,當k增加時,選取聚類初始點合適,可以得到滿意的結果,如5_1所示,與最初結果相比只是將球點雲聚類成了兩部分,而5_25_1相比結果很不理想,由顏色可以看出,圖中只有兩類,另外兩類是空的,說明k值不當,初始值不當的情況下,聚類是會失敗的。

綜上實驗結果分析可以看出,kmeans聚類算法是一類非常快捷的聚類算法,效果也很明顯,局部性較好,容易並行化,對大規模數據集很有意義。但比較依賴於k值得選定與初始聚類中心點的選擇,所以該算法比較適合有人工參與的較大型聚類場合。

 

工程源碼:http://pan.baidu.com/s/1ntN6Pjb

Kmeans聚類算法 - 開源中國社區 http://www.oschina.net/code/snippet_588162_50491

 

參考文獻

[1] Hartigan J A, Wong M A. Algorithm AS 136: A k-means clustering algorithm[J]. Applied statistics, 1979: 100-108.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM