在聚类性能评估中考虑随机因素

Machine LearningMachine LearningBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

本实验探讨均匀分布的随机标签对某些聚类评估指标行为的影响。聚类算法从根本上来说是无监督学习方法,而评估指标则利用“有监督”的真实信息来量化所得聚类的质量。然而,未经调整的聚类评估指标可能会产生误导,因为对于细粒度标签(可能完全是随机的),它们会输出较大的值。因此,只有经过调整的指标才能安全地用作共识指标,以评估聚类算法在数据集的各种重叠子样本上对于给定k值的平均稳定性。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签页,以访问Jupyter Notebook进行练习。

有时,你可能需要等待几秒钟让Jupyter Notebook完成加载。由于Jupyter Notebook的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,随时向Labby提问。课程结束后提供反馈,我们会及时为你解决问题。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills ml/sklearn -.-> lab-49059{{"在聚类性能评估中考虑随机因素"}} end

定义用于评估的指标列表

我们首先定义一个用于评估聚类算法的指标列表。这类指标的示例包括V度量、兰德指数、调整兰德指数(ARI)、互信息(MI)、归一化互信息(NMI)和调整互信息(AMI)。

from sklearn import metrics

score_funcs = [
    ("V-measure", metrics.v_measure_score),
    ("Rand index", metrics.rand_score),
    ("ARI", metrics.adjusted_rand_score),
    ("MI", metrics.mutual_info_score),
    ("NMI", metrics.normalized_mutual_info_score),
    ("AMI", metrics.adjusted_mutual_info_score),
]

实验1 - 固定真实标签并增加聚类数量

我们创建均匀分布的随机标签,并使用 random_labels 函数创建一组固定的真实标签(labels_a),这些标签分布在 n_classes 中,然后对几组随机“预测”的标签(labels_b)进行评分,以评估给定指标在给定 n_clusters 时的可变性。

rng = np.random.RandomState(0)

def random_labels(n_samples, n_classes):
    return rng.randint(low=0, high=n_classes, size=n_samples)

def fixed_classes_uniform_labelings_scores(
    score_func, n_samples, n_clusters_range, n_classes, n_runs=5
):
    scores = np.zeros((len(n_clusters_range), n_runs))
    labels_a = random_labels(n_samples=n_samples, n_classes=n_classes)

    for i, n_clusters in enumerate(n_clusters_range):
        for j in range(n_runs):
            labels_b = random_labels(n_samples=n_samples, n_classes=n_clusters)
            scores[i, j] = score_func(labels_a, labels_b)
    return scores

绘制实验1的结果

我们使用 matplotlibseaborn 库来绘制第一个实验的结果。当 n_clusters > n_classes 时,兰德指数趋于饱和。其他未经调整的指标,如V度量,显示出聚类数量与样本数量之间的线性关系。经过机会调整的指标,如ARI和AMI,显示出一些围绕平均分数0.0的随机变化,与样本数量和聚类数量无关。

import matplotlib.pyplot as plt
import seaborn as sns

n_samples = 1000
n_classes = 10
n_clusters_range = np.linspace(2, 100, 10).astype(int)
plots = []
names = []

sns.color_palette("colorblind")
plt.figure(1)

for marker, (score_name, score_func) in zip("d^vx.,", score_funcs):
    scores = fixed_classes_uniform_labelings_scores(
        score_func, n_samples, n_clusters_range, n_classes=n_classes
    )
    plots.append(
        plt.errorbar(
            n_clusters_range,
            scores.mean(axis=1),
            scores.std(axis=1),
            alpha=0.8,
            linewidth=1,
            marker=marker,
        )[0]
    )
    names.append(score_name)

plt.title(
    "Clustering measures for random uniform labeling\n"
    f"against reference assignment with {n_classes} classes"
)
plt.xlabel(f"Number of clusters (Number of samples is fixed to {n_samples})")
plt.ylabel("Score value")
plt.ylim(bottom=-0.05, top=1.05)
plt.legend(plots, names, bbox_to_anchor=(0.5, 0.5))
plt.show()

实验2 - 变化类别的数量和聚类的数量

在本节中,我们定义一个类似的函数,该函数使用多个指标对两个均匀分布的随机标签进行评分。在这种情况下,对于 n_clusters_range 中的每个可能值,类别数量和分配的聚类数量是匹配的。

def uniform_labelings_scores(score_func, n_samples, n_clusters_range, n_runs=5):
    scores = np.zeros((len(n_clusters_range), n_runs))

    for i, n_clusters in enumerate(n_clusters_range):
        for j in range(n_runs):
            labels_a = random_labels(n_samples=n_samples, n_classes=n_clusters)
            labels_b = random_labels(n_samples=n_samples, n_classes=n_clusters)
            scores[i, j] = score_func(labels_a, labels_b)
    return scores

绘制实验2的结果

我们使用 matplotlib 库绘制第二个实验的结果。我们观察到与第一个实验类似的结果:经过机会调整的指标始终接近零,而其他指标在标签粒度更细时往往会变大。随着聚类数量接近用于计算该指标的样本总数,随机标签的平均V度量显著增加。

n_samples = 100
n_clusters_range = np.linspace(2, n_samples, 10).astype(int)

plt.figure(2)

plots = []
names = []

for marker, (score_name, score_func) in zip("d^vx.,", score_funcs):
    scores = uniform_labelings_scores(score_func, n_samples, n_clusters_range)
    plots.append(
        plt.errorbar(
            n_clusters_range,
            np.median(scores, axis=1),
            scores.std(axis=1),
            alpha=0.8,
            linewidth=2,
            marker=marker,
        )[0]
    )
    names.append(score_name)

plt.title(
    "Clustering measures for 2 random uniform labelings\nwith equal number of clusters"
)
plt.xlabel(f"Number of clusters (Number of samples is fixed to {n_samples})")
plt.ylabel("Score value")
plt.legend(plots, names)
plt.ylim(bottom=-0.05, top=1.05)
plt.show()

总结

本实验探讨了均匀分布的随机标签对一些聚类评估指标行为的影响。结果表明,未经调整的聚类评估指标可能会产生误导,只有经过调整的指标才能安全地用作共识指标,以评估聚类算法在数据集的各种重叠子样本上对于给定k值的平均稳定性。