点击上方“AI公园”,关注公众号,选择加“星标“或“置顶”
导读作者:Rahul Agarwal
编译:ronghuaiyang
福利:什么样的足球运动员是好足球运动员?
数据科学是对算法的研究。
我接触过很多算法,所以我列出了一些最常见的和最常用的算法。
有很多次,当你创建了很多特征,然后你需要想出减少特征数量的方法。
有时我们最终会使用相关或基于树的方法来找出重要的特性。
我们能让特征选择变得更结构化一点吗?
本文介绍了在处理数据时可以使用的一些最常见的特征选择技术
为什么要做特征选择?
在我们继续之前,我们需要回答这个问题。为什么我们不把所有的特征都给机器学习算法,让它来决定哪个特征是重要的呢?
有三个原因:
1. 维度诅咒 — 过拟合
如果数据中的列数多于行数,我们就能够很好地匹配训练数据,但这并不适用于新样本。因此我们什么也没学到。
2. 奥卡姆剃刀:
我们希望我们的模型是简单的和可解释的。当我们有很多特征时,我们就失去了可解释性。
3. 垃圾进去垃圾出来:
大多数时候,我们会有许多非信息性的特征。例如,名称或ID变量。低质量的输入将产生低质量的输出。
此外,大量的特征使得模型体积大、耗时长,并且难以在生产中实现。
那么,我们该怎么做呢?
我们只选择有用的特征。
幸运的是,Scikit-learn使我们可以很容易地选择特征。我们可以用很多方法来考虑特征选择,但是大多数特征选择方法可以分为三个主要部分:
基于过滤器:我们基于过滤器的特征指定了一些指标,比如相关/卡方就是这种度量的一个例子。
基于包装器:包装器方法将一组特征的选择视为一个搜索问题。举例:递归特征消除
嵌入:嵌入方法使用具有内置特征选择方法的算法。例如,Lasso和RF都有自己的特征选择方法。
理论讲得够多了,让我们从五个特征选择方法开始。
我们将尝试使用数据集来更好地理解它。
我将使用一个足球运动员的数据集来找出是什么样的球员是一个伟大的球员。
如果你不懂足球术语,不要担心。我尽量把它控制在最低限度
下面是Kaggle的 Kernel,其中包含需要你自己尝试的代码。
一些简单的数据预处理
我们已经完成了一些基本的预处理,比如删除空值和独热编码。将问题转化为分类问题,使用:
y = traindf['Overall']>=87
在这里,我们使用高Overall作为一个伟大球员的判断标准。
我们的数据集(X)如下所示,有223列。
1. 皮尔逊相关系数
这是一个基于过滤器的方法。
我们检查我们数据集中目标和数值特征之间皮尔逊相关性的绝对值。我们根据这个准则保留了前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
,递归观察 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. Lasso: 从模型中选择
这是一个嵌入方法。如前所述,嵌入方法使用具有内置特征选择方法的算法。
例如,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')
基于树: 从模型中选择
这也是一个嵌入方法。如前所述,嵌入方法使用具有内置特征选择方法的算法。
我们还可以使用RandomForest根据特征的重要性来选择特征。
我们使用每个决策树中的节点杂质来计算特征的重要性。在随机森林中,最终的特征重要性是所有决策树特征重要性的平均值。
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)
我们检查一下我基于所有的这些方法得到的特征。在这种情况下,我们可以看到“反应”和“长传”是高评价球员的优秀属性。不出所料,“控球”和“射门”也占据了榜首。
结论
特征工程和特征选择是所有机器学习pipeline的关键部分。
在我们的模型中,我们力求精确,一个人不可能在不反复查看这些特征的情况下获得良好的精度。
在本文中,我试图解释一些最常用的特征选择技术,以及在特征选择方面的工作流。
我还试图对这些方法提供一些直观的认识,但是你可能应该尝试更多地了解它,并尝试将这些方法合并到你的工作中。
— END—英文原文:https://towardsdatascience.com/the-5-feature-selection-algorithms-every-data-scientist-need-to-know-3a6b566efd2
请长按或扫描二维码关注本公众号
喜欢的话,请给我个好看吧!