K Means聚類最優k值的選取

2021-08-20 09:38:30 字數 3183 閱讀 6137

最近做乙個文字分類的專案,在最開始的時候會用到k-means的聚類方法,因此需要在文字上找到最佳的聚類數。

1.1 理論

手肘法的評價k值好壞的標準是sse(sum of the squared errors)ss

e=∑p

∈ci|

p−mi

|2s se

=∑p∈

ci|p

−mi|

2其中 c

i c

i代表第

i i

個簇,p' role="presentation" style="position: relative;">pp是簇

cic

i裡的樣本點,mi

m

i是簇的質心。

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

1.2 **

輸入資料格式是乙個列表,每個元素都是乙個n維度向量。

from sklearn.cluster import kmeans

import multiprocessing

deftrain_cluster

(train_vecs, model_name=none, start_k=2, end_k=20):

print('training cluster')

sse =

sse_d1 = #sse的一階導數

sse_d2 = #sse的二階導數

models = #儲存每次的模型

for i in range(start_k, end_k):

kmeans_model = kmeans(n_clusters=kmeans_clusters, n_jobs=multiprocessing.cpu_count(), )

kmeans_model.fit(train_vecs)

print('{} means sse loss = {}'.format(i, kmeans_model.inertia_))

# 求二階導數,通過sse方法計算最佳k值

sse_length = len(sse)

for i in range(1, sse_length):

for i in range(1, len(sse_d1) - 1):

best_model = models[sse_d2.index(max(sse_d2)) + 1]

return best_model

2. 輪廓係數法

2.1 理論

該方法的核心指標是輪廓係數(silhouette coefficient),某個樣本點xi的輪廓係數定義如下s=

b−am

ax(a

,b) s=b

−ama

x(a,

b)

a a

是xi' role="presentation" style="position: relative;">xix

i和同簇的其他樣本的平均距離,稱為凝聚度。

b b

是xi' role="presentation" style="position: relative;">xix

i和最近簇中所有樣本的平均距離,稱之為分離度。最近簇的定義如下cj

=arg

minck1

n∑p∈

ck|p

−xi|

2 cj=

ar

gminck

1n∑p

∈ck|

p−xi

|2

其中pp

是簇ck

' role="presentation" style="position: relative;">ckc

k中的樣本, 也就是說,計算出xi

x

i到所有簇的平均距離之後,選取最小的作為

b b

即可。2.2 **

資料仍和1.2中的格式一樣

from sklearn.cluster import kmeans

import multiprocessing

from sklearn.metrics import silhouette_score

deftrain_cluster

(train_vecs, model_name=none, start_k=2, end_k=20):

print('training cluster')

scores =

models =

for i in range(start_k, end_k):

kmeans_model = kmeans(n_clusters=kmeans_clusters, n_jobs=multiprocessing.cpu_count(), )

kmeans_model.fit(train_vecs)

score = silhouette_score(train_vecs,kmeans_model.labels_,metric='euclidean')

print('{} means score loss = {}'.format(i, score))

best_model = models[scores.index(max(scores))]

return best_model

但是在實踐的時候發現手肘圖的最佳值和輪廓係數的最佳值是不一樣的,輪廓係數的最佳值小於手肘圖的最佳值,原因我猜測是輪廓係數考慮了分離度b,也就是樣本與最近簇中所有樣本的平均距離。

從定義上看,輪廓係數大,不一定是凝聚度a(樣本與同簇的其他樣本的平均距離)小,而可能是b和a都很大的情況下b相對a大得多,這麼一來,a是有可能取得比較大的。a一大,樣本與同簇的其他樣本的平均距離就大,簇的緊湊程度就弱,那麼簇內樣本離質心的距離也大,從而導致sse較大。所以,雖然輪廓係數引入了分離度b而限制了聚類劃分的程度,但是同樣會引來最優結果的sse比較大的問題。

需要進一步了解的可以檢視wiki

K means聚類最優k值的選取

最近做了乙個資料探勘的專案,挖掘過程中用到了k means聚類方法,但是由於根據行業經驗確定的聚類數過多並且並不一定是我們獲取到資料的真實聚類數,所以,我們希望能從資料自身出發去確定真實的聚類數,也就是對資料而言的最佳聚類數。為此,我查閱了大量資料和部落格資源,總結出主流的確定聚類數k的方法有以下兩...

K means聚類最優k值的選取

我們希望能從資料自身出發去確定真實的聚類數,也就是對資料而言的最佳聚類數 1.手肘法 1.1 理論 手肘法的核心指標是sse sum of the squared errors,誤差平方和 其中,ci是第i個簇,p是ci中的樣本點,mi是ci的質心 ci中所有樣本的均值 sse是所有樣本的聚類誤差,...

kmeans聚類選擇最優K值python實現

kmeans演算法中k值的確定是很重要的。下面利用python中sklearn模組進行資料聚類的k值選擇 資料集自製資料集,格式如下 手肘法 手肘法的核心指標是sse sum of the squared errors,誤差平方和 其中,ci是第i個簇,p是ci中的樣本點,mi是ci的質心 ci中所...