scikit-learn中SelectFromModel如何选特征?XGBClassifier配合max_features失效疑问
SelectFromModel特征选择逻辑与XGBClassifier搭配问题解析
一、SelectFromModel的核心筛选逻辑
SelectFromModel完全依赖基模型输出的特征重要性做筛选,流程很明确:
- 先训练你传入的基模型(这里是XGBClassifier),得到每个特征的重要性得分
- 设定筛选阈值,仅保留重要性得分≥阈值的特征
max_features是上限控制参数:如果按阈值筛选出的特征数超过这个值,就取重要性最高的前N个;但如果筛选出的特征数本来就少于max_features,只会保留这些达标的特征,不会强行凑数
二、为什么总是返回5个特征?
你遇到的情况本质是:当前XGBClassifier训练后,只有5个特征的重要性得分高于默认阈值,剩下的特征得分都低于阈值——哪怕你设了max_features=10,也不会把得分不达标的特征硬塞进来。
XGBoost默认用**分裂次数(importance_type='weight')**计算特征重要性,只有在决策树分裂中被用到的特征才会有得分,没被用到的特征得分是0。如果你的数据里只有5个特征被模型用来分裂,那其他特征得分都是0,自然不会被选中。
这并不代表你的数据集只有5个有用特征,可能是当前XGB模型配置太保守(比如gamma太高、min_child_weight太大),导致模型不敢用更多特征分裂;或是其他特征和这5个高度相关,模型已经通过这5个特征学到足够信息,没必要再用其他特征。
三、调整方法:保留更多特征
1. 手动设置更低的筛选阈值
直接通过threshold参数指定更宽松的阈值,比如:
- 用特征重要性的中位数:
threshold='median' - 用均值的一半:
threshold=0.5*sf.estimator_.feature_importances_.mean() - 直接设极小值:
threshold=0.01
示例代码:
from sklearn.feature_selection import SelectFromModel from xgboost import XGBClassifier # 用中位数做阈值,同时限制最多保留10个特征 sf = SelectFromModel(XGBClassifier(), threshold='median', max_features=10).fit(X, y) print(sf.get_support())
2. 调整XGBClassifier的训练参数
让模型更容易利用更多特征:
- 降低
gamma(控制分裂所需的最小增益,值越小越易分裂) - 降低
min_child_weight(控制叶子节点的最小样本权重和,值越小越易分裂) - 增大
max_depth(允许树更深,能捕捉更多特征交互)
示例:
xgb_clf = XGBClassifier(gamma=0.1, min_child_weight=1, max_depth=6) sf = SelectFromModel(xgb_clf, max_features=10).fit(X, y)
3. 换用其他特征重要性计算方式
XGBoost支持多种重要性计算逻辑,比如:
importance_type='gain':基于分裂带来的损失减少量计算,能体现特征对模型性能的实际贡献,可能让更多特征获得较高得分importance_type='cover':基于分裂覆盖的样本数计算
示例:
xgb_clf = XGBClassifier(importance_type='gain') sf = SelectFromModel(xgb_clf, max_features=10).fit(X, y)
内容的提问来源于stack exchange,提问作者N_Z
相关产品推荐
相关产品推荐

