数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。
特征选择的几个常用方法:
一、过滤法
1、方差过滤
过滤法的主要对象:需要遍历特征或者升维的算法们(KNN,单棵决策树。支持向量机SVM、神经网络、回归算法)。因为他们需要遍历特征或者升维的特点,所以这些算法本身的运算量就很大,需要的时间就很长。因此方差过滤这样的特征选择对他们来说就尤为重要。但对于不需要遍历特征的算法,比如随机森林,它选取特征进行分枝,本身运算就非常快速,因此特征选择对它们来说效果平平。
过滤法的主要目的:在维持算法表现的前提下,帮助算法们降低计算成本(减少时间)。
现实中,我们只会使用阈值为0或者阈值很小的方差来过滤,为我们优先消除一些明显用不到的特征,然后会选择更优的特征选择方法继续削减特征数量。
2、相关性过滤
2.1卡方检验
卡方过滤不能计算负数,否则要先进行数据预处理:标准化(让所有值都在0以上)或者归一化(让所有的数都在0~1之间)
2.2、F检验
F检验是用来捕捉每个特征与标签之间的线性关系的过滤方法。可以做分类,也可以做回归,因此包含feature_selection.f_classif(分类)he feature_selection.f_regression(回归)。F检验分类用于标签是离散型变量的数据,F检验回归用于标签是连续型变量的数据。
需要注意的是,F检验在数据服从正态分布时效果会非常稳定,所以使用F检验前可以先将数据转换成服从正态分布的方式。
2.3、互信息法
互信息法是用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系的过滤方法)。它也是可以做回归也可以做分类,包含feature_selection.mutual_info_classif(互信息分类)和feature_selection.mutual_info_regression(互信息回归)两个类。这两个类的用法和参数都和F检验类似,只不过互信息法比F检验更加强大,F检验只能找出线性关系。
互信息法不返回p值或F值类似的统计量,它返回“每个特征与目标之间的互信息量的估计”,这个值的取值范围为0~1,为0则表示两个变量独立,为1则表示两个变量完全相关。
(一般情况下,使用过滤法进行特征选择,会先使用方差过滤,再使用互信息法过滤)
二、Embedded嵌入法
嵌入法是一种让算法自己决定使用哪些特征的方法,即特征选择和算法训练同事进行。它会得出各个特征去权值系数,根据权值系数从大到小选择权值系数大的特征。权值系数代表特征对于模型的某种贡献或某种重要性。比如决策树和树的集成模型中的属性feature_importance,可以返回各个特征对树的建立的贡献。因此无关的特征(需要相关性过滤的特征)和无区分度的特征(需要方差过滤的特征)都会因为缺乏对模型的贡献而被删除掉,可以说是过滤法的进化版。
缺点:
过滤法中使用的统计量可以使用统计只是和常识来查找范围(如p值应当低于显著性水平0.05),而嵌入法中使用的权值系数却没有这样的范围可以找,在这种情况下,模型权值就是我们的超参数局,或许我们需要学习曲线,或者根据模型本身的某些性质去判断这个超参数的最佳值酒精是多少。
另外,嵌入法每次挑选都会使用全部特征,因此计算速度也会和应用的算法有很大的关系,如果采用计算量很大,计算缓慢的算法,嵌入法本身也会非常耗时耗力。并且在选择完毕后,我们还是需要进行模型的评估。
sklearn.feature_selection_SelectFromModel 这个类就是嵌入法。SelectFromModel 是一个元变换器,可以与任何拟合后具有coef_,eature_importances_属性的算法,或者参数中具有可惩罚项的评估器一起使用(比如随机森林和树模型就具有属性feature_importances_,逻辑回归就带有l1和l2惩罚项,线性支持向量机也支持l2惩罚项)。
对于有feature_importances_的模型来说,若重要性低于提供的阈值参数,则认为这些特征不重要并且会被移除,feature_importances_的取值范围是[0,1]。
参数:
estimator:输入想要执行的算法。(只要是带有coef_,eature_importances_属性的算法,或者参数中具有可惩罚项的评估器都可以)
threshold:特征重要性阈值。
三、Wrapper包装法
包装法也是一个特征选择和算法训练同时进行的方法,与嵌入法十分类似,它也是依赖于算法自身的选择,比如coef_属性或feature_importances_属性来完成特征选择。但不同的是,使用的算法不是我们用来分类或者回归的算法模型(不是XGBoost),而是一个专业的数据挖掘算法。即目标函数,这些数据挖掘算法的核心功能就是选取最佳特征子集。
最典型的目标函数是递归特征消除法(Recursive feature elimination,简写为RFE)。在sklearn中使用的类是feature_selection.RFE,代码:class sklearn.feature_selection.RFE(estimator,n_features_to_select=None,step=1,verbose=0)
其中重要的参数是estimator和n_feature_to_select。参数estimator是需要填写的实例化的评估器,n_feature_to_select是想要选择的特征个数。step是每次迭代中希望移除的特征个数。除此之外,REF类中有两个很重要的属性,.support_:返回所有的特征最后是否被选中的布尔矩阵,.ranking_:返回特征的按次数迭代中综合重要性的排名。类feature_selection.RFECV会在交叉验证循环中执行RFE以找到最佳数量的特征,增加参数CV,其他用法都和RFE一模一样。
包装法在初始特征集上训练评估器,并且通过coef_属性或feature_importances_属性来获得每个特征的重要性。然后从当前的一组特征中修剪掉最不重要的特征。在修剪的集合上递归地重复该过程,直到最终达到所需数量的要选择的特征。由于嵌入法每次都是使用全部的特征进行重复筛选,而包装法每次都会删掉一部分不重要的特征,再进行下一步的筛选,所以包装法需要的计算成本位于嵌入法和过滤法中间。
总结:
经验来说,过滤法更快速,但更粗糙,包装法和嵌入法更精确,比较适合具体到算法去调整,但计算量比较大,运行时间长。当数据量很大的时候,优先使用方差过滤和互信息法调整,再进行其他特征选择方法。使用逻辑回归时,优先使用嵌入法,使用支持向量机时,优先使用包装法。
特征选择只是特征工程的第一步,真正的高手往往是使用特征创造或特征提取来寻找高级特征。在kaggle之类的算法竞赛中,很多高分团队都是在高级特征上做文章,而这是比调参和特征选择更难的,提升算法表现的高深方法,非常依赖于经验和尝试。