KMeans聚类后混淆矩阵维度不符预期的问题排查
问题分析与解决步骤
这问题我之前排查过类似的,大概率是标签编号不匹配或者真实标签的类别范围超出了你预期的5类,咱们一步步来拆解:
首先得明确:KMeans是无监督聚类算法,它输出的聚类标签(默认从0到n_clusters-1,也就是这里的0-4)是算法自行分配的,和你的真实标签编号没有天然对应关系。你得到10×10混淆矩阵且最后5列全0,主要有两种常见原因:
1. 真实标签的类别范围包含10个值(仅5个有样本)
比如你的真实标签数组里可能存在0-9的编号,但实际只有0-4对应的样本有数据,5-9没有任何样本。当你用confusion_matrix(y_true, y_pred)计算时,sklearn会把所有出现过的标签(包括5-9)都纳入矩阵维度,而因为预测标签只有0-4,所以5-9对应的列全是0。
解决方法:重新编码真实标签
用LabelEncoder把真实标签重新映射为0到4的连续编号:
from sklearn.preprocessing import LabelEncoder from sklearn.metrics import confusion_matrix # 假设y_true是你的真实标签,y_pred是KMeans输出的labels_ le = LabelEncoder() y_true_encoded = le.fit_transform(y_true) # 现在计算的混淆矩阵就是预期的5×5了 cm = confusion_matrix(y_true_encoded, y_pred) print(cm)
2. 聚类标签与真实标签的编号未对齐(补充场景)
如果你的真实标签确实是5类(0-4),但KMeans输出的聚类标签虽然也是0-4,却和真实标签的类别对应关系混乱(比如聚类0对应真实类别2,聚类1对应真实类别0等),这时候直接计算的混淆矩阵虽然是5×5,但对角线元素不会是最大的。这种情况需要先对齐标签再评估:
解决方法:用匈牙利算法对齐标签
通过匈牙利算法找到聚类标签和真实标签的最佳匹配,再计算混淆矩阵:
from scipy.optimize import linear_sum_assignment from sklearn.metrics import confusion_matrix import numpy as np # 先计算原始混淆矩阵 cm = confusion_matrix(y_true, y_pred) # 用匈牙利算法找到最大化对角线元素的标签映射 row_ind, col_ind = linear_sum_assignment(-cm) # 重新映射预测标签 aligned_y_pred = np.array([col_ind[label] for label in y_pred]) # 得到对齐后的5×5混淆矩阵 aligned_cm = confusion_matrix(y_true, aligned_y_pred) print(aligned_cm)
额外提醒:无监督聚类的更优评估方式
混淆矩阵其实不是KMeans这类无监督算法的最佳评估指标,因为它依赖标签的一一对应。更合适的指标是:
- 调整兰德指数(ARI):衡量聚类结果与真实标签的相似度,不受标签编号影响
- 归一化互信息(NMI):同样衡量聚类与真实标签的匹配程度
- 轮廓系数:无监督评估,衡量聚类的紧凑性和分离度
比如计算ARI的示例:
from sklearn.metrics import adjusted_rand_score ari_score = adjusted_rand_score(y_true, y_pred) print(f"调整兰德指数:{ari_score}")
内容的提问来源于stack exchange,提问作者Harshpal Singh
相关产品推荐
相关产品推荐

