函數:homogeneity_score
參數:
labels_true
: array-like, shape = [n_samples]- 樣本的真實標簽。
labels_pred
: array-like, shape = [n_samples]- 樣本的預測標簽。
返回值:
h
: float- 同質性得分,在0到1之間,值越大表示聚類越同質,即在理想情況下,一個簇內的所有樣本都屬于同一類標簽。
內部數學形式:
給定一組樣本的真實標簽 CCC 和預測的聚類標簽 KKK,同質性的計算基于條件熵的概念:
H(C∣K)=?∑k∈K∑c∈C∣ck∣nlog?(∣ck∣∣k∣) H(C|K) = -\sum_{k \in K} \sum_{c \in C} \frac{|c_k|}{n} \log \left( \frac{|c_k|}{|k|} \right) H(C∣K)=?k∈K∑?c∈C∑?n∣ck?∣?log(∣k∣∣ck?∣?)
其中,
- CCC 是真實類別集合。
- KKK 是聚類集合。
- ∣ck∣|c_k|∣ck?∣ 表示同時屬于真實類別 ccc 和聚類 kkk 的樣本數。
- ∣k∣|k|∣k∣ 表示屬于聚類 kkk 的樣本總數。
- nnn 是樣本總數。
然后,同質性得分 hhh 定義為:
h=1?H(C∣K)H(C) h = 1 - \frac{H(C|K)}{H(C)} h=1?H(C)H(C∣K)?
其中,
- H(C)H(C)H(C) 是根據真實標簽計算的熵,定義為 H(C)=?∑c∈C∣c∣nlog?(∣c∣n)H(C) = -\sum_{c \in C} \frac{|c|}{n} \log \left(\frac{|c|}{n}\right)H(C)=?∑c∈C?n∣c∣?log(n∣c∣?),這里 ∣c∣|c|∣c∣ 表示屬于類別 ccc 的樣本數。
特點:
- 如果對于所有的 k∈Kk \in Kk∈K 都有 H(Ck)=0H(C_k) = 0H(Ck?)=0,那么 h=1h = 1h=1,意味著聚類完全同質。
- 同質性不考慮簇的數量或大小,因此即使所有樣本都被歸為一類,只要這一類內樣本屬于相同的實際類別,同質性得分也可以很高。
homogeneity_score
函數主要用于評估聚類算法輸出的質量,特別是在關注簇內部一致性的場景中非常有用。
使用示例
import numpy as np
from sklearn.metrics import homogeneity_score, completeness_score, v_measure_score
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs# --- 示例 1: 完美同質性 ---
print("=== 示例 1: 完美同質性 (每個聚類只包含一個類別的樣本) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 聚類結果: 每個聚類都只包含一個真實類別
labels_pred_homogeneous = [0, 0, 1, 1, 2, 2]homo = homogeneity_score(labels_true, labels_pred_homogeneous)
complete = completeness_score(labels_true, labels_pred_homogeneous)
v_measure = v_measure_score(labels_true, labels_pred_homogeneous)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_homogeneous}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 同質性=1.0,因為每個聚類都是純凈的。")
print()# --- 示例 2: 完全不純 (每個聚類都混雜了所有類別) ---
print("=== 示例 2: 完全不純 (每個聚類都混雜了所有類別) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 聚類結果: 第一個聚類包含所有類別的樣本,第二個也是
labels_pred_impure = [0, 1, 0, 1, 0, 1]homo = homogeneity_score(labels_true, labels_pred_impure)
complete = completeness_score(labels_true, labels_pred_impure)
v_measure = v_measure_score(labels_true, labels_pred_impure)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_impure}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 同質性=0.0,因為每個聚類都包含了所有真實類別,非常不純。")
print()# --- 示例 3: 部分同質性 ---
print("=== 示例 3: 部分同質性 (部分聚類是純凈的) ===")labels_true = [0, 0, 0, 1, 1, 1, 2, 2, 2]
# 聚類結果:
# - 聚類0: [0, 0, 0] -> 純凈 (只有類別0)
# - 聚類1: [1, 1, 1, 2, 2, 2] -> 不純 (混雜了類別1和2)
labels_pred_partial = [0, 0, 0, 1, 1, 1, 1, 1, 1]homo = homogeneity_score(labels_true, labels_pred_partial)
complete = completeness_score(labels_true, labels_pred_partial)
v_measure = v_measure_score(labels_true, labels_pred_partial)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_partial}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 同質性>0 但<1,因為有一個聚類是純凈的,但另一個聚類不純。")
print()# --- 示例 4: 過度分割 (高同質性,低完整性) ---
print("=== 示例 4: 過度分割 (高同質性,低完整性) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 聚類結果: 將每個真實類別都分成了兩個更小的聚類
labels_pred_overclustered = [0, 1, 2, 3, 4, 5] # 6個聚類,每個只有1個樣本homo = homogeneity_score(labels_true, labels_pred_overclustered)
complete = completeness_score(labels_true, labels_pred_overclustered)
v_measure = v_measure_score(labels_true, labels_pred_overclustered)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_overclustered}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 同質性=1.0 (每個聚類只有一個樣本,必然是純凈的),")
print(" 但完整性=0.0 (每個真實類別的樣本被分到了不同的聚類中)。")
print()# --- 示例 5: 實際應用 - 用 K-Means 聚類 ---
print("=== 示例 5: 實際應用 - K-Means 聚類評估 ===")# 生成一個簡單的聚類數據集 (3個簇)
X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=42)# 應用 K-Means 聚類
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
y_pred = kmeans.fit_predict(X)# 計算同質性、完整性和 V-Measure
homo_kmeans = homogeneity_score(y_true, y_pred)
complete_kmeans = completeness_score(y_true, y_pred)
v_measure_kmeans = v_measure_score(y_true, y_pred)print(f"K-Means 聚類結果 (n_clusters=3):")
print(f"同質性 (Homogeneity): {homo_kmeans:.6f}")
print(f"完整性 (Completeness): {complete_kmeans:.6f}")
print(f"V-Measure: {v_measure_kmeans:.6f}")
print(f"注: 所有指標都接近 1.0,說明 K-Means 在這個數據集上聚類效果極好。")
print()# --- 可視化 ---
plt.figure(figsize=(15, 5))# 子圖 1: 真實標簽
plt.subplot(1, 3, 1)
scatter1 = plt.scatter(X[:, 0], X[:, 1], c=y_true, cmap='viridis', alpha=0.7)
plt.title('真實標簽')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter1)# 子圖 2: K-Means 聚類結果 (同質性)
plt.subplot(1, 3, 2)
scatter2 = plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis', alpha=0.7)
plt.title(f'K-Means 聚類 (同質性={homo_kmeans:.3f})')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter2)# 子圖 3: K-Means 聚類結果 (完整性)
plt.subplot(1, 3, 3)
scatter3 = plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis', alpha=0.7)
plt.title(f'K-Means 聚類 (完整性={complete_kmeans:.3f})')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter3)plt.tight_layout()
plt.show()# --- 補充: 同質性、完整性與 V-Measure 的關系 ---
print("=== 補充: 同質性、完整性與 V-Measure 的關系 ===")
print("真實標簽:", y_true[:10]) # 只顯示前10個
print("K-Means預測:", y_pred[:10])print(f"同質性 (Homogeneity): {homo_kmeans:.3f}")
print(f"完整性 (Completeness): {complete_kmeans:.3f}")
print(f"V-Measure: {v_measure_kmeans:.3f}")print("\n解釋:")
print("1. 同質性 (Homogeneity): 關注聚類的'純凈度'。")
print("2. 完整性 (Completeness): 關注類別的'完整性'。")
print("3. V-Measure: 是同質性和完整性的調和平均數,")
print(" V = 2 * (homogeneity * completeness) / (homogeneity + completeness)")
print(" 它提供了一個綜合性的單一分數。")
print("4. 理想聚類: 同質性和完整性都應接近 1.0。")
結果分析
=== 示例 1: 完美同質性 (每個聚類只包含一個類別的樣本) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 0, 1, 1, 2, 2]
同質性 (Homogeneity): 1.000000
完整性 (Completeness): 1.000000
V-Measure: 1.000000
解釋: 同質性=1.0,因為每個聚類都是純凈的。=== 示例 2: 完全不純 (每個聚類都混雜了所有類別) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 1, 0, 1, 0, 1]
同質性 (Homogeneity): 0.000000
完整性 (Completeness): 0.000000
V-Measure: 0.000000
解釋: 同質性=0.0,因為每個聚類都包含了所有真實類別,非常不純。=== 示例 3: 部分同質性 (部分聚類是純凈的) ===
真實標簽: [0, 0, 0, 1, 1, 1, 2, 2, 2]
聚類標簽: [0, 0, 0, 1, 1, 1, 1, 1, 1]
同質性 (Homogeneity): 0.500000
完整性 (Completeness): 0.000000
V-Measure: 0.000000
解釋: 同質性>0 但<1,因為有一個聚類是純凈的,但另一個聚類不純。=== 示例 4: 過度分割 (高同質性,低完整性) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 1, 2, 3, 4, 5]
同質性 (Homogeneity): 1.000000
完整性 (Completeness): 0.000000
V-Measure: 0.000000
解釋: 同質性=1.0 (每個聚類只有一個樣本,必然是純凈的),但完整性=0.0 (每個真實類別的樣本被分到了不同的聚類中)。=== 示例 5: 實際應用 - K-Means 聚類評估 ===
K-Means 聚類結果 (n_clusters=3):
同質性 (Homogeneity): 1.000000
完整性 (Completeness): 1.000000
V-Measure: 1.000000
注: 所有指標都接近 1.0,說明 K-Means 在這個數據集上聚類效果極好。=== 補充: 同質性、完整性與 V-Measure 的關系 ===
真實標簽: [0 1 2 0 1 2 0 1 2 0]
K-Means預測: [1 2 0 1 2 0 1 2 0 1]
同質性 (Homogeneity): 1.000
完整性 (Completeness): 1.000
V-Measure: 1.000解釋:
1. 同質性 (Homogeneity): 關注聚類的'純凈度'。
2. 完整性 (Completeness): 關注類別的'完整性'。
3. V-Measure: 是同質性和完整性的調和平均數,V = 2 * (homogeneity * completeness) / (homogeneity + completeness)它提供了一個綜合性的單一分數。
4. 理想聚類: 同質性和完整性都應接近 1.0。
關鍵點總結
-
純凈度:
homogeneity_score
的核心是衡量聚類的“純凈度”。它回答的問題是:“一個聚類里是否都是同一種東西?” -
取值范圍:
[0, 1]
,越接近 1 越好。 -
與
completeness_score
的關系:- 同質性 (Homogeneity): 關注聚類簇的純凈度。
- 完整性 (Completeness): 關注真實類別的完整性。
- 兩者是互補的。一個完美的聚類應該同時具有高同質性和高完整性。
-
與
v_measure_score
的關系:- V-Measure 是同質性和完整性的調和平均數。
V = 2 * (homogeneity * completeness) / (homogeneity + completeness)
- 它提供了一個綜合性的單一分數,平衡了純凈度和完整性。
-
缺點: 單獨使用同質性可能會被“過度分割”(over-segmentation)所欺騙。將每個樣本都分成一個單獨的聚類,同質性會是 1.0,但這顯然不是有意義的聚類。
-
何時使用:
- 當你特別關心聚類結果的“純凈度”時。
- 通常與
completeness_score
和v_measure_score
一起使用,以獲得對聚類質量的全面評估。 - 在調試聚類算法時,如果同質性很低,說明算法可能把不同類別的樣本混在了一個簇里。
總而言之,homogeneity_score
是評估聚類質量的重要指標之一,它從“純凈度”的角度提供了有價值的洞察。但要記住,它只是拼圖的一塊,通常需要結合其他指標(尤其是 completeness_score
)來全面評價一個聚類算法的性能。
函數:completeness_score
簡介:
完整性得分用于評估聚類算法的結果,具體來說,它是衡量一個聚類算法是否能夠將屬于同一類別的所有樣本都分配到相同的簇中。完整性得分越高,說明聚類結果越完整。
參數:
labels_true
: array-like, shape = [n_samples]- 樣本的真實標簽。
labels_pred
: array-like, shape = [n_samples]- 樣本的預測標簽。
返回值:
c
: float- 完整性得分,在0到1之間,值越大表示聚類越完整,即在理想情況下,一個真實類別內的所有樣本都會被分到同一個簇中。
內部數學形式:
給定一組樣本的真實標簽 CCC 和預測的聚類標簽 KKK,完整性的計算基于條件熵的概念:
H(K∣C)=?∑c∈C∑k∈K∣kc∣nlog?(∣kc∣∣c∣) H(K|C) = -\sum_{c \in C} \sum_{k \in K} \frac{|k_c|}{n} \log \left( \frac{|k_c|}{|c|} \right) H(K∣C)=?c∈C∑?k∈K∑?n∣kc?∣?log(∣c∣∣kc?∣?)
其中,
- CCC 是真實類別集合。
- KKK 是聚類集合。
- ∣kc∣|k_c|∣kc?∣ 表示同時屬于聚類 kkk 和真實類別 ccc 的樣本數。
- ∣c∣|c|∣c∣ 表示屬于真實類別 ccc 的樣本總數。
- nnn 是樣本總數。
然后,完整性得分 ccc 定義為:
c=1?H(K∣C)H(K) c = 1 - \frac{H(K|C)}{H(K)} c=1?H(K)H(K∣C)?
其中,
- H(K)H(K)H(K) 是根據預測標簽計算的熵,定義為 H(K)=?∑k∈K∣k∣nlog?(∣k∣n)H(K) = -\sum_{k \in K} \frac{|k|}{n} \log \left(\frac{|k|}{n}\right)H(K)=?∑k∈K?n∣k∣?log(n∣k∣?),這里 ∣k∣|k|∣k∣ 表示屬于聚類 kkk 的樣本數。
特點:
- 如果對于所有的 c∈Cc \in Cc∈C 都有 H(Kc)=0H(K_c) = 0H(Kc?)=0,那么 c=1c = 1c=1,意味著聚類完全完整。
- 完整性不考慮簇的數量或大小,因此即使所有樣本都被歸為一類,只要這一類內包含了所有同屬一個實際類別的樣本,完整性得分也可以很高。
completeness_score
函數主要用于評估聚類算法輸出的質量,特別是在關注確保每個真實類別內的樣本都能被正確分類到同一簇的場景中非常有用。
使用示例
import numpy as np
from sklearn.metrics import completeness_score, homogeneity_score, v_measure_score
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs# --- 示例 1: 完美完整性 ---
print("=== 示例 1: 完美完整性 (每個真實類別的樣本都在同一個聚類中) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 聚類結果: 每個真實類別的樣本都在同一個聚類中
labels_pred_complete = [0, 0, 1, 1, 2, 2]complete = completeness_score(labels_true, labels_pred_complete)
homo = homogeneity_score(labels_true, labels_pred_complete)
v_measure = v_measure_score(labels_true, labels_pred_complete)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_complete}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 完整性=1.0,因為每個真實類別的樣本都被正確地聚集在了一起。")
print()# --- 示例 2: 完全不完整 (每個類別的樣本都被打散) ---
print("=== 示例 2: 完全不完整 (每個類別的樣本都被打散) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 聚類結果: 每個真實類別的樣本都被分到了不同的聚類中
labels_pred_scattered = [0, 1, 0, 1, 0, 1]complete = completeness_score(labels_true, labels_pred_scattered)
homo = homogeneity_score(labels_true, labels_pred_scattered)
v_measure = v_measure_score(labels_true, labels_pred_scattered)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_scattered}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 完整性=0.0,因為每個真實類別的樣本都被打散到了不同的聚類中。")
print()# --- 示例 3: 部分完整性 ---
print("=== 示例 3: 部分完整性 (部分類別是完整的) ===")labels_true = [0, 0, 0, 1, 1, 1, 2, 2, 2]
# 聚類結果:
# - 類別0的樣本: 聚類0 -> 完整
# - 類別1和2的樣本: 都在聚類1 -> 不完整 (被合并了)
labels_pred_partial = [0, 0, 0, 1, 1, 1, 1, 1, 1]complete = completeness_score(labels_true, labels_pred_partial)
homo = homogeneity_score(labels_true, labels_pred_partial)
v_measure = v_measure_score(labels_true, labels_pred_partial)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_partial}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 完整性=1.0 (因為每個真實類別的樣本都在一個聚類里),")
print(" 但同質性<1.0 (因為聚類1包含了類別1和2的樣本)。")
print()# --- 示例 4: 欠分割 (高完整性,低同質性) ---
print("=== 示例 4: 欠分割 (高完整性,低同質性) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 聚類結果: 將所有樣本都分到了一個聚類中
labels_pred_underclustered = [0, 0, 0, 0, 0, 0]complete = completeness_score(labels_true, labels_pred_underclustered)
homo = homogeneity_score(labels_true, labels_pred_underclustered)
v_measure = v_measure_score(labels_true, labels_pred_underclustered)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_underclustered}")
print(f"完整性 (Completeness): {complete:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"V-Measure: {v_measure:.6f}")
print("解釋: 完整性=1.0 (所有真實類別的樣本都在聚類0中),")
print(" 但同質性=0.0 (聚類0包含了所有真實類別的樣本,非常不純)。")
print()# --- 示例 5: 實際應用 - 用 K-Means 聚類 ---
print("=== 示例 5: 實際應用 - K-Means 聚類評估 ===")# 生成一個簡單的聚類數據集 (3個簇)
X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=42)# 應用 K-Means 聚類
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
y_pred = kmeans.fit_predict(X)# 計算完整性、同質性和 V-Measure
complete_kmeans = completeness_score(y_true, y_pred)
homo_kmeans = homogeneity_score(y_true, y_pred)
v_measure_kmeans = v_measure_score(y_true, y_pred)print(f"K-Means 聚類結果 (n_clusters=3):")
print(f"完整性 (Completeness): {complete_kmeans:.6f}")
print(f"同質性 (Homogeneity): {homo_kmeans:.6f}")
print(f"V-Measure: {v_measure_kmeans:.6f}")
print(f"注: 所有指標都接近 1.0,說明 K-Means 在這個數據集上聚類效果極好。")
print()# --- 可視化 ---
plt.figure(figsize=(15, 5))# 子圖 1: 真實標簽
plt.subplot(1, 3, 1)
scatter1 = plt.scatter(X[:, 0], X[:, 1], c=y_true, cmap='plasma', alpha=0.7)
plt.title('真實標簽')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter1)# 子圖 2: K-Means 聚類結果 (完整性)
plt.subplot(1, 3, 2)
scatter2 = plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='plasma', alpha=0.7)
plt.title(f'K-Means 聚類 (完整性={complete_kmeans:.3f})')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter2)# 子圖 3: K-Means 聚類結果 (同質性)
plt.subplot(1, 3, 3)
scatter3 = plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='plasma', alpha=0.7)
plt.title(f'K-Means 聚類 (同質性={homo_kmeans:.3f})')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter3)plt.tight_layout()
plt.show()# --- 補充: 完整性、同質性與 V-Measure 的關系 ---
print("=== 補充: 完整性、同質性與 V-Measure 的關系 ===")
print("真實標簽:", y_true[:10]) # 只顯示前10個
print("K-Means預測:", y_pred[:10])print(f"完整性 (Completeness): {complete_kmeans:.3f}")
print(f"同質性 (Homogeneity): {homo_kmeans:.3f}")
print(f"V-Measure: {v_measure_kmeans:.3f}")print("\n解釋:")
print("1. 完整性 (Completeness): 關注類別的'完整性'。")
print("2. 同質性 (Homogeneity): 關注聚類的'純凈度'。")
print("3. V-Measure: 是完整性和同質性的調和平均數,")
print(" V = 2 * (completeness * homogeneity) / (completeness + homogeneity)")
print(" 它提供了一個綜合性的單一分數。")
print("4. 理想聚類: 完整性和同質性都應接近 1.0。")
結果分析
=== 示例 1: 完美完整性 (每個真實類別的樣本都在同一個聚類中) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 0, 1, 1, 2, 2]
完整性 (Completeness): 1.000000
同質性 (Homogeneity): 1.000000
V-Measure: 1.000000
解釋: 完整性=1.0,因為每個真實類別的樣本都被正確地聚集在了一起。=== 示例 2: 完全不完整 (每個類別的樣本都被打散) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 1, 0, 1, 0, 1]
完整性 (Completeness): 0.000000
同質性 (Homogeneity): 0.000000
V-Measure: 0.000000
解釋: 完整性=0.0,因為每個真實類別的樣本都被打散到了不同的聚類中。=== 示例 3: 部分完整性 (部分類別是完整的) ===
真實標簽: [0, 0, 0, 1, 1, 1, 2, 2, 2]
聚類標簽: [0, 0, 0, 1, 1, 1, 1, 1, 1]
完整性 (Completeness): 1.000000
同質性 (Homogeneity): 0.500000
V-Measure: 0.666667
解釋: 完整性=1.0 (因為每個真實類別的樣本都在一個聚類里),但同質性<1.0 (因為聚類1包含了類別1和2的樣本)。=== 示例 4: 欠分割 (高完整性,低同質性) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 0, 0, 0, 0, 0]
完整性 (Completeness): 1.000000
同質性 (Homogeneity): 0.000000
V-Measure: 0.000000
解釋: 完整性=1.0 (所有真實類別的樣本都在聚類0中),但同質性=0.0 (聚類0包含了所有真實類別的樣本,非常不純)。=== 示例 5: 實際應用 - K-Means 聚類評估 ===
K-Means 聚類結果 (n_clusters=3):
完整性 (Completeness): 1.000000
同質性 (Homogeneity): 1.000000
V-Measure: 1.000000
注: 所有指標都接近 1.0,說明 K-Means 在這個數據集上聚類效果極好。=== 補充: 完整性、同質性與 V-Measure 的關系 ===
真實標簽: [0 1 2 0 1 2 0 1 2 0]
K-Means預測: [1 2 0 1 2 0 1 2 0 1]
完整性 (Completeness): 1.000
同質性 (Homogeneity): 1.000
V-Measure: 1.000解釋:
1. 完整性 (Completeness): 關注類別的'完整性'。
2. 同質性 (Homogeneity): 關注聚類的'純凈度'。
3. V-Measure: 是完整性和同質性的調和平均數,V = 2 * (completeness * homogeneity) / (completeness + homogeneity)它提供了一個綜合性的單一分數。
4. 理想聚類: 完整性和同質性都應接近 1.0。
關鍵點總結
-
完整性:
completeness_score
的核心是衡量聚類的“完整性”。它回答的問題是:“同一種東西是否都被分到了同一個聚類里?” -
取值范圍:
[0, 1]
,越接近 1 越好。 -
與
homogeneity_score
的關系:- 完整性 (Completeness): 關注真實類別的完整性。
- 同質性 (Homogeneity): 關注聚類簇的純凈度。
- 兩者是互補的。一個完美的聚類應該同時具有高完整性和高同質性。
-
與
v_measure_score
的關系:- V-Measure 是完整性和同質性的調和平均數。
V = 2 * (completeness * homogeneity) / (completeness + homogeneity)
- 它提供了一個綜合性的單一分數,平衡了完整性和純凈度。
-
缺點: 單獨使用完整性可能會被“欠分割”(under-segmentation)所欺騙。將所有樣本都分到一個聚類中,完整性會是 1.0,但這顯然不是有意義的聚類。
-
何時使用:
- 當你特別關心聚類結果是否能將屬于同一類別的樣本聚集在一起時。
- 通常與
homogeneity_score
和v_measure_score
一起使用,以獲得對聚類質量的全面評估。 - 在調試聚類算法時,如果完整性很低,說明算法可能把同一類別的樣本分到了不同的簇里。
總而言之,completeness_score
是評估聚類質量的重要指標之一,它從“完整性”的角度提供了有價值的洞察。但要記住,它只是拼圖的一塊,通常需要結合其他指標(尤其是 homogeneity_score
)來全面評價一個聚類算法的性能。
函數:v_measure_score
簡介:
V-measure是一個用于衡量聚類結果質量的度量標準,它是同質性和完整性的調和平均數。該分數旨在解決僅使用同質性或完整性作為單一指標時可能存在的偏差問題,并提供了關于聚類效果更全面的視角。
參數:
labels_true
: array-like of shape (n_samples,)- 樣本的真實類別標簽。
labels_pred
: array-like of shape (n_samples,)- 樣本的預測聚類標簽。
返回值:
v_measure
: float- V-measure得分,取值范圍從0到1之間,其中1表示最佳匹配。
內部數學形式:
給定一組樣本的真實標簽 CCC 和預測的聚類標簽 KKK,V-measure通過以下公式計算:
v=2?(h?c)(h+c) v = 2 \cdot \frac{(h \cdot c)}{(h + c)} v=2?(h+c)(h?c)?
其中,
- hhh 是同質性(homogeneity)得分,定義為不包含來自不同真實類別的成員在一個簇中。
- ccc 是完整性(completeness)得分,定義為屬于同一真實類別的所有樣本都被分配到了相同的簇中。
同質性和完整性的計算基于條件熵的概念:
同質性 hhh 定義為:
h=1?H(C∣K)H(C)
h = 1 - \frac{H(C|K)}{H(C)}
h=1?H(C)H(C∣K)?
完整性 ccc 定義為:
c=1?H(K∣C)H(K)
c = 1 - \frac{H(K|C)}{H(K)}
c=1?H(K)H(K∣C)?
其中,
- H(C∣K)H(C|K)H(C∣K) 表示在已知預測簇的情況下,真實類別的條件熵。
- H(C)H(C)H(C) 是真實類別的熵。
- H(K∣C)H(K|C)H(K∣C) 表示在已知真實類別的情況下,預測簇的條件熵。
- H(K)H(K)H(K) 是預測簇的熵。
特點:
- V-measure是對稱的,即交換
labels_true
和labels_pred
不會改變得分。 - 得分不受簇命名的影響,只與簇之間的對應關系有關。
- 當且僅當同質性和完整性都達到最大值1時,V-measure得分為1,表示聚類結果完美地匹配真實標簽。
v_measure_score
函數主要用于評估聚類算法輸出的質量,在需要同時考慮同質性和完整性的情況下非常有用。
使用示例
import numpy as np
from sklearn.metrics import v_measure_score, homogeneity_score, completeness_score
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs# --- 示例 1: 完美聚類 ---
print("=== 示例 1: 完美聚類 (同質性和完整性都為1) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 聚類結果: 完美匹配
labels_pred_perfect = [0, 0, 1, 1, 2, 2]v_measure = v_measure_score(labels_true, labels_pred_perfect)
homo = homogeneity_score(labels_true, labels_pred_perfect)
complete = completeness_score(labels_true, labels_pred_perfect)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_perfect}")
print(f"V-Measure: {v_measure:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print("解釋: V-Measure=1.0,因為同質性和完整性都=1.0。")
print()# --- 示例 2: 完全不相關 (隨機) ---
print("=== 示例 2: 完全不相關 (隨機聚類) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 隨機的聚類結果
labels_pred_random = [0, 1, 2, 0, 1, 2]v_measure = v_measure_score(labels_true, labels_pred_random)
homo = homogeneity_score(labels_true, labels_pred_random)
complete = completeness_score(labels_true, labels_pred_random)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_random}")
print(f"V-Measure: {v_measure:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print("解釋: V-Measure 接近 0,因為同質性和完整性都很低。")
print()# --- 示例 3: 高同質性,低完整性 (過度分割) ---
print("=== 示例 3: 高同質性,低完整性 (過度分割) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 每個樣本一個聚類
labels_pred_over = [0, 1, 2, 3, 4, 5]v_measure = v_measure_score(labels_true, labels_pred_over)
homo = homogeneity_score(labels_true, labels_pred_over)
complete = completeness_score(labels_true, labels_pred_over)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_over}")
print(f"V-Measure: {v_measure:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print("解釋: V-Measure=0.0,因為完整性=0.0,即使同質性=1.0。")
print(" 調和平均數被較低的值拉低。")
print()# --- 示例 4: 高完整性,低同質性 (欠分割) ---
print("=== 示例 4: 高完整性,低同質性 (欠分割) ===")labels_true = [0, 0, 1, 1, 2, 2]
# 所有樣本一個聚類
labels_pred_under = [0, 0, 0, 0, 0, 0]v_measure = v_measure_score(labels_true, labels_pred_under)
homo = homogeneity_score(labels_true, labels_pred_under)
complete = completeness_score(labels_true, labels_pred_under)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_under}")
print(f"V-Measure: {v_measure:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print("解釋: V-Measure=0.0,因為同質性=0.0,即使完整性=1.0。")
print(" 調和平均數被較低的值拉低。")
print()# --- 示例 5: 部分匹配 ---
print("=== 示例 5: 部分匹配 (部分同質,部分完整) ===")labels_true = [0, 0, 0, 1, 1, 1, 2, 2, 2]
# 聚類結果: 類別0分對了,類別1和2被合并
labels_pred_partial = [0, 0, 0, 1, 1, 1, 1, 1, 1]v_measure = v_measure_score(labels_true, labels_pred_partial)
homo = homogeneity_score(labels_true, labels_pred_partial)
complete = completeness_score(labels_true, labels_pred_partial)print(f"真實標簽: {labels_true}")
print(f"聚類標簽: {labels_pred_partial}")
print(f"V-Measure: {v_measure:.6f}")
print(f"同質性 (Homogeneity): {homo:.6f}")
print(f"完整性 (Completeness): {complete:.6f}")
print("解釋: V-Measure 在 0 和 1 之間,反映了部分匹配的情況。")
print()# --- 示例 6: 實際應用 - 用 K-Means 聚類 ---
print("=== 示例 6: 實際應用 - K-Means 聚類評估 ===")# 生成一個簡單的聚類數據集 (3個簇)
X, y_true = make_blobs(n_samples=300, centers=3, cluster_std=0.60, random_state=42)# 應用 K-Means 聚類
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
y_pred = kmeans.fit_predict(X)# 計算 V-Measure, 同質性, 完整性
v_measure_kmeans = v_measure_score(y_true, y_pred)
homo_kmeans = homogeneity_score(y_true, y_pred)
complete_kmeans = completeness_score(y_true, y_pred)print(f"K-Means 聚類結果 (n_clusters=3):")
print(f"V-Measure: {v_measure_kmeans:.6f}")
print(f"同質性 (Homogeneity): {homo_kmeans:.6f}")
print(f"完整性 (Completeness): {complete_kmeans:.6f}")
print(f"注: 所有指標都接近 1.0,說明 K-Means 在這個數據集上聚類效果極好。")
print()# --- 可視化 ---
plt.figure(figsize=(15, 5))# 子圖 1: 真實標簽
plt.subplot(1, 3, 1)
scatter1 = plt.scatter(X[:, 0], X[:, 1], c=y_true, cmap='cividis', alpha=0.7)
plt.title('真實標簽')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter1)# 子圖 2: K-Means 聚類結果 (V-Measure)
plt.subplot(1, 3, 2)
scatter2 = plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='cividis', alpha=0.7)
plt.title(f'K-Means 聚類 (V-Measure={v_measure_kmeans:.3f})')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter2)# 子圖 3: K-Means 聚類結果 (同質性 vs 完整性)
plt.subplot(1, 3, 3)
scatter3 = plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='cividis', alpha=0.7)
plt.title(f'K-Means 聚類\n(同質性={homo_kmeans:.3f}, 完整性={complete_kmeans:.3f})')
plt.xlabel('特征 1')
plt.ylabel('特征 2')
plt.colorbar(scatter3)plt.tight_layout()
plt.show()# --- 補充: V-Measure 與 AMI 的關系 ---
print("=== 補充: V-Measure 與 AMI 的關系 ===")
from sklearn.metrics import adjusted_mutual_info_scoreami_kmeans = adjusted_mutual_info_score(y_true, y_pred, average_method='geometric')print(f"V-Measure: {v_measure_kmeans:.6f}")
print(f"AMI (geometric): {ami_kmeans:.6f}")
print("解釋: V-Measure 等于使用 'geometric' 歸一化方法的調整互信息分數 (AMI)。")
print(" sklearn 的 v_measure_score 是 AMI 的一個特例。")
結果分析
=== 示例 1: 完美聚類 (同質性和完整性都為1) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 0, 1, 1, 2, 2]
V-Measure: 1.000000
同質性 (Homogeneity): 1.000000
完整性 (Completeness): 1.000000
解釋: V-Measure=1.0,因為同質性和完整性都=1.0。=== 示例 2: 完全不相關 (隨機聚類) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 1, 2, 0, 1, 2]
V-Measure: 0.000000
同質性 (Homogeneity): 0.000000
完整性 (Completeness): 0.000000
解釋: V-Measure 接近 0,因為同質性和完整性都很低。=== 示例 3: 高同質性,低完整性 (過度分割) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 1, 2, 3, 4, 5]
V-Measure: 0.000000
同質性 (Homogeneity): 1.000000
完整性 (Completeness): 0.000000
解釋: V-Measure=0.0,因為完整性=0.0,即使同質性=1.0。調和平均數被較低的值拉低。=== 示例 4: 高完整性,低同質性 (欠分割) ===
真實標簽: [0, 0, 1, 1, 2, 2]
聚類標簽: [0, 0, 0, 0, 0, 0]
V-Measure: 0.000000
同質性 (Homogeneity): 0.000000
完整性 (Completeness): 1.000000
解釋: V-Measure=0.0,因為同質性=0.0,即使完整性=1.0。調和平均數被較低的值拉低。=== 示例 5: 部分匹配 (部分同質,部分完整) ===
真實標簽: [0, 0, 0, 1, 1, 1, 2, 2, 2]
聚類標簽: [0, 0, 0, 1, 1, 1, 1, 1, 1]
V-Measure: 0.666667
同質性 (Homogeneity): 0.500000
完整性 (Completeness): 1.000000
解釋: V-Measure 在 0 和 1 之間,反映了部分匹配的情況。=== 示例 6: 實際應用 - K-Means 聚類評估 ===
K-Means 聚類結果 (n_clusters=3):
V-Measure: 1.000000
同質性 (Homogeneity): 1.000000
完整性 (Completeness): 1.000000
注: 所有指標都接近 1.0,說明 K-Means 在這個數據集上聚類效果極好。=== 補充: V-Measure 與 AMI 的關系 ===
V-Measure: 1.000000
AMI (geometric): 1.000000
解釋: V-Measure 等于使用 'geometric' 歸一化方法的調整互信息分數 (AMI)。sklearn 的 v_measure_score 是 AMI 的一個特例。
關鍵點總結
-
綜合性:
v_measure_score
的核心價值在于它將homogeneity_score
和completeness_score
這兩個互補但都重要的指標合并成一個單一的分數。 -
調和平均數: 它使用調和平均數(Harmonic Mean)來計算。調和平均數對極小值非常敏感。這意味著,即使一個指標(如同質性)非常高,如果另一個指標(如完整性)很低,V-Measure 也會被拉得很低。這確保了只有當兩個方面都表現良好時,V-Measure 才會高。
-
取值范圍:
[0, 1]
,越接近 1 越好。 -
與
homogeneity_score
和completeness_score
的關系:- V-Measure 是這兩個指標的調和平均數。
V = 2 * (homogeneity * completeness) / (homogeneity + completeness)
- 它提供了一個平衡的評估,避免了被單一指標(如高同質性或高完整性)的“假象”所誤導。
-
與
adjusted_mutual_info_score
(AMI) 的關系:- V-Measure 實際上等于使用
'geometric'
歸一化方法的adjusted_mutual_info_score
。 - 在 sklearn 中,
v_measure_score
函數是adjusted_mutual_info_score(average_method='geometric')
的一個別名或特例。
- V-Measure 實際上等于使用
-
何時使用:
- 當你需要一個單一的、綜合性的分數來評估聚類質量時。
- 當你想同時考慮聚類的“純凈度”和“完整性”,并且希望避免被極端情況(如過度分割或欠分割)所欺騙時。
- 它是評估聚類算法性能的推薦指標之一,因為它比單獨使用同質性或完整性更穩健。
總而言之,v_measure_score
是一個強大且實用的聚類評估工具。它通過調和平均數巧妙地結合了同質性和完整性,提供了一個既能反映聚類純凈度又能反映類別完整性的綜合評分。在實際應用中,它通常是比單獨使用同質性或完整性更優的選擇。