1. 程式人生 > >kmeans聚類選擇最優K值python實現

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

Kmeans演算法中K值的確定是很重要的。

下面利用python中sklearn模組進行資料聚類的K值選擇
資料集自制資料集,格式如下:
這裡寫圖片描述

①手肘法
手肘法的核心指標是SSE(sum of the squared errors,誤差平方和),

這裡寫圖片描述

其中,Ci是第i個簇,p是Ci中的樣本點,mi是Ci的質心(Ci中所有樣本的均值),SSE是所有樣本的聚類誤差,代表了聚類效果的好壞。

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

python程式碼:

import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import xlrd

# 從Excel中讀取資料存入陣列
rawData = xlrd.open_workbook('kmeansdata.xlsx')
table = rawData.sheets()[0]
data = []
for i in range(table.nrows):
    if i == 0:
        continue
    else
: data.append(table.row_values(i)[1:]) featureList = ['Age', 'Gender', 'Degree'] mdl = pd.DataFrame.from_records(data, columns=featureList) # '利用SSE選擇k' SSE = [] # 存放每次結果的誤差平方和 for k in range(1, 9): estimator = KMeans(n_clusters=k) # 構造聚類器 estimator.fit(np.array(mdl[['Age', 'Gender'
, 'Degree']])) SSE.append(estimator.inertia_) X = range(1, 9) plt.xlabel('k') plt.ylabel('SSE') plt.plot(X, SSE, 'o-') plt.show()

效果圖:
這裡寫圖片描述

顯然,肘部對於的k值為3,故對於這個資料集的聚類而言,最佳聚類數應該選3。

②輪廓係數法
該方法的核心指標是輪廓係數(Silhouette Coefficient),某個樣本點Xi的輪廓係數定義如下:
這裡寫圖片描述
其中,a是Xi與同簇的其他樣本的平均距離,稱為凝聚度,b是Xi與最近簇中所有樣本的平均距離,稱為分離度。而最近簇的定義是
這裡寫圖片描述

其中p是某個簇Ck中的樣本。事實上,簡單點講,就是用Xi到某個簇所有樣本平均距離作為衡量該點到該簇的距離後,選擇離Xi最近的一個簇作為最近簇。

求出所有樣本的輪廓係數後再求平均值就得到了平均輪廓係數。平均輪廓係數的取值範圍為[-1,1],且簇內樣本的距離越近,簇間樣本距離越遠,平均輪廓係數越大,聚類效果越好。那麼,很自然地,平均輪廓係數最大的k便是最佳聚類數。

python程式碼:

import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
import xlrd

# 從Excel中讀取資料存入陣列
rawData = xlrd.open_workbook('kmeansdata.xlsx')
table = rawData.sheets()[0]
data = []
for i in range(table.nrows):
    if i == 0:
        continue
    else:
        data.append(table.row_values(i)[1:])
featureList = ['Age', 'Gender', 'Degree']
mdl = pd.DataFrame.from_records(data, columns=featureList)


Scores = []  # 存放輪廓係數
for k in range(2, 9):
    estimator = KMeans(n_clusters=k)  # 構造聚類器
    estimator.fit(np.array(mdl[['Age', 'Gender', 'Degree']]))
    Scores.append(silhouette_score(np.array(mdl[['Age', 'Gender', 'Degree']]), estimator.labels_, metric='euclidean'))
X = range(2, 9)
plt.xlabel('k')
plt.ylabel('輪廓係數')
plt.plot(X, Scores, 'o-')
plt.show()

效果圖:

這裡寫圖片描述
說明:建議比較兩個方法選出的K值,如果沒有特殊情況的話,建議首先考慮用手肘法。

參考資料:https://blog.csdn.net/qq_15738501/article/details/79036255

姊妹篇:python進行kmeans聚類

http://www.omegaxyz.com/2018/08/28/python%e5%88%a9%e7%94%a8sklearn%e8%bf%9b%e8%a1%8ckmeans%e8%81%9a%e7%b1%bb/
更多內容訪問omegaxyz.com
網站所有程式碼採用Apache 2.0授權
網站文章採用知識共享許可協議BY-NC-SA4.0授權
© 2018 • OmegaXYZ-版權所有 轉載請註明出處