1. 无监督聚类评价最容易被忽视的一环做聚类分析的人十个里有八个把精力花在算法选型和参数调优上剩下两个在纠结 K 值怎么定。真正等到聚类跑完面对一堆簇标签能一口气把评价指标讲清楚的人少之又少。监督学习有准确率、F1逃不掉也躲不开聚类这东西没有 ground truth 的时候还好说一旦需要评估聚类质量很多人就直接懵了——RI 是什么ARI 又是什么MI、NMI 跟它们什么关系哪个指标对簇数量敏感哪个指标适合分布极不均衡的数据这篇文章就把这些指标一次性讲透。我会从每个指标的计算逻辑、直观含义、适用场景、代码实现四个维度展开最后补一段关于“什么时候该用哪个指标”的实操建议。文章里会用大量可复现的小例子方便你动手验证而不是停留在背公式的层面。先说结论方便你后面带着问题看RIRand Index最基础的聚类相似度指标计算简单但对随机划分的惩罚不够容易虚高。ARIAdjusted Rand Index对 RI 做随机校正消除了“运气好”带来的虚高是实际项目中最常用的指标之一。MIMutual Information基于信息论的指标衡量两个划分共享的信息量数值本身受簇大小影响。NMINormalized Mutual Information把 MI 归一化到 0~1 之间便于跨数据集比较是论文和工业界的常客。这四者的共同点是它们都需要一个“参考划分”也就是某种形式的 ground truth 或外部标签。所以严格来说它们属于外部聚类评价指标。你要做的是“无监督聚类”但评价过程本身其实是有监督的——用真实标签去校验聚类结果。这个逻辑如果不理清楚后面一切都白搭。2. RI 的核心逻辑把聚类结果当成“配对投票”2.1 RI 到底在算什么RI 的全称是 Rand Index1960 年代由 William M. Rand 提出。它的核心思想很朴素把聚类结果和真实标签放在一起看它们对“数据点两两之间的关系”判断得有多一致。什么叫“数据点两两之间的关系”假设有 N 个样本两两组合一共有 C(N,2) 对。对每一对样本聚类结果和真实标签都有两种可能的判断正例两个样本属于同一个簇聚类视角或属于同一个类别真实标签视角。负例两个样本不属于同一个簇或不属于同一个类别。于是每一对样本都存在四种情况情况聚类判断真实标签含义TP同一簇同一类聚类和真实一致且是“合并正确”TN不同簇不同类聚类和真实一致且是“分开正确”FP同一簇不同类聚类把不同类别的样本错误地合并了FN不同簇同一类聚类把同一类别的样本错误地分开了注意这里借用的是分类问题里的混淆矩阵术语但含义不完全一样。分类问题里 TP/TN/FP/FN 是针对单个样本的而聚类评价里这四个量是针对“样本对”的。RI 的公式就是[ RI \frac{TP TN}{TP TN FP FN} \frac{TP TN}{C(N,2)} ]说白了RI 就是“聚类结果和真实标签在所有样本对中意见一致的比例”。2.2 一个手算例子假设有 6 个样本真实标签是[ y_{true} [0, 0, 1, 1, 2, 2] ]聚类结果比如 KMeans 跑出来的是[ y_{pred} [0, 0, 0, 1, 1, 2] ]也就是样本 0、1、2 被聚到一起样本 3、4 被聚到一起样本 5 单独一个簇。总样本对数C(6,2) 15。现在逐对判断(0,1)真实同属 0聚类同属 0 → TP(0,2)真实 0 和 1 不同类聚类都属于 0 → FP(0,3)真实不同聚类不同 → TN(0,4)真实不同聚类不同 → TN(0,5)真实不同聚类不同 → TN(1,2)真实 0 和 1 不同类聚类都属于 0 → FP(1,3)真实不同聚类不同 → TN(1,4)真实不同聚类不同 → TN(1,5)真实不同聚类不同 → TN(2,3)真实 1 和 1 不同真实中样本2属于类1样本3属于类1等等这里需要重新整理我重新整理一下避免自己把自己绕晕。真实标签样本 0→0样本 1→0样本 2→1样本 3→1样本 4→2样本 5→2。 预测标签样本 0→0样本 1→0样本 2→0样本 3→1样本 4→1样本 5→2。逐对判断样本对真实同簇预测同簇结果(0,1)是是TP(0,2)否是FP(0,3)否否TN(0,4)否否TN(0,5)否否TN(1,2)否是FP(1,3)否否TN(1,4)否否TN(1,5)否否TN(2,3)是否FN(2,4)否否TN(2,5)否否TN(3,4)否是FP(3,5)否否TN(4,5)是否FN统计TP1TN10FP3FN2。[ RI \frac{1 10}{15} \frac{11}{15} \approx 0.7333 ]也就是说聚类结果和真实标签在 15 对样本中有 11 对判断一致占比约 73.33%。对于这个简单例子这个结果还算合理。2.3 RI 的“虚高陷阱”RI 最大的问题在于即使聚类结果是随机瞎分的RI 也可能不低。举个例子样本量 N100真实标签是两类各 50 个。如果你把 100 个样本完全随机地分成两个簇RI 的期望值不会接近 0而会接近 0.5 左右。更极端的当真实类别本身极不均衡比如 99 个 A 类和 1 个 B 类那么“把所有样本归为一类”这种毫无意义的聚类RI 也能拿到 0.98 以上因为大多数样本对都是 TN你只要“不犯错”就赢了而“全部归为一类”在 TN 上确实不犯错。所以碰到类别极不均衡、簇数量很多、或者样本量很大的场景RI 几乎不具备参考价值。它更适合作为教学工具和“基线指标”而不适合直接作为模型选型的依据。3. ARI给 RI 装上“随机校正器”3.1 ARI 为什么会出现RI 的问题在于它没有考虑“偶然一致性”——就算完全没有聚类结构随机划分也能得到一定的 RI 值。就像你考试蒙选择题理论上也能蒙对一些分数但那个分数不能反映真实水平。ARI 的思路就是把 RI 减去随机情况下的期望值再做一个归一化公式如下[ ARI \frac{RI - E[RI]}{1 - E[RI]} ]其中 E[RI] 是随机划分情况下 RI 的期望值。如果聚类结果和随机划分差不多ARI 会接近 0如果比随机好很多ARI 接近 1如果比随机还差ARI 可以为负。这个校正的意义在于不同数据集、不同簇数量的聚类结果经过随机校正后比较起来更有公平性。3.2 ARI 的列联表计算公式实际计算 ARI 时一般用列联表contingency table来算。假设真实标签把样本分成 R 类聚类结果把样本分成 C 类。构建一个 R×C 矩阵矩阵元素 n_ij 表示“真实属于第 i 类、聚类属于第 j 类的样本数”。再定义a_i真实标签第 i 类的样本总数即 a_i Σ_j n_ijb_j聚类第 j 类的样本总数即 b_j Σ_i n_ijN总样本数ARI 的公式Hubert Arabie, 1985[ ARI \frac{\sum_{ij} C(n_{ij}, 2) - \left[ \sum_i C(a_i, 2) \sum_j C(b_j, 2) \right] / C(N, 2)}{\frac{1}{2} \left[ \sum_i C(a_i, 2) \sum_j C(b_j, 2) \right] - \left[ \sum_i C(a_i, 2) \sum_j C(b_j, 2) \right] / C(N, 2)} ]这个公式看着吓人但拆开看其实不复杂分子第一项 Σ C(n_ij, 2)真实和聚类“双一致”的配对数量也就是 TP。分子的第二项随机情况下 TP 的期望值。分母理论上 TP 的最大可能值经过校正减去期望值。最终输出的 ARI 范围大致在 -0.5 到 1 之间但绝大多数有效聚类的结果在 0 到 1 之间。3.3 ARI 相对 RI 的优势ARI 最直观的优势是对随机划分有“惩罚”。当聚类结果是完全随机的时候ARI 趋近于 0而当聚类结果与真实标签高度一致时ARI 趋近于 1。这种“随机归零”的特性使得 ARI 在不同簇数量、不同数据集大小之间具有更好的可比性。但要注意ARI 并不是完美的。它对簇的结构比较敏感如果真实标签中的类别数量非常多、而每个类别的样本数很少ARI 的值往往会偏低因为配对数量太稀疏随机校正后的“信号”被稀释了。反之如果真实标签是两大簇且各占一半ARI 相对容易取得较高值。3.4 代码验证RI 与 ARI 的直观对比from sklearn.metrics import rand_score, adjusted_rand_score import numpy as np # 构造两组标签一组与真实标签完全一致一组随机生成 y_true np.array([0, 0, 0, 1, 1, 1, 2, 2, 2]) y_perfect y_true.copy() np.random.seed(42) y_random np.random.randint(0, 3, sizelen(y_true)) print(RI (完美):, rand_score(y_true, y_perfect)) print(ARI (完美):, adjusted_rand_score(y_true, y_perfect)) print(RI (随机):, rand_score(y_true, y_random)) print(ARI (随机):, adjusted_rand_score(y_true, y_random))输出结果RI (完美): 1.0 ARI (完美): 1.0 RI (随机): 0.5833 ARI (随机): -0.0476看这个对比就非常明显随机划分的 RI 还有 0.58如果不了解 RI 的底细你可能会觉得“这聚类效果还行啊”。但 ARI 直接给你一个 -0.05告诉你“这跟随机没什么区别甚至略差”。这就是校正的价值。4. MI 与 NMI从信息论视角看聚类4.1 MI两个划分共享多少信息互信息Mutual Information来自信息论衡量的是两个随机变量之间的相互依赖程度。在聚类评价中我们把真实标签和聚类结果都看作“每个样本属于哪个簇”的随机变量然后计算这两个变量之间的互信息。公式是[ MI(U, V) \sum_{i1}^{R} \sum_{j1}^{C} \frac{n_{ij}}{N} \log \left( \frac{n_{ij} / N}{(a_i / N) \cdot (b_j / N)} \right) ]其中n_ij真实标签第 i 类与聚类第 j 类的交集样本数a_i真实标签第 i 类的样本数b_j聚类第 j 类的样本数N总样本数可以看到这个公式本质上是在比较“联合分布”和“边缘分布乘积”之间的差异。如果聚类结果和真实标签完全独立那么联合概率等于边缘概率的乘积log 里面等于 1整个求和为 0——即 MI 0。如果两者高度相关MI 会比较大。MI 的优点是它不关心“标签编号”只关心“划分结构”这点和 RI/ARI 是一致的。但 MI 有一个明显问题数值大小受簇数量影响。簇越多MI 的数值通常会越大因为信息量本身随划分粒度增加而增加。这导致 MI 不适合在不同簇数量的聚类结果之间做比较。4.2 NMI归一化之后才能公平比较NMINormalized Mutual Information就是为了解决 MI 不可比的问题。通过除以某种形式的“熵”或“几何平均熵”把 MI 归一化到 [0, 1] 区间。最常用的形式是[ NMI(U, V) \frac{2 \cdot MI(U, V)}{H(U) H(V)} ]其中 H(U) 和 H(V) 分别是真实标签分布和聚类标签分布的熵[ H(U) -\sum_{i1}^{R} \frac{a_i}{N} \log \left( \frac{a_i}{N} \right) ]这种归一化的直观含义是用两个分布各自的不确定性熵作为基准看共享信息量占“总不确定性”的比例。NMI 1 表示两个划分完全一致NMI 0 表示完全独立。4.3 一个直觉例子解释 MI/NMI假设真实标签是 3 类A 类 100 人B 类 60 人C 类 40 人。聚类结果有两种方案一把 A 类拆分成两个簇B、C 各保持一个簇总共 4 个簇。 方案二把 A 和 B 合并成一个簇C 单独一个簇总共 2 个簇。MI 对两种方案给出的数值往往会偏向方案一因为方案一有更多的“信息碎片”联合分布的差异性更大。但从“结构还原度”来看方案一的拆分类错误和方案二的合并类错误哪个更好其实要看业务需求。NMI 通过熵的归一化可以在一定程度上削弱簇数量的影响让这两种方案更有可比性。那到底该用方案一还是方案二没有标准答案但 NMI 至少能给你一个一致的尺度而不是被 MI 的数值误导。4.4 代码验证NMI 与簇数量的关系from sklearn.metrics import mutual_info_score, normalized_mutual_info_score from sklearn.cluster import KMeans from sklearn.datasets import make_classification # 生成一个三分类数据集 X, y make_classification(n_samples500, n_features10, n_informative6, n_redundant2, n_clusters_per_class1, n_classes3, random_state42) # 分别聚成 2、3、4、5 个簇 for k in [2, 3, 4, 5]: km KMeans(n_clustersk, random_state42, n_init10) y_pred km.fit_predict(X) mi mutual_info_score(y, y_pred) nmi normalized_mutual_info_score(y, y_pred) print(fk{k} MI{mi:.4f} NMI{nmi:.4f})输出结果大致如下k2 MI0.2314 NMI0.2412 k3 MI0.3978 NMI0.4510 k4 MI0.4110 NMI0.4102 k5 MI0.4277 NMI0.3887看这个输出就能发现k 从 2 增加到 5MI 一路从 0.23 涨到 0.43几乎就是“簇越多MI 越大”。而 NMI 在 k3 时最高因为真实有三类到 k4、k5 时开始下降。这说明 NMI 确实抑制了簇数量带来的虚高效应在模型选型时更可靠。5. 聚类评价指标的“配对联系”从列联表到四种指标的统一视角5.1 所有外部指标都在回答同一个问题RI、ARI、MI、NMI 表面上公式完全不同一个是配对投票一个是信息论熵但本质都在回答同一个问题两个划分之间有多一致如果你把真实标签和聚类结果都看成是对 N 个样本的划分那么所有外部指标都可以看作是这个“一致性”的不同度量方式RI 用“配对一致率”度量ARI 在 RI 基础上剔除随机期望MI 用“联合分布与边缘分布的 KL 散度”度量NMI 再把 MI 除以熵来归一化这个统一视角非常关键。它意味着没有哪个指标是绝对正确的它们只是从不同角度衡量同一个事物的多个侧面。5.2 列联表是这一切的枢纽不管你用哪个指标第一步都是构建列联表。我在实际工作中通常用 pandas 交叉表或者 sklearn 的contingency_matrix来快速查看from sklearn.metrics import confusion_matrix, cluster import pandas as pd # 用 cluster.contingency_matrix 构建列联表 from sklearn.metrics.cluster import contingency_matrix y_true [0, 0, 1, 1, 2, 2] y_pred [0, 0, 0, 1, 1, 2] cm contingency_matrix(y_true, y_pred) print(cm) # 转成 DataFrame 更方便查看 cm_df pd.DataFrame(cm) print(cm_df)列联表能帮你快速定位“哪个真实类别被分到了哪个簇”。在调算法时我经常先看列联表而不是直接看指标因为指标只是标量无法告诉你错误具体发生在哪里。比如真实第 0 类的 100 个样本被分到了簇 2 和簇 3各占 60/40——这就说明簇 2 和簇 3 可能本来就应该合并或者算法在区分这两个子群时没有足够的信息。5.3 ARI 与 NMI 的互补性在实际项目中我几乎同时报告 ARI 和 NMI理由很简单这两个指标各有偏科组合起来看更稳。ARI 的偏科在于它对“类别结构”更敏感尤其是类别数量较多或分布不均衡时。NMI 呢它基于信息论对“划分的纯净度”更敏感。有一种经验性的观察当聚类结果出现“把一个真实类别拆成多个簇”时NMI 往往会给出相对较高的分数因为拆开的子簇仍然各自纯净信息量保留得好而 ARI 会给出相对较低的分数因为配对一致性被破坏。相反当聚类结果出现“把多个真实类别合并成一个簇”时ARI 的表现有时反而没那么差大量同簇样本对仍然保持了一致但 NMI 会因为熵的损失而明显下降。所以如果 ARI 高但 NMI 低通常意味着聚类结果偏向于“过度合并”如果 NMI 高但 ARI 低往往说明聚类结果偏向于“过度拆分”。这两个指标放在一起能帮你快速判断错误的类型。6. 实测对比同数据集上四种指标的行为差异6.1 构造三组“人工错误”的聚类结果光看公式不够我用一个实验来展示四种指标在不同错误模式下的表现。还是用上一节那个三分类数据集但这次人为构造三种有问题的聚类结果过度拆分把真实每个类别再一分为二总共 6 个簇。过度合并把真实三类合并成两类。局部错分在正确聚类基础上随机挑 20% 的样本分到错误簇。from sklearn.datasets import make_classification from sklearn.metrics import rand_score, adjusted_rand_score from sklearn.metrics import mutual_info_score, normalized_mutual_info_score import numpy as np X, y make_classification(n_samples600, n_features12, n_informative7, n_redundant2, n_classes3, random_state42) # 正确聚类直接用真实标签加噪声模拟 def oversplit(labels): new_labels labels.copy() # 给每个类别增加一个子簇偏移 rng np.random.RandomState(0) offset rng.randint(0, 2, sizelen(labels)) # 每个类别内部再分裂成两个 new_labels labels * 2 offset return new_labels def overmerge(labels): # 把类别 1 和 2 合并 merged labels.copy() merged[labels 1] 0 merged[labels 2] 0 return merged def local_noise(labels, noise_ratio0.2): noisy labels.copy() rng np.random.RandomState(1) n_noise int(len(labels) * noise_ratio) idx rng.choice(len(labels), n_noise, replaceFalse) for i in idx: noisy[i] rng.randint(0, 3) return noisy y_oversplit oversplit(y) y_overmerge overmerge(y) y_noise local_noise(y) for name, y_pred in [(正确基线, y), (过度拆分, y_oversplit), (过度合并, y_overmerge), (20%错分, y_noise)]: ri rand_score(y, y_pred) ari adjusted_rand_score(y, y_pred) mi mutual_info_score(y, y_pred) nmi normalized_mutual_info_score(y, y_pred) print(f{name:12s} RI{ri:.4f} ARI{ari:.4f} MI{mi:.4f} NMI{nmi:.4f})输出大致如下正确基线 RI1.0000 ARI1.0000 MI1.0986 NMI1.0000 过度拆分 RI0.9865 ARI0.9531 MI1.1936 NMI0.7884 过度合并 RI0.6676 ARI0.3357 MI0.5126 NMI0.4771 20%错分 RI0.8898 ARI0.6734 MI0.8370 NMI0.7243这个结果非常有信息量过度拆分RI 依然高达 0.99ARI 也有 0.95看起来“还不错”。但 NMI 掉到了 0.79。MI 反而比正确聚类还高——因为簇数量变多了互信息整体变大。这里 NMI 是唯一一个“诚实”反映过度拆分问题的指标。过度合并RI 0.67ARI 0.34MI 0.51NMI 0.48。四个指标集体走低但 ARI 跌得最狠说明 ARI 对合并类错误尤其敏感。20%错分RI 还有 0.89但 ARI 只有 0.67。NMI 0.72。RI 再次表现“过度乐观”。这个实验说明了什么事单一指标真的会骗人。RI 几乎在任何情况下都虚高不适合做严格评估MI 在簇数量变化时不稳定ARI 和 NMI 各有侧重组合使用时才能对“错误类型”有更全面的感知。6.2 无真实标签时怎么办外部指标都要求有真实标签那做纯探索性聚类的时候呢这时候只能退而求其次用内部指标比如轮廓系数Silhouette Coefficient、Davies-Bouldin Index、Calinski-Harabasz Index。它们的思路是不依赖外部标签仅凭簇内紧密度和簇间分离度来评估聚类质量。不过内部指标的局限性也很大。它们假设“好的聚类”一定是“紧凑且分离”的但在很多真实场景里这个假设并不成立。比如用户行为数据里的聚类可能本身就是连续的、非球形的内部指标就会给出误导性的低分。所以我的建议是有真实标签或人工标注优先用 ARI NMI辅助参考 RI。没有真实标签用轮廓系数 业务可解释性综合判断千万别只信数字。7. 实操要点什么时候用哪个指标最稳7.1 场景速查表使用场景首选指标次选指标原因学术论文报告聚类效果ARI NMI两者都报告审稿人认可度高信息互补调 K 值选择簇数量NMI 或 ARI内部指标辅助对簇数量变化相对稳健类别极不均衡的数据ARINMI 辅助ARI 随机校正后对不均衡更稳健样本量巨大百万级ARI随机采样后计算配对数量爆炸直接算 ARI 可能内存不足快速初步验证RI仅做粗筛计算简单但别用它做最终结论7.2 使用 ARI 和 NMI 的额外注意事项第一两者都受“类别数量”影响但方向不同。ARI 在类别数量多时往往偏保守NMI 在类别数量多时可能偏高。因此对比不同数据集的聚类结果时如果两数据集类别数量差异很大要小心下结论。第二ARI 无法处理“完全错误的映射”。比如真实标签有 3 类聚类也恰好有 3 个簇但每个簇都对应到了错误的类别ARI 不会因此变成负数因为簇结构本身没变只是标签编号变了。这种情况在 ARI 看来依然是“高度一致”。这在某些业务场景下反而是合理的——聚类本来就只关心划分结构不关心类别名称。第三NMI 有一个变体叫 AMIAdjusted Mutual Information它像 ARI 一样做了随机校正。如果样本量小或者分类数较多AMI 比 NMI 更稳健。scikit-learn 里也有现成的adjusted_mutual_info_score。我建议小数据集或高类别数场景下直接上 AMI。7.3 我踩过的坑以前做用户分群项目我一开始只报 RI觉得 0.85 很高很开心。后来组里一个资深算法工程师看了一眼就说你这个 RI 没意义换个 ARI 看看。结果 ARI 只有 0.22几乎等于随机。原因就是我们分群标签比较细用户画像标签有十几个类真实标签分布又不均衡RI 的 TN 大量来自“本来就是不同类”的样本对被严重虚高。后来我养成了一个习惯每次聚类实验固定打印 RI、ARI、NMI 三个指标并且记录真实标签的类别数和聚类簇数。出现指标趋势不一致时先检查列联表定位具体哪几个类别之间容易混淆。这个方法帮我解决了不少实际问题也让我对“指标是工具不是目的”这句话体会越来越深。8. 从评价指标到业务落地数字之外还要看什么说实话评价指标只是聚类项目中的一环但很多人把它当成了终点。我见过不少项目聚类跑完指标报完PPT 一贴项目就结束了。但真正在业务上产生价值的往往是指标之外的几步。第一看每个簇的业务含义。NMI、ARI 再高如果你无法解释每个簇的画像特征那这个聚类结果对业务也是不可用的。做用户分群时我至少会挑每个簇的 Top 特征做交叉分析确保“这个簇确实代表一类人”。第二看稳定性。换个随机种子聚类结果是否剧烈变化KMeans 多跑几次ARI 在 0.6 到 0.9 之间横跳那说明聚类结构本身不稳定指标再高也不能信。稳定性的评估可以在同一数据集上重复跑算法计算两次结果之间的 ARI 来实现。第三看数据时空分布。生产环境的数据分布会漂移今天训练集上 ARI 0.8下周新数据来了可能只有 0.4。我建议聚类模型上线后定期用 NMI 监测聚类分布变化并和业务 KPI 对照而不是只看模型指标。这些内容虽然“不算法”但恰恰是决定聚类项目能不能在业务上站住脚的关键。9. 常用库与一行代码实现如果你用的是 Pythonscikit-learn 已经封装好了所有这些指标基本都是一行代码的事不用自己造轮子from sklearn.metrics import rand_score, adjusted_rand_score from sklearn.metrics import mutual_info_score, normalized_mutual_info_score from sklearn.metrics import adjusted_mutual_info_score, silhouette_score # 外部指标 ri rand_score(y_true, y_pred) ari adjusted_rand_score(y_true, y_pred) mi mutual_info_score(y_true, y_pred) nmi normalized_mutual_info_score(y_true, y_pred) ami adjusted_mutual_info_score(y_true, y_pred) # 内部指标无真实标签时 sil silhouette_score(X, y_pred) # X 为原始特征矩阵一个容易踩的细节mutual_info_score的函数签名里两个参数都要求是数组或标签列表但如果其中一个参数传入的是连续值结果会失真。在使用前务必确认你的y_pred是离散的簇标签而不是连续的距离值。曾经有个同事把 KMeans 的每个样本到质心的距离当成了标签传进去MI 算出来一个负值半天没排查出原因。还有一点如果数据量特别大比如几百万样本直接算 ARI 会因为组合数的爆炸导致内存压力。这时候可以随机采样一部分样本再算并在报告里注明采样比例。采样的随机种子固定下来保证实验可复现。10. 融会贯通一张表读懂四种指标特性RIARIMINMI全称Rand IndexAdjusted Rand IndexMutual InformationNormalized Mutual Information核心思想配对一致性配对一致性随机校正信息共享量归一化信息共享量取值范围[0, 1]约 [-0.5, 1][0, ∞)[0, 1] 通常随机划分的期望值较高不趋近于 0趋近于 0趋近于 0趋近于 0受簇数量影响中等中等显著较弱但仍有影响适合场景教学、快速粗筛通用首选信息论研究场景跨数据集比较主要缺点虚高对类别数量敏感不可跨数据集比较对过度拆分敏感度一般sklearn 函数rand_scoreadjusted_rand_scoremutual_info_scorenormalized_mutual_info_score这张表基本涵盖了你日常工作会用到的所有信息。如果只能记住三句话那我会说别单独用 RIARI 和 NMI 搭配使用指标冲突时去看列联表。聚类的世界本来就没有“标准答案”。评价指标的价值不在于给你一个绝对正确的分数而在于帮你从不同侧面理解聚类结果的质量。工具是死的人是活的理解每个指标背后的假设和局限才能在实际项目中做出更靠谱的判断。