定量評估聚類效果

如果有了類別標籤,那麼聚類結果也可以像分類那樣計算準確率和召回率。但是不應該將分類標籤作爲聚類結果的評價指標,除非你有相關的先驗知識或某種假設,知道這種分類類內差距更小。但是它還是給出了幾種評價標準。

7.9.1 調整蘭德係數 (Adjusted Rand index)

1. 數學原理

  蘭德係數(Rand index)需要給定實際類別信息C,假設K是聚類結果,a表示在C與K中都是同類別的元素對數,b表示在C與K中都是不同類別的元素對數,則蘭德指數爲:

1240

  對於以上公式,

  • 分子:屬性一致的樣本數,即同屬於這一類或都不屬於這一類。a是真實在同一類、預測也在同一類的樣本數;b是真實在不同類、預測也在不同類的樣本數;
  • 分母:任意兩個樣本爲一類有多少種組合,是數據集中可以組成的總元素對數;
  • RI取值範圍爲[0,1],值越大意味着聚類結果與真實情況越吻合。

  對於隨機結果,RI並不能保證分數接近零。爲了實現“在聚類結果隨機產生的情況下,指標應該接近零”,調整蘭德係數(Adjusted rand index)被提出,它具有更高的區分度:

1240

  ARI取值範圍爲[-1,1],值越大意味着聚類結果與真實情況越吻合。從廣義的角度來講,ARI衡量的是兩個數據分佈的吻合程度。

2. 優缺點

優點:

  1. 對任意數量的聚類中心和樣本數,隨機聚類的ARI都非常接近於0;
  2. 取值在[-1,1]之間,負數代表結果不好,越接近於1越好;
  3. 可用於聚類算法之間的比較。

缺點:

  • ARI需要真實標籤

3. python代碼實現

  1. labels_true, labels_pred = check_clusterings(labels_true, labels_pred)

  2. n_samples = labels_true.shape[0]

  3. classes = np.unique(labels_true)

  4. clusters = np.unique(labels_pred)

  5. # Special limit cases: no clustering since the data is not split;

  6. # or trivial clustering where each document is assigned a unique cluster.

  7. # These are perfect matches hence return 1.0.

  8. if (classes.shape[0] == clusters.shape[0] == 1 or classes.shape[0] == clusters.shape[0] == 0 or classes.shape[0] == clusters.shape[0] == len(labels_true)):

  9. return 1.0

  10.  
  11. contingency = contingency_matrix(labels_true, labels_pred)

  12.  
  13. # Compute the ARI using the contingency data

  14. sum_comb_c = sum(comb2(n_c) for n_c in contingency.sum(axis=1))

  15. sum_comb_k = sum(comb2(n_k) for n_k in contingency.sum(axis=0))

  16. sum_comb = sum(comb2(n_ij) for n_ij in contingency.flatten())

  17. prod_comb = (sum_comb_c * sum_comb_k) / float(comb(n_samples, 2))

  18. mean_comb = (sum_comb_k + sum_comb_c) / 2.

  19. return ((sum_comb - prod_comb) / (mean_comb - prod_comb))

4. metrics類使用方法

  設定已知先驗知識的標籤爲labels_true,利用聚類算法預測的樣本標籤爲label_pred,Adjusted Rand index函數是在計算樣本預測值和真實值之間的相似度similarity:同屬於這一類或都不屬於這一類,而不考慮數據元素順序和歸一化。示例代碼:

  1. >>> from sklearn import metrics

  2. >>> labels_true = [0, 0, 0, 1, 1, 1]

  3. >>> labels_pred = [0, 0, 1, 1, 2, 2]

  4.  
  5. >>> metrics.adjusted_rand_score(labels_true, labels_pred)

  6. 0.24...

 

  我們也可以調整預測集label_pred中元素0和1的位置,以及將數據集中爲2的屬性改名爲3,其結果不受影響,示例代碼:

  1. >>> labels_pred = [1, 1, 0, 0, 3, 3]

  2. >>> metrics.adjusted_rand_score(labels_true, labels_pred)

  3. 0.24...

 

  此外,調整adjusted_rand_score函數中labels_true和labels_pred的位置,對結果沒有影響,示例代碼:

  1. >>> metrics.adjusted_rand_score(labels_pred, labels_true)

  2. 0.24...

 

  利用此函數評估模型最好的值爲1,示例代碼:

  1. >>> labels_pred = labels_true[:]

  2. >>> metrics.adjusted_rand_score(labels_true, labels_pred)

  3. 1.0

 

  評估模型最差的值(與labels_true不相關),其結果爲負值或接近0值,示例代碼:

  1. >>> labels_true = [0, 1, 2, 0, 3, 4, 5, 1]

  2. >>> labels_pred = [1, 1, 0, 0, 2, 2, 2, 2]

  3. >>> metrics.adjusted_rand_score(labels_true, labels_pred)

  4. -0.12...

 

7.9.2 互信息評分(Mutual Information based scores)

1. 數學原理

  互信息(Mutual Information)也是用來衡量兩個數據分佈的吻合程度。假設U與V是對N個樣本標籤的分配情況,則兩種分佈的熵(熵表示的是不確定程度)分別爲:

1240

1240


其中:

1240

1240


U與V之間的互信息(MI)定義爲:

1240


其中:

1240


標準化後的互信息(Normalized mutual information)爲:

1240


  不管標籤分配之間的“互信息”的實際數量如何,互信息或者標準化後的值不會因此而調整,而會隨着標籤(簇)數量的增加而增加。
互信息的期望值可以用如下公式來計算:

1240


其中:

1240

1240


ai和bj分別對應着元素屬於Ui和Vj的數量。
  與ARI類似,調整互信息( Adjusted mutual information)定義爲:

1240


  利用基於互信息的方法來衡量聚類效果需要實際類別信息,MI與NMI取值範圍爲[0,1],AMI取值範圍爲[-1,1],它們都是值越大意味着聚類結果與真實情況越吻合。

2. 優缺點

  • 優點:除取值範圍在[0,1]之間,其他同ARI,可用於聚類模型選擇;
  • 缺點:需要先驗知識。

3. python代碼實現

  1. if contingency is None:

  2. labels_true, labels_pred = check_clusterings(labels_true, labels_pred)

  3. contingency = contingency_matrix(labels_true, labels_pred)

  4. contingency = np.array(contingency, dtype='float')

  5. contingency_sum = np.sum(contingency)

  6. pi = np.sum(contingency, axis=1)

  7. pj = np.sum(contingency, axis=0)

  8. outer = np.outer(pi, pj)

  9. nnz = contingency != 0.0

  10. # normalized contingency

  11. contingency_nm = contingency[nnz]

  12. log_contingency_nm = np.log(contingency_nm)

  13. contingency_nm /= contingency_sum

  14. # log(a / b) should be calculated as log(a) - log(b) for

  15. # possible loss of precision

  16. log_outer = -np.log(outer[nnz]) + log(pi.sum()) + log(pj.sum())

  17. mi = (contingency_nm * (log_contingency_nm - log(contingency_sum))+ contingency_nm * log_outer)

  18. return mi.sum()

 

4. metrics類使用方法

  設定已知先驗知識的標籤爲labels_true,利用聚類算法預測的樣本標籤爲label_pred,互信息是衡量兩種預測的一致性,忽略排列的順序。互信息評估有兩種方法,標準化的互信息Normalized Mutual Information(NMI) 和調整後的互信息Adjusted Mutual Information(AMI)。示例代碼:

  1. >>> from sklearn import metrics

  2. >>> labels_true = [0, 0, 0, 1, 1, 1]

  3. >>> labels_pred = [0, 0, 1, 1, 2, 2]

  4.  
  5. >>> metrics.adjusted_mutual_info_score(labels_true, labels_pred)

  6. 0.22504...

 

  我們也可以調整預測集label_pred中元素0和1的位置,以及將數據集中爲2的屬性改名爲3,其結果不受影響,示例代碼:

  1. >>> labels_pred = [1, 1, 0, 0, 3, 3]

  2. >>> metrics.adjusted_mutual_info_score(labels_true, labels_pred)

  3. 0.22504..

 

  互信息評分中mutual_info_score,adjusted_mutual_info_score和normalized_mutual_info_score函數其參數都是對稱的,交換的參數位置不會改變評分值,示例代碼:

  1. >>> metrics.adjusted_mutual_info_score(labels_pred, labels_true)

  2. 0.22504...

 

  利用此函數評估模型最好的值爲1,示例代碼:

  1. >>> labels_pred = labels_true[:]

  2. >>> metrics.adjusted_mutual_info_score(labels_true, labels_pred)

  3. 1.0

  4.  
  5. >>> metrics.normalized_mutual_info_score(labels_true, labels_pred)

  6. 1.0

 

  評估模型最差的值(與labels_true不相關),其結果爲非正值,示例代碼:

  1. >>> labels_true = [0, 1, 2, 0, 3, 4, 5, 1]

  2. >>> labels_pred = [1, 1, 0, 0, 2, 2, 2, 2]

  3. >>> metrics.adjusted_mutual_info_score(labels_true, labels_pred)

  4. -0.10526...

 

7.9.3 同質性Homogeneity 完整性completeness 調和平均V-measure

1. 數學原理

  • 同質性homogeneity:每個羣集只包含單個類的成員;
  • 完整性completeness:給定類的所有成員都分配給同一個羣集。

  同質性和完整性分數基於以下公式得出:

1240

1240


  其中H(C|K)是給定給定簇賦值的類的條件熵,由以下公式求得:

1240


  H(C)是類熵,公式爲:

1240


  其中,n是樣本總數,nc和nk分別屬於類c和類k的樣本數,而nc,k是從類c劃分到類k的樣本數量。
  條件熵H(K|C)和類熵H(K),根據以上公式對稱求得。
  V-measure是同質性homogeneity和完整性completeness的調和平均數,公式:

1240

2. 優缺點

優點:

  • 分數明確:從0到1反應出最差到最優的表現;
  • 解釋直觀:差的調和平均數可以在同質性和完整性方面做定性的分析;
  • 對簇結構不作假設:可以比較兩種聚類算法如k均值算法和譜聚類算法的結果。

缺點:

  • 以前引入的度量在隨機標記方面沒有規範化,這意味着,根據樣本數,集羣和先驗知識,完全隨機標籤並不總是產生相同的完整性和均勻性的值,所得調和平均值V-measure也不相同。特別是,隨機標記不會產生零分,特別是當簇的數量很大時。

當樣本數大於一千,聚類數小於10時,可以安全地忽略該問題。對於較小的樣本量或更大數量的集羣,使用經過調整的指數(如調整蘭德指數)更爲安全。

1240

  • 這些指標要求的先驗知識,在實踐中幾乎不可用或需要手動分配的人作註解者(如在監督學習環境中)。

3. sklearn實現方法

  sklearn.metrics類的homogeneity_score和completeness_score方法分別用來求得同質性和完整性分數,示例代碼:

  1. >>> from sklearn import metrics

  2. >>> labels_true = [0, 0, 0, 1, 1, 1]

  3. >>> labels_pred = [0, 0, 1, 1, 2, 2]

  4.  
  5. >>> metrics.homogeneity_score(labels_true, labels_pred)

  6. 0.66...

  7.  
  8. >>> metrics.completeness_score(labels_true, labels_pred)

  9. 0.42...

 

  兩者的調和平均V-measure,示例代碼:

  1. >>> metrics.v_measure_score(labels_true, labels_pred)

  2. 0.51...

 

  metrics類的homogeneity_completeness_v_measure融合了以上方法,分別能求得相關值,示例代碼:

  1. >>> metrics.homogeneity_completeness_v_measure(labels_true, labels_pred)

  2. ...

  3. (0.66..., 0.42..., 0.51...)

 

  以下預測的評分略好,體現在同質性而非完整性,示例代碼:

  1. >>> labels_true = [0, 0, 0, 1, 1, 1]

  2. >>> labels_pred = [0, 0, 0, 1, 2, 2]

  3. >>> metrics.homogeneity_completeness_v_measure(labels_true, labels_pred)

  4. ...

  5. (1.0, 0.68..., 0.81...)

 

7.9.4 Fowlkes-Mallows scores

  Fowlkes-Mallows指數是針對訓練集和驗證集數據之間求得的查全率和查準率的幾何平均值,其公式爲:

1240


  示例代碼:

  1. >>> from sklearn import metrics

  2. >>> labels_true = [0, 0, 0, 1, 1, 1]

  3. >>> labels_pred = [0, 0, 1, 1, 2, 2]

  4. >>>

  5. >>> metrics.fowlkes_mallows_score(labels_true, labels_pred)

  6. 0.47140...

 

7.9.5 輪廓係數 Silhouette Coefficient

  輪廓係數適用於實際類別信息未知的情況。對於單個樣本,設a是與它同類別中其他樣本的平均距離,b是與它距離最近不同類別中樣本的平均距離,其輪廓係數爲:

1240


  對於一個樣本集合,它的輪廓係數是所有樣本輪廓係數的平均值。
  輪廓係數的取值範圍是[-1,1],同類別樣本距離越相近不同類別樣本距離越遠,分數越高。
  示例代碼:

  1. >>> from sklearn import metrics

  2. >>> from sklearn.metrics import pairwise_distances

  3. >>> from sklearn import datasets

  4. >>> dataset = datasets.load_iris()

  5. >>> X = dataset.data

  6. >>> y = dataset.target

  7.  
  8. >>> import numpy as np

  9. >>> from sklearn.cluster import KMeans

  10. >>> kmeans_model = KMeans(n_clusters=3, random_state=1).fit(X)

  11. >>> labels = kmeans_model.labels_

  12. >>> metrics.silhouette_score(X, labels, metric='euclidean')

  13. ...

  14. 0.55...

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章