K-Means聚類算法

聲明

部分參考K-Means聚類算法原理

聚類算法

聚類算法是一種無監督學習算法,它主要用於將相似的樣本自動歸到一個類別中.
聚類算法與分類算法的區別:聚類算法是無監督學習,而分類是監督學習,在聚類算法中我們根據樣本之間的相似度(或者說距離),將樣本歸到不同的類別中,對於不同的相似度我們得到的聚類結果可能是不通的.
K-Means是一種聚類算法,它實現起來比較簡單,而且聚類的效果也不錯,所以應用比較廣泛.K-Means也有很多變體,如K-Means++,距離計算優化elkan K-Means算法和大數據情況下的優化Mini Batch K-Means算法。

K-Means原理

K-Means算法的思想很簡單,對於給定的樣本集,按照樣本之間的距離大小,將樣本集劃分爲K個簇.讓簇內的點儘量的緊密連在一起,而讓簇間的距離儘可能大.
如果用目標函數來表示,假設簇劃分爲(C1,C2,..Ck)(C_1,C_2,..C_k),則我們的目標是最小化平方誤差函數:
E=i=1kxCixμi22 E = \sum\limits_{i=1}^k\sum\limits_{x \in C_i} ||x-\mu_i||_2^2
其中μi\mu_i是簇CiC_i的均值向量,也叫做質心,計算如下:
μi=1CixCix \mu_i = \frac{1}{|C_i|}\sum\limits_{x \in C_i}x
如果我們想直接求上式的最小值並不容易,這是一個NP難的問題,因此只能採用啓發式的迭代方法。
其啓發式方法可以用下圖概括:(該圖來自Andrew Ng machine learning):
{% asset_img 1.png %}
過程如下:
假設我們現在k=2k=2.在圖(b)中我們首先隨機選擇兩個k類所對應類別的質心.接近我們讓每個點分別計算到兩個質心的距離,並將該點的類別標註爲距離最近的那個質心的類別,如圖©.接着我們在每個類別內分別重新計算質心μi\mu_i,如圖(d).在得到新的質心後,我們繼續重複上述圖©的過程,圖(e).知道我們的每個類別的質心不發生變化,圖(f).

K-Means的過程

k值的選擇

對於k-means算法我們只有一個超參數,那就是如何選擇k?
一般來說我們會根據自己的需求以及先驗知識選擇一個合適的k值,也可以通過交叉驗證來選擇一個合適的k值.
Andrew Ng介紹了一種方法叫做Elbow Method(肘方法).如下:
對於你]
個點的數據集,迭代計算k從1-n,每次聚類完成後計算每個點到其聚類質心的距離的平方和(也就是目標函數值),然後描述圖像.可以想象平方和是逐漸減少的,知道k==n目標函數值爲0.在這個目標函數值逐漸變小的過程中,可能會出現一個"肘"點,如下圖:
{% asset_img 2.png %}
那麼此時我們就認爲這個"肘"點處是最優的k值.
但是其實大多數情況下,我們得到的都是如下圖像,而並不是存在"肘"點的,所以這種方法可能就無法使用了.
{% asset_img 3.png %}

隨機初始化

在確定了k的值之後,我們就需要選擇k個質心,如何選擇呢?
一般我們是隨機選擇k個樣本,然後將質心的值設爲這k個樣本的值.但是由於我們使用的是啓發式方法,所以初始值的選擇對我們的聚類結果是有影響的,可能我們得到的就是局部最優質,而不是全局最優了,因此我們需要選擇合適的k個質心.
通常情況下,我們的做法就是進行多次聚類(如100次),每次隨機選擇k個質心.每次聚類完成後計算目標函數J的值,從其中確定的最優的方案.(經驗表明,在k=1~10,這種方法一般會找到全局最優解)

算法流程

輸入是樣本集D={x1,x2,...xm}D=\{x_1,x_2,...x_m\},聚類的簇數k,最大迭代次數N
輸出是簇劃分C={C1,C2,...Ck}C=\{C_1,C_2,...C_k\}
1.從數據集D中隨機選擇k個樣本作爲初始的k個質心向量:{μ1,μ2,...,μk}\{\mu_1,\mu_2,...,\mu_k\}
2.對於n=1,2,...Nn = 1,2,...N:
1)將簇劃分C初始化爲Ct=    t=1,2...kC_t = \varnothing \;\; t =1,2...k
2)對於i = 1,2,…m計算樣本xix_i和各個質心向量μj\mu_j的距離:dij=xiμj22d_{ij} = ||x_i - \mu_j||_2^2,將xix_i標記爲最小的爲dijd_{ij}所對應的類別λi\lambda_i,此時更新Cλi=Cλi{xi}C_{\lambda_i} = C_{\lambda_i} \cup \{x_i\}
3)對於j = 1,2,…k 對CjC_j中所有的樣本點重新計算新的質心μj=1CjxCjx\mu_j = \frac{1}{|C_j|}\sum\limits_{x \in C_j}x
如果所有的k個質心的向量都無變化則跳到3.
3.結束依次k-means聚類,計算目標函數JJ
4.重複1-3多次,找到最優的聚類

K-Means初始化優化K-Means++

在上節我們提到,k個初始化的質心的位置選擇對最後的聚類結果和運行時間都有很大的影響,因此需要選擇合適的k個質心。如果僅僅是完全隨機的選擇,有可能導致算法收斂很慢。K-Means++算法就是對K-Means隨機初始化質心的方法的優化。
K-Means++的對於初始化質心的優化策略也很簡單,如下:
1.從輸入的數據集中隨機選擇一個點作爲第一個聚類中心μ1\mu_1
2.對於數據集中的每一個點xix_i,計算它與已選擇的聚類中心中最近聚類中心點的距離
D(xi)=arg  minxiμr22    r=1,2,...kselectedD(x_i) = arg\;min||x_i- \mu_r||_2^2\;\;r=1,2,...k_{selected}
3.選擇一個新的數據點作爲新的聚類中心,選擇的原則是:D(x)D(x)較大的點,被選取作爲聚類中心的概率較大
4.重複2,3直到選擇出k個聚類質心
5.利用這k個質心作爲初始化質心去運行標準的K-Means聚類方法

K-Means距離計算優化elkan K-Means

在傳統的K-Means算法中,我們在每輪迭代時,要計算所有的樣本點到所有的質心的距離,這樣會比較的耗時。那麼,對於距離的計算有沒有能夠簡化的地方呢?elkan K-Means算法就是從這塊入手加以改進。它的目標是減少不必要的距離的計算。那麼哪些距離不需要計算呢?
elkan K-Means利用了兩邊之和大於等於第三邊,以及兩邊之差小於第三邊的三角形性質,來減少距離的計算。
第一種規律是對於一個樣本點xx和兩個質心μj1,μj2\mu_{j_1}, \mu_{j_2}.如果我們預先計算出了這兩個質心之間的距離D(j1,j2)D(j_1,j_2),則如果計算髮現2D(x,j1)D(j1,j2)2D(x,j_1) \leq D(j_1,j_2),我們立即就可以知道D(x,j1)D(x,j2)D(x,j_1) \leq D(x, j_2).此時我們不需要再計算D(x,j2)D(x, j_2).
第二種規律是對於一個樣本點x和兩個質心μj1,μj2\mu_{j_1}, \mu_{j_2}.我們可以得到D(x,j2)max{0,D(x,j1)D(j1,j2)}D(x,j_2) \geq max\{0, D(x,j_1) - D(j_1,j_2)\}.
利用上邊的兩個規律,elkan K-Means比起傳統的K-Means迭代速度有很大的提高。但是如果我們的樣本的特徵是稀疏的,有缺失值的話,這個方法就不使用了,此時某些距離無法計算,則不能使用該算法。

大樣本優化Mini Batch K-Means

在統的K-Means算法中,要計算所有的樣本點到所有的質心的距離。如果樣本量非常大,比如達到10萬以上,特徵有100以上,此時用傳統的K-Means算法非常的耗時,就算加上elkan K-Means優化也依舊。在大數據時代,這樣的場景越來越多。此時Mini Batch K-Means應運而生。

顧名思義,Mini Batch,也就是用樣本集中的一部分的樣本來做傳統的K-Means,這樣可以避免樣本量太大時的計算難題,算法收斂速度大大加快。當然此時的代價就是我們的聚類的精確度也會有一些降低。一般來說這個降低的幅度在可以接受的範圍之內。
 在Mini Batch K-Means中,我們會選擇一個合適的批樣本大小batch size,我們僅僅用batch size個樣本來做K-Means聚類。那麼這batch size個樣本怎麼來的?一般是通過無放回的隨機採樣得到的。
 爲了增加算法的準確性,我們一般會多跑幾次Mini Batch K-Means算法,用得到不同的隨機採樣集來得到聚類簇,選擇其中最優的聚類簇。

K-Means小結

K-Means的主要優點有:

  1. 原理比較簡單,實現也很容易,收斂速度快
  2. 聚類效果比較好,算法的可解釋性強
  3. 主要的超參數就是k

缺點:

  1. k值的選取不好把握
  2. 對於不是凸的數據集比較難收斂
  3. 如果各隱含類別的數據不平衡,比如各隱含類別的數據量嚴重失衡,或者各隱含類別的方差不同,則聚類效果不佳
  4. 採用迭代方法,得到的結果只是局部最優
  5. 對噪音和異常點比較敏感
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章