k-means算法是一種基本的聚類算法,這個算法的先決條件是
1)必須選擇最終結果需要聚為幾類,就是k的大小。
2)初始化聚類中心點,也就是seeds。
當然,我們可以在輸入的數據集中隨機的選擇k個點作為seeds,但是隨機選擇初始seeds可能會造成聚類的結果和數據的實際分布相差很大。既然選擇初始的seeds這么重要,那有什么算法可以幫助選擇初始的seeds嗎?當然有,k-means++就是選擇初始seeds的一種算法。
k-means++算法選擇初始seeds的基本思想就是:初始的聚類中心之間的相互距離要盡可能的遠。wiki上對該算法的描述是如下:
- 從輸入的數據點集合中隨機選擇一個點作為第一個聚類中心
- 對於數據集中的每一個點x,計算它與最近聚類中心(指已選擇的聚類中心)的距離D(x)
- 選擇一個新的數據點作為新的聚類中心,選擇的原則是:D(x)較大的點,被選取作為聚類中心的概率較大
- 重復2和3直到k個聚類中心被選出來
- 利用這k個初始的聚類中心來運行標准的k-means算法
從上面的算法描述上可以看到,算法的關鍵是第3步,如何將D(x)反映到點被選擇的概率上,一種算法如下(詳見此地):
- 先從我們的數據庫隨機挑個隨機點當“種子點”
- 對於每個點,我們都計算其和最近的一個“種子點”的距離D(x)並保存在一個數組里,然后把這些距離加起來得到Sum(D(x))。
- 然后,再取一個隨機值,用權重的方式來取計算下一個“種子點”。這個算法的實現是,先取一個能落在Sum(D(x))中的隨機值Random,然后用Random -= D(x),直到其<=0,此時的點就是下一個“種子點”。
- 重復2和3直到k個聚類中心被選出來
- 利用這k個初始的聚類中心來運行標准的k-means算法
可以看到算法的第三步選取新中心的方法,這樣就能保證距離D(x)較大的點,會被選出來作為聚類中心了。至於為什么原因很簡單,如下圖 所示:
假設A、B、C、D的D(x)如上圖所示,當算法取值Sum(D(x))*random時,該值會以較大的概率落入D(x)較大的區間內,所以對應的點會以較大的概率被選中作為新的聚類中心。So it's work!
參考資料:
1)http://coolshell.cn/articles/7779.html
2)http://en.wikipedia.org/wiki/K-means%2B%2B
3)http://stackoverflow.com/questions/5466323/how-exactly-does-k-means-work