聚類指的是把集合,分組成多個類,每個類中的對象都是彼此相似的。K-means是聚類中最常用的方法之一,它是基於點與點距離的相似度來計算最佳類別歸屬。
在使用該方法前,要注意(1)對數據異常值的處理;(2)對數據標准化處理(x-min(x))/(max(x)-min(x));(3)每一個類別的數量要大體均等;(4)不同類別間的特質值應該差異較大
一、K-means聚類步驟:
(1)選擇k個初始聚類中心
(2)計算每個對象與這k個中心各自的距離,按照最小距離原則分配到最鄰近聚類
(3)使用每個聚類中的樣本均值作為新的聚類中心
(4)重復步驟(2)和(3)直到聚類中心不再變化
(5)結束,得到k個聚類
二、評價聚類的指標:
(1)inertias:是K-Means模型對象的屬性,它作為沒有真實分類結果標簽下的非監督式評估指標。表示樣本到最近的聚類中心的距離總和。值越小越好,越小表示樣本在類間的分布越集中。
(2)蘭德指數:蘭德指數(Rand index)需要給定實際類別信息C,假設K是聚類結果,a表示在C與K中都是同類別的元素對數,b表示在C與K中都是不同類別的元素對數,則蘭德指數為:
RI取值范圍為[0,1],值越大意味着聚類結果與真實情況越吻合。
對於隨機結果,RI並不能保證分數接近零。為了實現“在聚類結果隨機產生的情況下,指標應該接近零”,調整蘭德系數(Adjusted rand index)被提出,它具有更高的區分度:
ARI取值范圍為[−1,1],值越大意味着聚類結果與真實情況越吻合。從廣義的角度來講,ARI衡量的是兩個數據分布的吻合程度。
(3)互信息(Mutual Information,MI):指的是相同數據的兩個標簽之間的相似度,即也是在衡量兩個數據分布的相似程度。利用互信息來衡量聚類效果需要知道實際類別信息。
假設U與V是對N個樣本標簽的分配情況,則兩種分布的熵分別為:
,其中
U與V之間的互信息(MI)定義為:
,其中
。
標准化后的互信息(Normalized Mutual Information):
調整互信息(Adjusted Mutual Information):
MI與NMI取值范圍[0,1],AMI取值范圍[-1,1],都是值越大說明聚類效果越好。
(4)同質化得分(Homogeneity):如果所有的聚類都只包含屬於單個類的成員的數據點,則聚類結果滿足同質性。取值范圍[0,1],值越大意味着聚類結果與真實情況越符合。
(5)完整性得分(Complenteness):如果作為給定類的成員的所有數據點是相同集群的元素,則聚類結果滿足完整性。取值范圍[0,1],值越大意味着聚類結果與真實情況越符合。
(6)v_meansure_score:同質化和完整性之間的諧波平均值,v=2*(同質化*完整性)/(同質化+完整性),取值范圍[0,1],值越大意味着聚類結果與真實情況越符合。
(7)輪廓系數(Silhouette):適用於實際類別信息未知的情況,用來計算所有樣本的平均輪廓系數。對於單個樣本,設a是該樣本與它同類別中其他樣本的平均距離,b是與它距離最近不同類別中樣本的平均距離,輪廓系數為:
對於一個樣本集合,它的輪廓系數是所有樣本輪廓系數的平均值,輪廓系數取值范圍是[−1,1],0附近的值表示重疊的聚類,負值通常表示樣本被分配到錯誤的集群,分數越高,說明同類別樣本間距離近,不同類別樣本間距離遠。
(8)calinski-harabaz Index:適用於實際類別信息未知的情況,為群內離散與簇間離散的比值,值越大聚類效果越好。
三、KMeans 主要參數
(1)n_clusters:k值
(2)init:初始值選擇方式,可選值:'k-means++'(用均值)、'random'(隨機)、an ndarray(指定一個數組),默認為'k-means++'。
(3)n_init:用不同的初始化質心運行算法的次數。由於K-Means是結果受初始值影響的局部最優的迭代算法,因此需要多跑幾次以選擇一個較好的聚類效果,默認是10,一般不需要改,即程序能夠基於不同的隨機初始中心點獨立運行算法10次,並從中尋找SSE(簇內誤差平方和)最小的作為最終模型。如果k值較大,則可以適當增大這個值。
(4)max_iter: 最大的迭代次數,一般如果是凸數據集的話可以不管這個值,如果數據集不是凸的,可能很難收斂,此時可以指定最大的迭代次數讓算法可以及時退出循環。
(5)algorithm:算法,可選值:“auto”, “full” or “elkan”。"full"指K-Means算法, “elkan”指elkan K-Means算法。默認的"auto"則會根據數據值是否是稀疏的,來決定如何選擇"full"和“elkan”。一般數據是稠密的,那么就是 “elkan”,否則就是"full"。一般來說建議直接用默認的"auto"。
四、k值的選擇方法
基於簇內誤差平方和,使用肘方法確定簇的最佳數量,肘方法的基本理念就是找出聚類偏差驟增是的k值,通過畫出不同k值對應的聚類偏差圖,可以清楚看出。
#導入庫 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.cluster import KMeans #導入數據 df=pd.read_csv(r'E:\data analysis\test\cluster.txt',header=None,sep='\s+') print(df.head()) x=df.iloc[:,:-1] y=df.iloc[:,-1] #肘方法看k值 d=[] for i in range(1,11): #k取值1~11,做kmeans聚類,看不同k值對應的簇內誤差平方和 km=KMeans(n_clusters=i,init='k-means++',n_init=10,max_iter=300,random_state=0) km.fit(x) d.append(km.inertia_) #inertia簇內誤差平方和 plt.plot(range(1,11),d,marker='o') plt.xlabel('number of clusters') plt.ylabel('distortions') plt.show()
從圖中可看出,k取3合適。
五、python做K-Means
繼續使用上例中導入的數據。
#訓練聚類模型 from sklearn import metrics model_kmeans=KMeans(n_clusters=3,random_state=0) #建立模型對象 model_kmeans.fit(x) #訓練聚類模型 y_pre=model_kmeans.predict(x) #預測聚類模型 #評價指標 inertias=model_kmeans.inertia_ #樣本距離最近的聚類中心的距離總和 adjusted_rand_s=metrics.adjusted_rand_score(y_true,y_pre) #調整后的蘭德指數 mutual_info_s=metrics.mutual_info_score(y_true,y_pre) #互信息 adjusted_mutual_info_s=metrics.adjusted_mutual_info_score (y_true,y_pre) #調整后的互信息 homogeneity_s=metrics.homogeneity_score(y_true,y_pre) #同質化得分 completeness_s=metrics.completeness_score(y_true,y_pre) #完整性得分 v_measure_s=metrics.v_measure_score(y_true,y_pre) #V-measure得分 silhouette_s=metrics.silhouette_score(x,y_pre,metric='euclidean') #輪廓系數 calinski_harabaz_s=metrics.calinski_harabaz_score(x,y_pre) #calinski&harabaz得分 print('inertia\tARI\tMI\tAMI\thomo\tcomp\tv_m\tsilh\tc&h') print('%d\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%d'% (inertias,adjusted_rand_s,mutual_info_s,adjusted_mutual_info_s,homogeneity_s, completeness_s,v_measure_s,silhouette_s,calinski_harabaz_s)) inertia ARI MI AMI homo comp v_m silh c&h 0.96 1.03 0.94 0.94 0.94 0.94 0.63 2860
#聚類可視化 centers=model_kmeans.cluster_centers_ #類別中心 print(centers) colors=['r','c','b'] plt.figure() for j in range(3): index_set=np.where(y_pre==j) cluster=x.iloc[index_set] plt.scatter(cluster.iloc[:,0],cluster.iloc[:,1],c=colors[j],marker='.') plt.plot(centers[j][0],centers[j][1],'o',markerfacecolor=colors[j],markeredgecolor='k',markersize=8) #畫類別中心 plt.show() [[-0.97756516 -1.01954358] [ 0.9583867 0.99631896] [ 0.98703574 -0.97108137]]
參考:
《python數據分析與數據化運營》——宋天龍
https://blog.csdn.net/sinat_26917383/article/details/70577710
https://www.jianshu.com/p/b5996bf06bd6
https://blog.csdn.net/sinat_26917383/article/details/51611519
http://www.cnblogs.com/pinard/p/6169370.html
來自:https://www.cnblogs.com/niniya/p/8784947.html