博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
5个特征选择算法,让你的数据处理得心应手
阅读量:2089 次
发布时间:2019-04-29

本文共 5858 字,大约阅读时间需要 19 分钟。

全文共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

 

如需转载,请后台留言,遵守转载规范

 

长按识别二维码可添加关注

读芯君爱你

 

你可能感兴趣的文章
Java并发与多线程
查看>>
对于多线程程序,单核cpu与多核cpu是怎么工作的
查看>>
多线程和CPU的关系
查看>>
认识cpu、核与线程
查看>>
关于Java健壮性的一些思考与实践!
查看>>
如何避免自己写的代码成为别人眼中的一坨屎!
查看>>
Postman 安装及使用入门教程
查看>>
获取指定包下所有自定义注解并提取注解信息
查看>>
Windows 环境下 Git clone pull fetch 慢 解决之道
查看>>
Redis (error) NOAUTH Authentication required.解决方法
查看>>
plsql窗口中文显示的是横版的 问题解决办法
查看>>
使用notePad修改将文件格式保存后不起作用
查看>>
如何查询oracle会话及锁 如何查锁了哪张表?如何杀掉会话
查看>>
Git常用命令速查手册
查看>>
Redis运维利器 -- RedisManager
查看>>
分布式之REDIS复习精讲
查看>>
分布式之数据库和缓存双写一致性方案解析
查看>>
Redis集群
查看>>
Oracle 查看和扩展表空间
查看>>
记一次线上Java程序导致服务器CPU占用率过高的问题排除过程
查看>>