如何实现分组式递归特征消除(RFE)的分组特征选择功能?
分组式递归特征消除(Group RFE)实现方案
实现思路
原生scikit-learn的RFE默认按单个特征的重要性排序剔除,要实现按组剔除,核心逻辑是将同组特征的重要性聚合为组的重要性得分,每次迭代删除得分最低的整组,直到保留指定数量的分组。
完整可运行代码
导入依赖
import numpy as np from sklearn.base import BaseEstimator, SelectorMixin from sklearn.utils.validation import check_is_fitted from sklearn.svm import SVR from sklearn.datasets import make_classification
自定义分组RFE类(适配sklearn接口规范)
class GroupRFE(BaseEstimator, SelectorMixin): def __init__(self, estimator, n_groups_to_select, groups): """ 分组递归特征消除类 :param estimator: 基估计器,需具备coef_或feature_importances_属性 :param n_groups_to_select: 需要保留的分组数量(对应当你需求里的n_features_to_select) :param groups: 分组列表,每个元素是对应分组的特征索引列表,需覆盖所有特征无重叠 """ self.estimator = estimator self.n_groups_to_select = n_groups_to_select self.groups = groups self.n_groups = len(groups) def fit(self, X, y): # 初始化全部保留分组 keep_groups = list(range(self.n_groups)) while len(keep_groups) > self.n_groups_to_select: # 提取当前保留分组对应的所有特征 selected_features = [] for g_idx in keep_groups: selected_features.extend(self.groups[g_idx]) X_selected = X[:, selected_features] # 训练基模型 self.estimator.fit(X_selected, y) # 获取特征重要性 if hasattr(self.estimator, 'coef_'): importances = np.abs(self.estimator.coef_).ravel() elif hasattr(self.estimator, 'feature_importances_'): importances = self.estimator.feature_importances_.ravel() else: raise ValueError("基估计器需支持coef_或feature_importances_属性") # 聚合计算每个保留分组的平均重要性 group_importances = [] ptr = 0 for g_idx in keep_groups: g_len = len(self.groups[g_idx]) g_imp = np.mean(importances[ptr:ptr+g_len]) group_importances.append(g_imp) ptr += g_len # 删除重要性最低的分组 worst_g_idx = np.argmin(group_importances) del keep_groups[worst_g_idx] # 存储最终结果 self.support_ = np.zeros(X.shape[1], dtype=bool) for g_idx in keep_groups: self.support_[self.groups[g_idx]] = True self.keep_groups_ = keep_groups return self def _get_support_mask(self): check_is_fitted(self) return self.support_
使用示例
# 生成示例数据 X, y = make_classification(n_samples=100, n_features=20, random_state=42) # 定义分组规则:前10列为第1组,11-20列为第2组 groups = [ list(range(0, 10)), list(range(10, 20)) ] # 初始化分组RFE,设置保留1组(对应保留10个特征) estimator = SVR(kernel="linear") selector = GroupRFE(estimator, n_groups_to_select=1, groups=groups) # 训练并转换数据 selector.fit(X, y) X_selected = selector.transform(X) # 验证结果 print(f"保留的特征数量:{X_selected.shape[1]}") print(f"保留的分组索引:{selector.keep_groups_}")
注意事项
- 传入的
groups参数需覆盖所有输入特征,且不存在索引重叠 - 若你需要保留5组共50个特征,只需将
n_groups_to_select设置为5,同时将对应50个特征的分组规则传入groups即可 - 分组重要性默认采用组内特征重要性的平均值计算,可根据需求修改为求和、最大值等其他聚合逻辑
内容的提问来源于stack exchange,提问作者Talha Anwar
相关产品推荐
相关产品推荐

