如何在Python中查看K-modes聚类的特征重要性?
分析K-modes聚类中各分类变量的贡献方法
针对你用K-modes聚类12个分类变量得到3个簇后,想分析每个变量对聚类结果的贡献这个问题,我整理了几个实用的方法,都是分类聚类场景下常用的思路:
方法1:基于卡方检验的类别关联分析
K-modes的核心是利用分类变量的类别分布区分簇,所以一个变量对聚类的贡献越大,它和簇标签的关联性就越强。卡方检验正好可以量化这种关联性——卡方值越大,说明变量的类别分布在不同簇间的差异越显著,对聚类的区分作用越强。
操作步骤:
- 对每个分类变量,构建它与簇标签的列联表(即每个类别在各簇中的样本数)
- 计算卡方统计量和对应的p值:p值小于0.05(常规显著性水平)说明变量和簇显著相关,卡方值的排序能直接反映变量的贡献优先级
代码示例(Python):
from scipy.stats import chi2_contingency import pandas as pd # 假设你的数据集是df,簇标签列名为'cluster' for col in df.columns[:-1]: # 遍历所有分类变量,排除簇标签列 # 构建列联表 contingency_table = pd.crosstab(df[col], df['cluster']) # 计算卡方检验结果 chi2, p_value, dof, expected = chi2_contingency(contingency_table) print(f"变量【{col}】:卡方值 = {chi2:.2f},p值 = {p_value:.4f}")
方法2:基于簇模式差异的直观分析
K-modes每个簇都会生成一个“模式”(cluster centroid,即每个变量在簇中出现频率最高的类别)。如果某个变量在不同簇的模式差异越大,说明它越能帮助区分不同簇。
操作步骤:
- 从训练好的K-modes模型中提取各簇的模式(比如
kmodes库中,模型的cluster_centroids_属性就是各簇的模式矩阵) - 对每个变量,分析其在不同簇间的模式差异:比如统计不同模式的数量,或者计算各簇类别频率的标准差(标准差越大,差异越显著)
代码示例(Python):
from kmodes.kmodes import KModes import pandas as pd # 假设已经训练好K-modes模型km,数据集是df,簇标签列是'cluster' cluster_modes = km.cluster_centroids_ variables = df.columns[:-1] for idx, var in enumerate(variables): # 获取该变量在所有簇中的模式 var_modes = cluster_modes[:, idx] # 统计模式的唯一值数量:数量越多,簇间差异越大 unique_mode_count = len(set(var_modes)) # 计算该变量在各簇的类别频率标准差 freq_table = pd.crosstab(df[var], df['cluster']).apply(lambda x: x/x.sum(), axis=0) avg_freq_std = freq_table.std(axis=1).mean() print(f"变量【{var}】:簇间唯一模式数 = {unique_mode_count},类别频率平均标准差 = {avg_freq_std:.4f}")
方法3:基于置换检验的特征重要性评估
这是最直接衡量变量贡献的方法:通过打乱某个变量的取值,模拟“移除该变量信息”的场景,观察聚类成本(K-modes的成本是所有样本到对应簇模式的不匹配变量数之和)的变化。如果打乱后成本上升越多,说明该变量对聚类的贡献越大。
操作步骤:
- 记录原始聚类的成本(模型的
cost_属性) - 对每个变量,随机打乱其所有取值,保持其他变量不变
- 计算打乱后的聚类成本,对比原始成本的变化比例,比例越大说明变量越重要
代码示例(Python):
from kmodes.kmodes import KModes import pandas as pd import numpy as np # 假设已经训练好模型km,数据集是df,簇标签是km.labels_ original_cost = km.cost_ variables = df.columns[:-1] def calculate_cluster_cost(df, cluster_modes, cluster_labels): """计算给定数据和簇模式的K-modes成本""" total_cost = 0 for i, label in enumerate(cluster_labels): # 计算当前样本到对应簇模式的不匹配数 mismatch_count = sum(df.iloc[i] != cluster_modes[label]) total_cost += mismatch_count return total_cost for var in variables: # 复制数据集并打乱当前变量的取值 df_shuffled = df.copy() df_shuffled[var] = df_shuffled[var].sample(frac=1).values.reset_index(drop=True) # 计算打乱后的成本 shuffled_cost = calculate_cluster_cost(df_shuffled, km.cluster_centroids_, km.labels_) # 计算成本增加比例 cost_increase_ratio = (shuffled_cost - original_cost) / original_cost print(f"变量【{var}】:成本增加比例 = {cost_increase_ratio:.2%}")
方法总结
- 如果想快速筛选和簇显著相关的变量,优先用卡方检验
- 如果想直观理解变量在簇间的区分逻辑,选簇模式差异分析
- 如果要最准确衡量变量对聚类性能的影响,置换检验是最优选择
内容的提问来源于stack exchange,提问作者Curious




