当前位置: 首页 > news >正文

手把手教你用Python计算聚类指标:从混淆矩阵到ARI/AMI/ACC的完整推导

手把手教你用Python计算聚类指标:从混淆矩阵到ARI/AMI/ACC的完整推导

在机器学习领域,聚类分析作为无监督学习的重要分支,其效果评估一直是研究者和实践者关注的焦点。当我们使用sklearn等工具包时,常常会调用adjusted_rand_score()adjusted_mutual_info_score()等函数快速获得评估结果,但你是否真正理解这些指标背后的数学逻辑?本文将带你从最基础的混淆矩阵出发,逐步推导ARI、AMI和ACC三大核心聚类指标的计算过程,让你不仅知其然,更知其所以然。

1. 基础准备:理解混淆矩阵与聚类评估

聚类评估的核心在于比较算法输出与真实标签(如有)或内部结构的一致性。混淆矩阵(Contingency Table)作为基础工具,记录了聚类结果与真实类别之间的样本分布关系。让我们从一个简单的例子开始:

假设我们对9个样本进行聚类,真实类别和聚类结果如下:

样本编号真实类别聚类结果
1AA
2AC
3AC
4BC
5BB
6BC
7CB
8CB
9CC

构建混淆矩阵时,行代表真实类别,列代表聚类结果,单元格n_ij表示真实类别i被划分到聚类j的样本数:

import numpy as np confusion_matrix = np.array([ [1, 0, 2], # 真实类别A:1个在聚类A,0个在B,2个在C [0, 1, 2], # 真实类别B [0, 2, 1] # 真实类别C ])

这个矩阵将成为我们计算所有指标的基础。值得注意的是,在无监督学习中,如果真实标签不可得,我们则需要依赖轮廓系数等内部评估指标。

2. 调整兰德指数(ARI)的完整推导

ARI衡量的是两个数据分布之间的一致性,修正了随机分配的影响。其核心思想是比较实际配对与期望配对的相似度。

2.1 配对统计基础

首先定义几个关键变量:

  • a_i: 聚类结果中第i类的样本数(行和)
  • b_j: 真实类别中第j类的样本数(列和)
  • n_ij: 真实i类且聚类j类的样本数
  • n: 总样本数

从我们的例子可得:

a = np.sum(confusion_matrix, axis=1) # [3, 3, 3] b = np.sum(confusion_matrix, axis=0) # [1, 3, 5] n = np.sum(a) # 9

2.2 组合数计算

ARI公式中的组合数计算如下:

$$ ARI = \frac{\sum_{ij} \binom{n_{ij}}{2} - [\sum_i \binom{a_i}{2} \sum_j \binom{b_j}{2}] / \binom{n}{2}}{\frac{1}{2} [\sum_i \binom{a_i}{2} + \sum_j \binom{b_j}{2}] - [\sum_i \binom{a_i}{2} \sum_j \binom{b_j}{2}] / \binom{n}{2}} $$

用Python实现组合计算:

from math import comb def compute_ari(confusion_matrix): # 计算各项组合数 sum_comb_nij = sum(comb(n_ij, 2) for row in confusion_matrix for n_ij in row) sum_comb_ai = sum(comb(a_i, 2) for a_i in np.sum(confusion_matrix, axis=1)) sum_comb_bj = sum(comb(b_j, 2) for b_j in np.sum(confusion_matrix, axis=0)) comb_n = comb(np.sum(confusion_matrix), 2) # 计算ARI分子和分母 numerator = sum_comb_nij - (sum_comb_ai * sum_comb_bj) / comb_n denominator = 0.5 * (sum_comb_ai + sum_comb_bj) - (sum_comb_ai * sum_comb_bj) / comb_n return numerator / denominator

2.3 结果验证

与我们例子中的sklearn输出对比:

from sklearn.metrics import adjusted_rand_score labels_true = ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'] labels_pred = ['A', 'C', 'C', 'C', 'B', 'C', 'B', 'B', 'C'] print(f"Sklearn ARI: {adjusted_rand_score(labels_true, labels_pred):.3f}") print(f"Manual ARI: {compute_ari(confusion_matrix):.3f}")

输出结果均为-0.032,验证了我们的推导。

3. 调整互信息(AMI)的数学原理与实现

AMI基于信息论中的互信息概念,通过熵来衡量两个分类系统的一致性。

3.1 熵与联合分布计算

首先计算真实类别分布U和聚类结果分布V的熵:

def entropy(probs): return -np.sum(p * np.log2(p) for p in probs if p > 0) # 计算真实类别熵H(U) probs_u = np.sum(confusion_matrix, axis=1) / n h_u = entropy(probs_u) # 计算聚类结果熵H(V) probs_v = np.sum(confusion_matrix, axis=0) / n h_v = entropy(probs_v)

3.2 互信息计算

互信息衡量两个分布的相互依赖程度:

$$ MI(U,V) = \sum_{i=1}^{|U|} \sum_{j=1}^{|V|} \frac{n_{ij}}{n} \log \left( \frac{n_{ij}/n}{a_i b_j / n^2} \right) $$

Python实现:

def mutual_info(confusion_matrix, n): mi = 0.0 for i in range(confusion_matrix.shape[0]): for j in range(confusion_matrix.shape[1]): n_ij = confusion_matrix[i,j] if n_ij > 0: a_i = np.sum(confusion_matrix[i,:]) b_j = np.sum(confusion_matrix[:,j]) term = (n_ij / n) * np.log2((n_ij * n) / (a_i * b_j)) mi += term return mi

3.3 期望互信息与AMI计算

AMI通过调整随机期望来标准化互信息:

def expected_mi(confusion_matrix, n): # 简化计算,实际实现应考虑更精确的期望计算 a = np.sum(confusion_matrix, axis=1) b = np.sum(confusion_matrix, axis=0) term1 = np.sum(comb(a_i, 2) for a_i in a) / comb(n, 2) term2 = np.sum(comb(b_j, 2) for b_j in b) / comb(n, 2) return np.log2(n) - (1/n) - (1 - term1 - term2) def compute_ami(confusion_matrix, n): mi = mutual_info(confusion_matrix, n) emi = expected_mi(confusion_matrix, n) h_u = entropy(np.sum(confusion_matrix, axis=1) / n) h_v = entropy(np.sum(confusion_matrix, axis=0) / n) return (mi - emi) / (max(h_u, h_v) - emi)

验证结果与sklearn一致:

from sklearn.metrics import adjusted_mutual_info_score print(f"Sklearn AMI: {adjusted_mutual_info_score(labels_true, labels_pred):.3f}") print(f"Manual AMI: {compute_ami(confusion_matrix, n):.3f}")

4. 聚类准确率(ACC)的特殊处理

ACC看似简单,但在聚类中需要特殊处理标签对应问题。

4.1 标签对齐问题

由于聚类标签是任意的,直接计算准确率会得到错误结果。我们需要找到最优的标签映射:

from itertools import permutations from sklearn.metrics import accuracy_score def cluster_accuracy(y_true, y_pred): # 获取唯一标签 true_labels = np.unique(y_true) pred_labels = np.unique(y_pred) # 生成所有可能的映射 best_acc = 0 for mapping in permutations(true_labels, len(pred_labels)): mapped_pred = [mapping[np.where(pred_labels == p)[0][0]] for p in y_pred] acc = accuracy_score(y_true, mapped_pred) if acc > best_acc: best_acc = acc return best_acc

4.2 实际应用示例

# 将字符标签转换为数字 label_map = {'A':0, 'B':1, 'C':2} y_true = [label_map[x] for x in labels_true] y_pred = [label_map[x] for x in labels_pred] print(f"Direct ACC: {accuracy_score(y_true, y_pred):.3f}") print(f"Optimal ACC: {cluster_accuracy(y_true, y_pred):.3f}")

这个例子展示了为什么简单的准确率在聚类中可能产生误导,以及如何正确计算聚类准确率。

5. 指标特性与使用场景对比

不同聚类评估指标各有特点,理解它们的数学本质有助于在实际应用中选择合适的指标:

指标取值范围随机预期值适用场景优缺点
ARI[-1,1]0有真实标签对随机分配有修正,对称性度量
AMI[0,1]0有真实标签考虑信息熵,适合不平衡分类
ACC[0,1]随机概率有真实标签直观但需标签对齐,对不平衡敏感

注意:当真实标签不可得时,应考虑轮廓系数、Calinski-Harabasz指数等内部评估指标。

在实际项目中,我通常会同时计算多个指标来全面评估聚类效果。特别是在处理高维数据时,AMI往往能更敏感地捕捉到聚类质量的变化。而调试算法参数时,理解这些指标的计算过程能帮助更快定位问题所在。

http://www.jsqmd.com/news/876772/

相关文章:

  • 终极塔科夫离线存档编辑器:5步掌握SPT-AKI Profile Editor完整指南
  • Adv Sci | 李敏团队:AI 赋能蛋白质功能注释
  • RGB 中的“隐藏亮度“:揭秘藏在红绿蓝中的明暗密码
  • QKeyMapper:彻底解放你的输入设备,打造个性化操作体验
  • 为AI Agent框架OpenClaw配置Taotoken作为模型供应商
  • 量子玻尔兹曼机数值模拟:TPQ态与Lanczos算法的误差分析与调优实践
  • 面板数据因果推断:双机器学习与固定效应的融合实践
  • Karpathy加盟Anthropic与九章四号:2026年5月AI人才与算力双突破
  • 信号太吵、特征太多?试试用OMP给你的数据‘瘦身’:图像去噪与特征选择实战指南
  • Windows热键冲突终极指南:5分钟找到占用热键的罪魁祸首
  • 量子机器学习新突破:利用克尔相干态构建可编程弯曲特征空间
  • 如何3分钟搞定实时屏幕翻译:Translumo的神奇用法
  • 如何高效使用NHSE:动物森友会存档编辑器的完整专业指南
  • 终极指南:如何让老款Mac免费升级到最新macOS系统
  • 2026年苏州建筑防水修缮行业市场洞察与主流企业核心能力深度解析报告 苏州防水补漏维修公司靠谱品牌排名 - 鼎壹万修缮说
  • 概念建模的四种数学框架:从格代数到群论,构建更智能的AI
  • 抖音下载器终极指南:3分钟掌握批量下载技巧,无水印提取效率提升95%
  • 在Taotoken模型广场中根据任务需求挑选合适模型的思路
  • Windows热键冲突终极解决方案:3分钟快速定位被占用的快捷键
  • 谷歌 Gemini Omni 实测:生成视频效果好坏参半,换脸逼真或能骗过身边人!
  • 生产级MLOps鲁棒性实战:从数据漂移到模型监控的五大平台对比
  • Vectorizer终极指南:5分钟实现专业级多色彩位图矢量化
  • 淘金币自动化脚本终极指南:如何快速解放双手实现淘宝任务全自动执行
  • Getac G140 评测:坚固耐用但价格昂贵,性能表现差强人意
  • StreamCap:一站式跨平台直播录制工具,轻松捕获40+平台直播内容
  • MemTestCL终极指南:专业级GPU内存检测工具完整教程
  • 从AUC稳健下界到量子场论:机器学习与物理的数学统一
  • ComfyUI-Manager下载加速全攻略:从缓慢到极速的优化指南
  • 【前端国际化】动态语言切换:实现无缝的语言切换体验
  • 中兴光猫工厂模式解锁实战指南:zteOnu工具深度解析与完整方案