如何正确使用sklearn.feature_selection.mutual_info_classif?特征选择疑问求解
特征选择中mutual_info_classif的discrete_features参数问题解答
核心结论
mutual_info_classif完全不会自动识别nom__OnlineSecurity_No Internet Service、nom__OnlineSecurity_Yes、nom__OnlineSecurity_No这类独热编码后的列属于同一个原始特征。它会把每一列当成独立的离散特征,单独计算互信息,这会导致同一个原始特征的信息被分散,无法体现其整体重要性。
当前设置的问题
你现在的discrete_features参数设置(判断特征名是否以"nom"开头来标记离散)本身没问题,但因为独热编码拆分了原始特征,最终得到的是每个独热子列的互信息,而非原始特征的整体得分。
解决方案
方案1:编码前计算原始特征的互信息(推荐)
直接对未编码的原始特征计算互信息,这样能得到每个原始特征的整体重要性,再基于此做特征选择,之后再进行编码处理:
# 假设你已经定义了原始特征的分类:标称、序数、数值特征列表 nominal_features = ["OnlineSecurity", ...] # 原始标称特征 ordinal_features = ["..."] # 原始序数特征 numerical_features = ["..."] # 原始数值特征 # 直接对原始特征计算互信息 y_train_final = y_train.map({'No': 0, 'Yes': 1}) mi_raw = mutual_info_classif( X=X_train[nominal_features + ordinal_features + numerical_features], y=y_train_final, # 对应标记每个特征是否离散:标称和序数是离散,数值是连续 discrete_features=[True]*len(nominal_features) + [True]*len(ordinal_features) + [False]*len(numerical_features) ) # 生成原始特征的互信息结果表 df_raw_mi = pd.DataFrame({ 'feature': nominal_features + ordinal_features + numerical_features, 'mi': mi_raw }).sort_values(by='mi', ascending=False) display(df_raw_mi.style.background_gradient(cmap='coolwarm'))
方案2:编码后对独热特征分组聚合
如果必须在编码后计算,可以通过特征名前缀提取原始特征,对互信息得分做聚合(求和/均值),得到原始特征的整体得分:
def isolate(): composer.fit(X=X_train) X_train_final = composer.transform(X=X_train) y_train_final = y_train.map({'No': 0, 'Yes': 1}) mi = mutual_info_classif( X=X_train_final, y=y_train_final, # 序数编码的特征也标记为离散 discrete_features=[feature.startswith("nom") or feature.startswith("ord") for feature in composer.get_feature_names_out()] ) df_c = pd.DataFrame() df_c['mi'] = mi df_c['feature'] = composer.get_feature_names_out() # 从编码后的特征名中提取原始特征名(分割__取前两部分) df_c['original_feature'] = df_c['feature'].apply(lambda x: '__'.join(x.split('__')[:2])) # 按原始特征分组,求和得到整体互信息 df_original_mi = df_c.groupby('original_feature')['mi'].sum().reset_index() display(df_original_mi.sort_values(by='mi', ascending=False).style.background_gradient(cmap='coolwarm')) isolate()
补充说明
- 序数编码如果是单列形式(没有拆分成独热),当前的离散标记逻辑是合理的,
mutual_info_classif可以正确处理这类离散的有序特征。 - 如果序数特征也做了独热编码,同样需要用方案2的分组聚合方式计算原始特征的整体互信息。
内容的提问来源于stack exchange,提问作者Jason Rich Darmawan
相关产品推荐
相关产品推荐

