零基礎學習Kmeans聚類演算法的原理與實現過程

內容匯入:

聚類

是無監督學習的典型例子,聚類也能為企業運營中也發揮者巨大的作用,比如我們可以利用聚類對目標使用者進行群體分類,把目標群體劃分成幾個具有明顯特徵區別的細分群體,從而可以在運營活動中為這些細分群體採取

精細化

個性化

的運營和服務;還可以利用聚類對產品進行分類,把企業的產品體系進一步細分成具有

不同價值、不同目的

的多維度的產品組合,在此基礎分別制定和相應的開發計劃、運營計劃和服務規劃。這都將提升運營的效率和商業效果。

聚類方法分為基於劃分的聚類、基於層次的聚類、基於密度的聚類、基於網路的聚類、基於模型的聚類以及基於模糊的聚類

,今天我們就從基於劃分的聚類開始講解聚類演算法,什麼是基於劃分的聚類呢?其原理即需要將一堆散點進行聚類,聚類目標是“類內的點足夠近,類間的點足夠遠”,而你需要做的就是(1)確定聚類數目;(2)挑選初始中心點;(3)迭代重置中心點直到滿足“類內的點足夠近,類間的點足夠遠”,典型的基於劃分的聚類就是K-means演算法。

K-means演算法流程

經典的K-means演算法

假設要將無標籤資料集:

零基礎學習Kmeans聚類演算法的原理與實現過程

聚成k個簇C1,C2,…, Ck,最小化損失函式:

零基礎學習Kmeans聚類演算法的原理與實現過程

但是完成這個過程需要遍歷所有可能的簇劃分,這將帶來大量的計算,而K-means是利用貪心策略求得近似解的方法,

經典K-means演算法流程如下

(1)隨機地選擇k個物件,每個物件初始地代表了一個簇的中心;

(2)對剩餘的每個物件,根據其與各簇中心的距離,將它賦給最近的簇;

(3)重新計算每個簇的平均值,更新為新的簇中心;

(4)不斷重複2、3,直到達到某個終止條件。

這個終止條件可以是:沒有(或最小數目)物件被重新分配給不同的聚類、沒有(或最小數目)聚類中心再發生變化、誤差平方和區域性最小。

K-means演算法的改進K-means++演算法

因K-means演算法的聚類結果會受到初始點的的選取的影響,有人提出了K-means++改進了初始點的選取過程:

(1)隨機選取一個樣本點作為第一個聚類中心

(2)計算每個樣本點與當前已有聚類中心的

最短距離

,即:

零基礎學習Kmeans聚類演算法的原理與實現過程

則某樣本點選為下一個簇中心的機率為

零基礎學習Kmeans聚類演算法的原理與實現過程

python實現K-means

在scikit-learn中的KMeans類實現了這一演算法,下面我們來簡單介紹一下Kmeans類的主要引數及方法:

KMeans的主要引數

n_clusters:

int,可選,預設值8,行成的簇數以及中心數

init:

{‘k-means ++’,‘random’或ndarray},預設值‘k-means ++’

‘k-means ++’:以‘k-means ++’方法選擇初始中心

‘random’:隨機選擇初始中心

ndarray (nclusters, nfeatures):給定初始中心

n_init:

int ,預設值 10,用不同的初始化質心執行演算法的次數

max_iter :

int, 預設值 300,最大的迭代次數

tol:

float,預設值 1e-4 與inertia結合來確定收斂條件。

precompute_distances :

{‘auto’, True, False},預計算距離,計算速度更快但佔用更多記憶體。

‘auto’:如果 樣本數乘以聚類數大於 12million 的話則不預計算距離。

True:總是預先計算距離。

False:永遠不預先計算距離。

random_state :

int, RandomState instance 或者None (預設), 確定質心初始化的隨機數生成。使用整數使隨機性具有確定性。

copy_x

:boolean,預設值True 。當我們precomputing distances時,將資料中心化會得到更準確的結果。

True,原始資料不會被改變,確保X是C連續的

False,修改原始資料,並在函式返回之前放回原始資料,但是可能會透過減去然後加上資料均值來引入較小的數值差異,在這種情況下,也不會確保資料是C連續的,這可能會導致 大幅放緩。

n_jobs

:int, 指定計算所用的程序數。內部原理是同時進行n_init指定次數的計算。

‘None’:除非在:obj:joblib。parallel_backend上下文中,否則表示1。

‘-1’: means using all processors。

algorithm :

“auto”, “full” or “elkan”, 預設=“auto”

‘full’: 經典的EM風格演算法

‘elkan’:使用三角不等式的‘elkan’會更有效,但不支援稀疏資料

‘auto’:密集資料選擇‘elkan’,為稀疏資料選擇‘full’。

KMeans的主要方法

fit:訓練Kmeans聚類

fit_predict:計算聚類中心並預測每個樣本的聚類索引。

predict:預測,依據與聚類中心的遠近進行類別預測

KMeans聚類例項:

本文僅展現聚類的過程及程式碼,視覺化的程式碼不再展現

為了更好的

視覺化聚類

效果,我們使用如下圖所示的二維資料進行聚類:

零基礎學習Kmeans聚類演算法的原理與實現過程

Kmeans最優聚類數目的確定

我們知道Kmeans方法需要我們給出聚類數目,但是一般情況下我們無法直接給出一個很合適的聚類數目,因此我們需要確定最優的聚類數目,常見的確定最優聚類數的方法有手肘法和輪廓係數法。

下面我們就來介紹一下這兩個方法的思想以及python實現確認最優聚類數目的過程。

手肘法:

定義聚類的誤差平方和

零基礎學習Kmeans聚類演算法的原理與實現過程

,隨著聚類數k的增大,樣本劃分會更加精細,每個簇的聚合程度會逐漸提高,那麼誤差平方和SSE自然會逐漸變小,當k小於最優聚類數時,由於k的增大會大幅增加每個簇的聚合程度,故SSE的下降幅度會很大,而當k到達最優聚類數後,再增加k所得到的聚合程度回報會迅速變小,所以SSE的下降幅度會驟減,然後隨著k值的繼續增大而趨於平緩,也就是說SSE和k的關係圖是一個手肘的形狀,而這個肘部對應的k值就是資料的最優聚類數。

python計算不同聚類數目下誤差平方和的程式碼如下:

SSE = []for i in range(1,8): km=KMeans(n_clusters=i) km。fit(x) y1=km。predict(x) SSE。append(km。inertia_) print(“k=”+str(i)+“時Kmeans的誤差平方和:”,km。inertia_)‘’‘輸出結果:k=1時Kmeans的誤差平方和: 9289。822973786537k=2時Kmeans的誤差平方和: 4081。729006176964k=3時Kmeans的誤差平方和: 2049。521363130263k=4時Kmeans的誤差平方和: 1258。109982411505k=5時Kmeans的誤差平方和: 1030。7046088439135k=6時Kmeans的誤差平方和: 891。9218511797383k=7時Kmeans的誤差平方和: 777。4389345859881

以聚類數目k為橫座標,誤差平方和為縱座標,繪製折線圖如下圖所示:

零基礎學習Kmeans聚類演算法的原理與實現過程

我們可以看到聚類數目到達4後,再增加k值,SSE下降幅度減小,SSE趨於平緩,所以我們可以確定聚類數目為4。

輪廓係數:

輪廓係數的計算方法如下:

計算 a(i) = average(i向量到所有它屬於的簇中其它點的距離),稱為簇內不相似度

計算 b(i) = min (i向量到與它相鄰最近的一簇內的所有點的平均距離),稱為簇間不相似度

那麼i向量輪廓係數就為:

零基礎學習Kmeans聚類演算法的原理與實現過程

所有點的輪廓係數的平均值

,即聚類結果的總的輪廓係數。

輪廓係數的取值在[-1,1]之間,越趨近於1代表內聚度和分離度都相對較優,即聚類效果越好。(當簇內只有一點時,我們定義輪廓係數s(i)為0)

python計算

不同聚類數目下輪廓係數的程式碼

如下:

from sklearn import metricsSC=[]for i in range(2,8): km=KMeans(n_clusters=i) km。fit(x) y1=km。predict(x) sc=metrics。silhouette_score(x,y1) SC。append(sc) ch=metrics。calinski_harabaz_score(x,y1) CH。append(ch) print(“k=”+str(i)+“時Kmeans的輪廓係數:”, sc)’‘’輸出結果:k=2時Kmeans的輪廓係數: 0。5104346420008198k=3時Kmeans的輪廓係數: 0。5564101841418961k=4時Kmeans的輪廓係數: 0。5707892750326952k=5時Kmeans的輪廓係數: 0。47190247374410116k=6時Kmeans的輪廓係數: 0。475091206758774k=7時Kmeans的輪廓係數: 0。4198657590150086

以聚類數目k為橫座標,輪廓係數和為縱座標,繪製折線圖如下圖所示:

零基礎學習Kmeans聚類演算法的原理與實現過程

我們可以看到k=4時輪廓係數最高,故

最優聚類數目為4

接下來我們在看一下不同聚類數目下的聚類的CH指標:

CH=[]for i in range(2,8): km=KMeans(n_clusters=i) km。fit(x) y1=km。predict(x) ch=metrics。calinski_harabaz_score(x,y1) CH。append(ch) print(“k=”+str(i)+“時Kmeans的CH指標:”, ch)‘’‘輸出結果:k=2時Kmeans的CH指標: 1656。1868658421492k=3時Kmeans的CH指標: 2290。942499540155k=4時Kmeans的CH指標: 2757。8670074800625k=5時Kmeans的CH指標: 2594。294350251559k=6時Kmeans的CH指標: 2437。2529863724803k=7時Kmeans的CH指標: 2359。025076485279

我們再看看之前介紹一個新的聚類的度量指標——CH指標,

CH指標是資料集的分離度與緊密度的比值,以各類中心點與資料集的中心點的距離平方和來度量資料集的分離度,以類內各點與其類中心的距離平方和來度量資料的緊密度

。聚類效果越好,類間差距應該越大,類內差距越小,即類自身越緊密,類間越分散,CH指標值越大聚類效果越好。

不同聚類數目下CH指標值的折線圖如下:

零基礎學習Kmeans聚類演算法的原理與實現過程

從圖中我們也可以發現聚類數目4的聚類效果最好,最後我們以最優聚類數目進行聚類,並可視化聚類結果如下圖所示:

零基礎學習Kmeans聚類演算法的原理與實現過程

從圖中我們可以看出資料被聚為四類,類內較緊密,類間較分散,聚類效果很好。(此時的誤差平方和為:1258。109982,輪廓係數為:0。570789,CH指標為:2757。867)

K-means的優點與缺點

優點

:對於大型資料集也是簡單高效、時間複雜度、空間複雜度低。

缺點

:資料集大時結果容易區域性最優;需要預先設定K值,對最先的K箇中心點選取很敏感;對噪聲和離群值非常敏感;只用於數值型資料;不能解決非凸(non-convex)資料。

想獲取更多內容,請關注

資料實驗室公眾號。