文章目录
写在前面
本文的特征选择的内容是对菜菜老师的机器学习课程:机器学习sklearn入门教程:数据预处理与特征工程中的特征选择的内容进行的整理
特征工程概述
坊间常说:“数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已”。
了解特征工程,其定义是利用数据领域的相关知识来创建能够使机器学习算法达到最佳性能的特征的过程。特征工程就是把原始数据转变成为特征的过程。
特征工程有三大块。
-
特征提取
特征提取一般是在特征选择之前,它提取的对象是原始数据。其目的是将原始数据转换为一组具有明显统计意义的特征。
-
特征选择
从给定的特征集合中选出相关特征子集的过程。
1、相关特征:对当前学习任务有用的属性或者特征。
2、无关特征:对当前学习任务没用的属性或者特征。
特征选择的选择依据:
1、特征是否发散:如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本没有差异,这个特征对于样本的区分并没有什么作用。
2、特征与目标的相关性:与目标的相关性越高的特征,应当优先选择。
特征选择的常用方法(关于特征选择的常用方法,下面会展开点讲):
1、过滤式(Filter过滤法)
2、包裹式(包装法)
2、嵌入式(Embedded嵌入法)
-
特征构建
从原始的数据中人工的构建新的特征。需要花时间去观察原始数据,思考问题的潜在形式和数据结构,对数据敏感性和机器学习实战经验能帮助特征构建。
以上就是特征工程的三个流程,下面我们展开谈谈特征选择。
特征选择
特征选择的第一步我认为是:理解业务,但是在真正的数据应用领域,比如金融、医疗、电商,其中的特征集更为复杂和庞大,我们无法依赖本身对业务的理解来选择特征。我们有三种方法来用于选择特征。
-
过滤式(Filter过滤法)
Filter过滤法会对模型的性能有影响吗?答案是不一定,要依赖所使用的模型来评估,过滤特征的主要目的还是在维持算法表现的前提下,帮助算法降低计算量。
-
方差过滤
设定阈值,过滤方差低于阈值的特征
from sklearn.feature_selection import VarianceThreshold #VarianceThreshold()里传递阈值threshold,默认为0 x_var0 = VarianceThreshold().fit_transform(x) x_var0.shape
注:假如我们想一步到位,把特征总数减半,那么我们只需找到特征方差的中位数,再把这个中位数作为threshold参数传入VarianceThreshold()。
当特征是伯努利随机变量时(也就是特征取值为0和1),我们可以这么剔除特征
from sklearn.feature_selection import VarianceThreshold #假设p = 0.8,即二分类特征中某种分类占到80%以上的时候剔除特征 x_var0 = VarianceThreshold(0.8*(1-0.8)).fit_transform(x) x_var0.shape
-
卡方过滤
卡方过滤是专门针对离散型标签的相关性过滤
from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 #利用卡方检验,选择K个最好的特征,返回选择特征后的数据 x_fschi = SelectKBest(chi2, k=300).fit_transform(x,y)
注:我们该怎么选择k值,有一种答案是绘制学习曲线。
import matplotlib.pyplot as plt from sklearn.feature_selection import chi2 from sklearn.model_selection import cross_val_score from sklearn.feature_selection import SelectKBest from sklearn.tree import RandomForestClassifier as RFC score = [] for i in range(390,200,-10): x_fschi = SelectKBest(chi2,k = i).fit_transform(x,y) once = cross_val_score(RFC(n_estimators = 10,random_state = 0),x_fschi,y,cv = 5).mean() score.append(once) plt.plot(range(350,200,-10),score) plt.show()
但是在绘制学习曲线的时候,运行时间会有点长,下面介绍到的相关性系数选择是一个选择k值更好的方法。
-
相关性系数选择
计算各个特征对标签的相关系数,常用的就是使用皮尔逊相关系数P来做衡量,给定我们想筛选出来的特征个数即可,注意当p值 <= 0.05说明两组数据(特征和标签)是相关的,常用来和卡方检验配合使用,负责计算出想要保留的特征数k值
from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 chivalue,pvalues_chi = chi2(x,y) #我们想消除所有p值大于设定值(0.05)的特征 k = chivalue.shape[0] - (values_chi > 0.05).sum() x_fschi = SelectKBest(chi2, k=k).fit_transform(x,y)
-
F检验
又称ANOVA,方差齐性检验,是用来捕捉每个特征与标签之间的线性关系的过滤方法,F检验既可以做回归也可以做分类,其中F检验分类用于标签是离散型变量的数据,而F检验回归用于标签是连续型变量的数据,值得注意的是F检验在数据呈正态分布时的效果更好
from sklearn.feature_selection import f_classif from sklearn.feature_selection import SelectKBest F,pvalues_f = f_classif(x,y) k = F.shape[0] - (pvalues_f > 0.05).sum() x_fsF = SelectKBest(f_classif, k=k).fit_transform(x,y)
-
互信息法
互信息法是用来捕捉每个特征和标签之间的任意关系(包括线性关系和非线性关系)的过滤方法。
from sklearn.feature_selection import mutual_info_classif as MIC from sklearn.feature_selection import SelectKBest result = MIC(x,y) k = result.shape[0] - sum(result <= 0) x_fsmic = SelectKBest(MIC, k=k).fit_transform(x,y)
-
-
嵌入式(Embedded嵌入法)
嵌入法是一种让算法自己决定采用哪些特征的方法,即特征选择和算法训练同时进行,在使用嵌入法的同时,我们先使用某些机器学习算法和模型进行训练,得到各个特征的权值系数,根据权值系数从大到小排列选择权值系数大的特征。嵌入法可谓是过滤法的进化版,它能自动地剔除掉无关的特征和无区分度的特征。
from sklearn.feature_selection import SelectFromModel from sklearn.tree import RandomForestClassifier as RFC RFC_ = RFC(n_estimators = 10,random_state = 0) #特征重要性低于0.005这个阈值的特征都被砍掉,可能砍掉很多特征 x_embedded = SelectFromModel(RFC_,threshold = 0.005).fit_transform(x,y)
注:阈值是个超参数,我们很难确定阈值的取值,可以通过绘制学习曲线,判断模型在不同阈值取值下的表现来决定取哪些阈值。
import matplotlib.pyplot as plt from sklearn.tree import RandomForestClassifier as RFC import numpy RFC_ = RFC(n_estimators = 10,random_state = 0) threshold = np.linespace(0,(RFC_.fit(x,y).feature_importances_).max(),20) score = [] for i in threshold: x_embedded = SelectFromModel(RFC_,threshold = i).fit_transform(x,y) once = cross_val_score(RFC_,x_embedded,y,cv = 5).mean() score.append(once) plt.plot(threshold,score) plt.show()
-
包裹式(wrapper包装法)
包装法也是一个特征选择和算法训练同时进行的方法,与嵌入法十分相似,但不同的是,我们往往使用一个目标函数来帮助我们选择特征,而不是自己输入某个评估指标或阈值。包装法在初始特征集上训练评估,可通过feature_importances_属性获得每个特征的重要性。然后,从当前的一组特征中选取特征。在修剪的集合上递归地重复该过程,直到最终到达所需数量的要选择的特征。包装法所需要的计算成本位于嵌入法和过滤法中间。
from sklearn.feature_selection import RFE from sklearn.tree import RandomForestClassifier as RFC #随机森林模型 RFC_ = RFC(n_estimators = 10,random_state = 0) #实例化选取特征的学习器 selector = RFE(RFC_,n_features_to_select = 340,step = 50).fit(x,y) #selector.support_返回所有特征中特征是否保留的布尔矩阵 selector.support_.sum() #selector.ranking_返回特征的按数次迭代中综合重要性的排名 selector.ranking_ x_wrapper = selector.transform(x)
注:n_features_to_select也是个超参数,我们可以通过绘制学习曲线来决定取哪个值(也就是我们要保留的特征数)。