有真实标签时如何评估无监督聚类?类别匹配方法咨询
聚类结果与真实标签的匹配及评估方案
聚类算法(如KMeans)输出的类别编号是随机分配的,和真实标签的编号没有天然对应关系,直接用LabelEncoder转换真实标签后计算准确率会得到错误结果。以下是两种解决思路:
一、使用无需类别匹配的评估指标
这类指标不关心类别编号,只衡量聚类结果与真实标签的分组一致性,适合直接评估聚类效果:
常用指标及代码示例
from sklearn.metrics import adjusted_rand_score, normalized_mutual_info_score # 计算调整兰德指数(取值[-1,1],越接近1说明聚类与真实标签一致性越高) ars = adjusted_rand_score(df['class'], df['prediction']) # 计算归一化互信息(取值[0,1],越接近1说明聚类效果越好) nmi = normalized_mutual_info_score(df['class'], df['prediction']) print(f"调整兰德指数: {ars:.4f}") print(f"归一化互信息: {nmi:.4f}")
二、找到真实标签与聚类结果的最优匹配,计算准确率等指标
如果需要明确每个聚类类别对应的真实标签,并计算准确率,可以通过匈牙利算法找到最优的类别映射:
具体步骤及代码
from sklearn.preprocessing import LabelEncoder from scipy.optimize import linear_sum_assignment import numpy as np from sklearn.metrics import accuracy_score # 1. 将真实标签转换为数字编码 le = LabelEncoder() y_true = le.fit_transform(df['class']) y_pred = df['prediction'].values # 2. 构建混淆矩阵:行=真实标签编号,列=聚类标签编号,值=交叉样本数 confusion_matrix = np.zeros((len(le.classes_), len(le.classes_)), dtype=int) for true, pred in zip(y_true, y_pred): confusion_matrix[true, pred] += 1 # 3. 用匈牙利算法找最优匹配(最大化匹配的样本数,因此对混淆矩阵取负数) row_ind, col_ind = linear_sum_assignment(-confusion_matrix) # 4. 构建聚类标签到真实标签的映射关系 label_mapping = {col_ind[i]: row_ind[i] for i in range(len(row_ind))} # 5. 对聚类结果进行标签映射,计算准确率 y_pred_mapped = np.array([label_mapping[pred] for pred in y_pred]) acc = accuracy_score(y_true, y_pred_mapped) # 输出结果 print(f"匹配后的准确率: {acc:.4f}") print("\n真实标签与聚类标签的对应关系:") for cluster_label, true_idx in label_mapping.items(): true_label = le.inverse_transform([true_idx])[0] print(f"聚类标签 {cluster_label} → 真实标签 {true_label}")
优化你的KMeans代码
避免使用全局变量,改为直接返回结果,同时加入random_state保证聚类结果可复现:
def kmeans(df): from sklearn.cluster import KMeans n_clusters = len(df['class'].unique()) # 设置random_state确保每次运行结果一致 km = KMeans(n_clusters=n_clusters, random_state=42) y_predicted = km.fit_predict(df[['x', 'y']]) df['prediction'] = y_predicted return df, y_predicted df, y_pred = kmeans(df)
内容的提问来源于stack exchange,提问作者Mukhammadyusuf Yuldashev Kobul
相关产品推荐
相关产品推荐

