聚類分析是數據分析中,非常重要的一類課題。他的作用是將大量的無標簽數據通過計算,自動為其標注標簽。眾所周知,這一點是區別于數據分類技術的。而現實的場景中,無標簽的數據顯然多于有標簽數據,因此,我在這里也是先說聚類,后面的博文,再說分類。
聚類的目的,是要將數據歸為不同的類,基本原則是要相近的數據盡量歸為一類,而不同類之間的數據則要盡量有比較大的差別。
說到聚類,當然最先想到的就是k-means算法。它不僅是最簡單的聚類算法,也是最普及且最常用的。k-means算法是一種基于形心的劃分數據的方法。我們給定一個數據集
下面,通過一個例子,展示k-means的細節。
我們來處理一個簡單的二維平面上的聚類問題。數據集為:A1(2, 10), A2(2, 5), A3(8, 4), B1(5, 8), B2(7, 5), B3(6, 4), C1(1, 2), C2(4,9),如圖Fig.1:
現在,我們選擇:A1, B1, C1三個點作為初始的簇心,將這個數據集分成三類。
第一步,令所有數據點選擇距離他們最近的簇心,并且執行歸類:歸類的結果如圖Fig.1中虛線所圈出來的那樣:
第二步,更新簇心,重新計算距離,再次執行歸類,結果如圖Fig.2所示,圖中,我用紅色*
號表示簇心:
第三步,重復進行前兩步,直到簇心不在變更為止,最終,得到Fig.3中所示的聚類結果,圖中,我用紅色*
號表示簇心:
可見,整個算法就是一個迭代的過程。需要注意的是,初始簇心的選擇有時候會影響最終的聚類結果,所以,實際操作中,我們一般會選用不同的數據作為初始簇心,多次執行k-means算法。
由于篇幅限制,詳細的實現代碼我在我的github主頁中給出:kmeans,這里省略。
最后,我們對k-means算法作簡要分析:
時間復雜度:k-means++是k-means的變形,通過小心選擇初始簇心,來獲得較快的收斂速度以及聚類結果的質量,本文中,我們將簡單介紹k-means++. 首先,一定要先理解k-means++的原理。
它是這樣去做的:先隨機選擇一個數據項作為第一個初始的簇心(當然,最終我們要選擇
那么究竟怎樣的選擇就是合理的選擇呢?在此我們有這樣一個原則:假設現在已經選擇了
你可能會說,這個道理很簡單,但是應該是選擇距離“最大”的才對,為什么選擇距離“較大”的呢?那是因為這里面可能會存在數據噪聲的問題,也可能由于我們至少第一個簇心的選擇還是隨機的緣故,導致如果這樣每次都“精確”選擇,反而最終的聚類效果不佳。所以,一種比較合理的做法是選擇“較大”,而非“最大”。當然,從這一點,我們也能看出,k-means++即使比傳統的k-means更好,卻依然是一種啟發式的算法,不能說這種做法最終的結果就一定是最優的。
現在的問題就全部集中在如何選擇離簇心距離“較大”的數據點了。假設,現在將所有的數據點與其對應簇心連接,那么會構成
sum(Dis_i)
,然后隨機選取一個小于sum(Dis_i)
的值Random令Random依次減去綜上,k-means++算法步驟如下:
隨機選擇一個數據項,作為第一個簇心根據選擇下一個簇心的操作方法(上面列出的3步),選擇下一簇心重復步驟2,直到得到全部的k-means++雖然在初始簇心的選擇上比k-means更優,但是依然也有缺陷,比如,下一個簇心的選擇總是依賴于已有的簇心,后來k-means||算法,改進了這一缺點,這里就不再做過多介紹了。
k-means++算法和前面k-means算法的全部代碼以及測試數據我都放在了github上:kmeans,歡迎參考指正。
新聞熱點
疑難解答