在数据预处理过程中,特征选择是一个重要的过程,选择出重要的特征可以加快模型训练速度。通常可以从以下两方面来选择特征:

1.特征是否发散(对于样本区分作用的大小)
2.特征与标签的相关性

特征选择的方法主要有3种:

1.Filter Method:先根据统计量设置阈值选择特征,之后再训练模型。
2.Wrapper Method:把最终将要使用的模型的性能作为特征子集的评价标准,多次训练模型选择有利于模型性能的特征子集。
3.Embedding Method:将特征选择过程与模型训练过程融为一体,在模型训练的过程中自动进行特征选择。

常用sklearn中的feature_selection库来进行特征选择。

1. Fliter 过滤法:

Fliter的优点在于只训练一次模型,速度快。但是选择与标签相关性最强的特征子集不一定是最佳特征,甚至可能对结果负优化。

1.1 方差选择法

计算各个特征的方差,设置阈值,选择方差大于阈值的特征。

1 2 3 from sklearn.feature_selection import VarianceThreshold #参数threshold为方差的阈值 VarianceThreshold(threshold=3).fit_transform(iris.data)
1.2 Pearson相关系数法

计算各个特征对于标签的Pearson相关系数和p值,选择前k名的特征。

1 2 3 4 from sklearn.feature_selection import SelectKBest from scipy.stats import pearsonr #参数k为选择的特征个数 SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)

Pearson法的缺陷在于只对线性相关敏感,对非线性关系不敏感。

1.3 卡方检验\互信息法等方法

也是用来评价X与y的相关性,先构建评价函数,再选择前K名的特征。

1 2 3 4 5 6 7 8 9 10 11 12 #chi2 from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target) #MIC from minepy import MINE def mic(x, y): m = MINE() m.compute_score(x, y) return (m.mic(), 0.5) SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)

2. Wrapper 包装法:

Wrapper的优点在于能够识别模型最适宜的特征子集,缺点在于训练多次模型,算法复杂性高,且特征子集不一定是大多数解释变量。

Wrapper最具代表性的方法就是RFE递归消除特征法,即使用一个基模型来进行多轮训练,每轮训练都遍历所有特征,之后消除重要性(feature_importances_)低的特征,再基于新的特征集进行下一轮训练。

1 2 3 4 5 6 7 8 #RFE from sklearn.feature_selection import RFE from sklearn.linear_model import LogisticRegression rfe = RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target) #RFECV from sklearn.feature_selection import RFECV rfecv = RFECV(estimator=svc, step=1, cv=StratifiedKFold(2), scoring='roc_auc')

3. Embedded 嵌入法

3.1 基于惩罚项的特征选择法

使用带惩罚项的基模型,除了筛选出特征外,同时也进行了降维。由于L1正则化会产生稀疏权值矩阵,所以其自带特征选择的特性。

1 2 3 4 5 6 7 #L1正则 from sklearn.feature_selection import SelectFromModel from sklearn.linear_model import LogisticRegression SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data, iris.target) #L2正则 SelectFromModel(LogisticRegression(penalty="l2",threshold=0.5, C=0.1)).fit_transform(iris.data, iris.target)
3.2 基于树模型的特征选择法

树模型中GBDT也可用来作为基模型进行特征选择。

1 2 3 from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import GradientBoostingClassifier SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)

4. 基于SHAP值的特征筛选

SHAP是由Shapley value启发的可加性解释模型。对于每条样本,每个特征都会对应一个SHAP value值体现其对结果的贡献。

1 2 3 4 5 6 7 8 import shap # 创建模型解释器 explainer_xgb = shap.TreeExplainer(model1) explainer_lgb = shap.TreeExplainer(model2) # 获取训练集每个样本每个特征特征的SHAP值,并对特征进行整体的可视化 shape_values = explainer_lgb.shap_values(data[cols]) shap.summary_plot(shape_values, data[cols], plot_type='bar')

5. 基于对抗验证(Adversarial Validation)的特征筛选

常用于训练集与测试集相差非常大的情况。实现步骤:
1.将训练集和测试集合并,分别打上0和1的标签。
2.构建模型进行训练,逐个将特征输入模型,记录AUC。
3.最后将AUC高的特征删除(将测试和训练样本差别很大的特征删除),通过删掉这些特征实现模型效果提升。