列举十个经典的数据挖掘算法(5个特征选择算法)
全文共5462字,预计学习时长11分钟
图片来源:https://unsplash.com/@seefromthesky
数据科学是研究算法的学问。本文将会介绍一些处理数据时最常用的特征选择技术。
我们经常遇到这样的情况:在创建了大量特征后,又需要减少数量,最后再使用相关性或者基于树的方法来找出其中的重要特征。那么,如何让这些方法变得更有结构呢?
为何要进行特征选择?
在文章开始之前,先来回答这个问题:为什么不将所有的特征都交给机器学习算法,让它来决定哪些特征比较重要呢?
以下便是不能的三个原因:
1. 维数的诅咒——过拟合
维数的诅咒:随着特征空间维数的增加,配置数量将会以指数级增长,因此观测量会下降
如果数据中的列数多于行数,就能完美匹配训练数据,但这却并不适用于新样本。因此这样什么也没学到。
2. 奥卡姆剃刀原理
模型应当简单易懂。如果特征太多,就失去了可解释性。
3. 无用输入和输出
很多时候会出现像名称或ID变量等非信息特征。劣质输入也会产生劣质输出。
此外,大量特征会使模型量大、耗时,更难落实生产。
那应该怎么做?
答案是:只选择有用特征。
幸运的是,Scikit-learn能便捷简单地选择特征。特性选择有很多种方法,但是大多可以分为三类:
• 过滤:列入一些筛选特征的标准,如相关性/卡方分布。
• 包装:包装法将特征选择看作是搜索问题。如回归特征消除。
• 嵌入:嵌入法使用内置了特征选择方法的算法。比如,Lasso和RF都有各自的特征选择方法。
理论已经讲够了,接下来开始说五个特征选择的方法。
本文将使用数据集来方便理解——用一个足球运动员的数据集来找到成为优秀足球运动员的秘诀。
如果不理解足球术语也没关系,术语并不多。
Kaggle Kernel代码:https://www.kaggle.com/mlwhiz/Feature-selection-using-football-data?source=post_page---------------------------
一些简单的数据预处理
此前已进行了一些基本的预处理,比如删除空值和一次热编码。将此问题转化为分类问题要用:
y = traindf['Overall']>=87
这里使用整体最高代指一个优秀球员。数据集(X)如下所示,有223列。
train Data X
1. 皮尔逊相关系数
这个是过滤法的一种。
检查数据集里目标和数值特征之间皮尔逊相关系数8的绝对值。根据这个准则保留前n个特征。
def cor_selector(X, y,num_feats): cor_list = [] feature_name = X.columns.tolist() # calculate the correlation with y for each feature for i in X.columns.tolist(): cor = np.corrcoef(X[i], y)[0, 1] cor_list.append(cor) # replace NaN with 0 cor_list = [0 if np.isnan(i) else i for i in cor_list] # feature name cor_feature = X.iloc[:,np.argsort(np.abs(cor_list))[-num_feats:]].columns.tolist() # feature selection? 0 for not select, 1 for select cor_support = [True if i in cor_feature else False for i in feature_name] return cor_support, cor_feature cor_support, cor_feature = cor_selector(X, y,num_feats) print(str(len(cor_feature)), 'selected features')
2. 卡方分布
另一种过滤法。
该方法计算目标与数值变量之间的卡方度量分布,只选取卡方值最大的变量。
举个小例子来说明如何计算样本的卡方统计量。
假设数据集中有75个右前锋和25个非右前锋。观察到其中40个右前锋好,35个不好。这是否意味着右前锋会影响整体表现呢?
观察和预期计数
计算卡方值:
要计算,首先要找出每个部分中的期望值,如果这两个分类变量之间确实独立的话。
很简单,将每个单元格的行和与列和相乘,并将其除以总观察值。
因此“好的”和“非右前锋的”期望值=25(行和)*60(列和)/100(总观察量)
为什么会这样?因为数据中有25%,所以预计在观察到的60名优秀球员中,有25%的人会是右前锋球员。因此是15个。
然后可以用下面的公式对所有4个单元格求和:
此处不会展示,但卡方统计量也有非负数值和分类特征。
数据集中可以得到如下卡方特征:
from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 from sklearn.preprocessing import MinMaxScaler X_norm = MinMaxScaler().fit_transform(X) chi_selector = SelectKBest(chi2, k=num_feats) chi_selector.fit(X_norm, y) chi_support = chi_selector.get_support() chi_feature = X.loc[:,chi_support].columns.tolist() print(str(len(chi_feature)), 'selected features')
3. 递归特征消除
这是一个包装法。如上所述,包装法将一组特性的选择视为搜索问题。
来自sklearn 文件:
递归特征消除(RFE)的目标是递归地考虑越来越小的特征集来选择特征。首先,用初始特征集训练估计器,通过 coef_或者feature_importances_属性可以获得特征的重要性。然后,从当前的一组特性中删除最不重要的。该过程在修剪集上递归地重复,直到最终达到所需的要选择的特性数量。大家可能猜到了,这个方法可以用在任何估计器上。此处用的是 LogisticRegression ,而RFE观察了 LogisticRegression对象的coef_属性。
from sklearn.feature_selection import RFE from sklearn.linear_model import LogisticRegression rfe_selector = RFE(estimator=LogisticRegression(), n_features_to_select=num_feats, step=10, verbose=5) rfe_selector.fit(X_norm, y) rfe_support = rfe_selector.get_support() rfe_feature = X.loc[:,rfe_support].columns.tolist() print(str(len(rfe_feature)), 'selected features')
4. 套索:SelectFromModel
这个是嵌入法。如前所述,嵌入法使用有内置特征选择方法的算法。
例如,Lasso和RF都有自己的特征选择方法。Lasso正则化器强制许多特征权重为零。
这里用套索来选择变量。
from sklearn.feature_selection import SelectFromModel from sklearn.linear_model import LogisticRegression embeded_lr_selector = SelectFromModel(LogisticRegression(penalty="l1"), max_features=num_feats) embeded_lr_selector.fit(X_norm, y) embeded_lr_support = embeded_lr_selector.get_support() embeded_lr_feature = X.loc[:,embeded_lr_support].columns.tolist() print(str(len(embeded_lr_feature)), 'selected features')
5. 基于树形结构:SelectFromModel
这是嵌入法。如前所述,嵌入法使用有内置特征选择方法的算法。
还可以使用随机森林,根据特征的重要性来选择特征。
使用每个决策树中的节点杂质来计算特征的重要性。随机森林中,最终的特征重要性是所有决策树特征重要性的平均值。
from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import RandomForestClassifier embeded_rf_selector = SelectFromModel(RandomForestClassifier(n_estimators=100), max_features=num_feats) embeded_rf_selector.fit(X, y) embeded_rf_support = embeded_rf_selector.get_support() embeded_rf_feature = X.loc[:,embeded_rf_support].columns.tolist() print(str(len(embeded_rf_feature)), 'selected features')
也可以使用 LightGBM或者XGBoost 对象,只要它有feature_importances_属性。
from sklearn.feature_selection import SelectFromModel from lightgbm import LGBMClassifier lgbc=LGBMClassifier(n_estimators=500, learning_rate=0.05, num_leaves=32, colsample_bytree=0.2, reg_alpha=3, reg_lambda=1, min_split_gain=0.01, min_child_weight=40) embeded_lgb_selector = SelectFromModel(lgbc, max_features=num_feats) embeded_lgb_selector.fit(X, y) embeded_lgb_support = embeded_lgb_selector.get_support() embeded_lgb_feature = X.loc[:,embeded_lgb_support].columns.tolist() print(str(len(embeded_lgb_feature)), 'selected features'
彩蛋
既有森林,何须独木?
答案是,有时候数据太多、时间紧迫,全部使用是不可能的。
但只要有可能,为什么不这样做呢?
# put all selection together feature_selection_df = pd.DataFrame({'Feature':feature_name, 'Pearson':cor_support, 'Chi-2':chi_support, 'RFE':rfe_support, 'Logistics':embeded_lr_support, 'Random Forest':embeded_rf_support, 'LightGBM':embeded_lgb_support}) # count the selected times for each feature feature_selection_df['Total'] = np.sum(feature_selection_df, axis=1) # display the top 100 feature_selection_df = feature_selection_df.sort_values(['Total','Feature'] , ascending=False) feature_selection_df.index = range(1, len(feature_selection_df) 1) feature_selection_df.head(num_feats) functionComputeSMA(data,window_size)
检查一下,用了以上所有方法后是否得到了特征。此处可以看到反应和长传是好评球员的优秀属性。和预期一样,控球和最后得分也占据了首位。
结论
特征工程和特征选择是所有机器学习分支的关键。
模型要力求精确,不一遍遍查看是不会获得良好精度的。
本文试图解释了一些最常用的特性选择技术,以及特性选择方面的工作流程,并且试图对这些方法提供一些直观认识。
留言 点赞 关注
我们一起分享AI学习与发展的干货
编译组:李美欣、蒋馨怡
相关链接:
https://towardsdatascience.com/the-5-feature-selection-algorithms-every-data-scientist-need-to-know-3a6b566efd2
如需转载,请后台留言,遵守转载规范
,
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com