k-means實現聚類及聚類效果指標 k值選擇方法


聚類指的是把集合,分組成多個類,每個類中的對象都是彼此相似的。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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM