《sklearn机器学习——聚类性能指数》同质性,完整性和 V-measure
函数: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∈Cn∣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∈Kn∣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
是一个强大且实用的聚类评估工具。它通过调和平均数巧妙地结合了同质性和完整性,提供了一个既能反映聚类纯净度又能反映类别完整性的综合评分。在实际应用中,它通常是比单独使用同质性或完整性更优的选择。