adjusted_rand_score用于评估聚类结果与真实标签的一致性,取值范围[-1,1],1表示完全一致,0表示等价于随机划分;要求两组整数标签长度一致、无NaN、为一维数组,对簇名顺序不敏感。

调整兰德系数(Adjusted Rand Index, ARI)在 scikit-learn 中直接可用,但必须确保真实标签和聚类结果标签都为整数数组且长度一致;否则会报 ValueError: Input contains NaN, infinity or a value too large for dtype('float64') 或 labels_true and labels_pred must have same size。
用 adjusted_rand_score 函数计算 ARI
scikit-learn 提供了 sklearn.metrics.adjusted_rand_score,它接受两个一维数组:真实类别标签 labels_true 和模型预测的聚类标签 labels_pred。该函数不关心标签具体取值(如 0/1/2 或 5/10/15),只看划分一致性。
常见错误现象包括:
- 传入
list嵌套结构(如[[0], [1], [0]])而非一维数组 —— 需用np.ravel()或.flatten()展平 - 聚类结果含
NaN或None(例如某些 DBSCAN 把噪声点标为 -1 是合法的,但若误填np.nan就会报错) - 使用
fit_predict返回的是ndarray,但真实标签是pandas.Series,索引未对齐导致长度看似一致实则错位
示例:
立即学习“Python免费学习笔记(深入)”;
from sklearn.metrics import adjusted_rand_score import numpy as np <p>labels_true = [0, 0, 1, 1, 2, 2] labels_pred = [0, 0, 1, 1, 1, 1] # 比如 KMeans 把后两类全分进同一簇</p><p>score = adjusted_rand_score(labels_true, labels_pred) print(score) # 输出类似 0.24...
ARI 对标签编码方式不敏感,但对空簇和噪声点很敏感
adjusted_rand_score 基于配对计数(pair counting),所以只要两个标签序列的“哪些样本被分到同一组”逻辑一致,分数就相同。这意味着:
-
[0, 0, 1, 1]和[5, 5, 99, 99]与真实标签比,ARI 完全一样 - DBSCAN 返回的
-1表示噪声点,这是合法标签值,会被正常计入计算 —— 无需提前过滤或替换 - 如果某簇完全没样本(比如 KMeans 设
n_clusters=4但实际只产生 3 个非空簇),不影响 ARI,因为函数只看已有标签的配对关系
但注意:若 labels_pred 全是同一个值(如全为 0),而 labels_true 有多个类,则 ARI 会是负数(表示比随机划分还差),这是正常行为,不是 bug。
和 homogeneity_score、completeness_score 的关键区别
ARI 是对称指标,不偏向“真实标签”或“预测标签”哪一方;而 homogeneity_score 要求每个簇纯度高,completeness_score 要求同类样本尽量不分散 —— 它们都不做随机性校正,数值范围是 [0,1],而 ARI 是 [-1,1],0 表示等价于随机划分。
典型使用场景:
- 比较不同聚类算法在同一数据集上的效果(如 KMeans vs AgglomerativeClustering)
- 调参时评估
n_clusters取值 —— 注意 ARI 在真实类数附近常出现峰值,但未必严格对应 - 当真实标签存在但不完全可靠(如人工标注有少量错误),ARI 比纯精度更鲁棒,因它关注样本对关系而非逐点匹配
性能影响很小:adjusted_rand_score 时间复杂度是 O(n),n 是样本数;内部用稀疏矩阵计数,10⁵ 级样本也能秒级完成。
最容易被忽略的一点:ARI 无法处理多标签分类或层次化聚类输出;如果你的 labels_pred 是树状结构或每个样本属于多个簇,得先转换成单标签形式(如取最大概率簇),否则会直接报错或结果无意义。


















