转载自:https://www.itcodemonkey.com/article/5560.html
来自:优达学城Udacity(微信号:youdaxue),作者:William Koehrsen,译者:之肴
FeatureSelector完整的代码放在GitHub上(https://github.com/WillKoehrsen/feature-selector),欢迎任何contributions。特征选择器还在锐意制作中,将根据社区需求继续改进!
可处理处理一些最常见的特征:
缺失值多的特征
共线(高度相关)特征
树模型中零重要性的特征
低重要性的特征
有单一值的特征
1、示例数据集
我们用到的数据集来自 Kaggle 上的 Home Credit Default Risk machine learning competition ,数据集可供下载,我们会用其中一部分数据作为示范。
数据集下载:https://www.kaggle.com/c/home-credit-default-risk/data
这个比赛聚焦于监督式分类问题,用它的原因是因为它有很多缺失值,有很多高度相关的(共线)特征,也有一些对机器学习模型没什么用的不相关特征。
2、创建实例
要创建 FeatureSelector 类的实例,我们需要传入一个结构化数据集,其中包含行上的结果和列上的特征。我们可以用一些只需要特征的方法,但一些基于重要性的方法也需要训练标签。又因为这是个监督式分类问题,因此我们将使用一组特征和一组标签。
记住,确保在和feature_selector.py相同的目录下运行
3、方法
特征选择器有五种删除特征的方法。 我们可以访问任何已识别的特征然后手动将其从数据中删除,或者使用特征选择器中的删除特征。
接下来我会挨个介绍每种方法,并展示如何同时运行他们。 FeatureSelector 还具有多种绘图功能,亲眼看看数据也是机器学习的重要组成部分。
1)缺失值
第一种删特征的方法很简单:找到缺失值高于指定阈值的特征。 下面的函数调用标出了缺失值超过60%的特征(粗体是输出值)。
我们可以在数据栏的每一列中看到缺失值的分数:
我们可以通过 FeatureSelector 的 ops 属性,来看看哪些特征会被删除,ops 是 Python 中的 dict,特征被列入值中。
最后,我们画了张缺失值分布图:
2)共线特征
共线特征是彼此高度相关的特征。 在机器学习中,由于高方差和较低的模型可解释性,共线特征会导致测试集上的泛化性能降低。
identify_collinear方法能基于指定的相关系数值找到共线特征。 对于每对相关特征,它会标出其中一个特征来删除(因为我们只需要删除一个):
我们可以用热图来对相关性进行可视化。 它能展示特征之间或多或少都有相关性:
和之前同理,我们可以查看将要删除的相关特征列表,或者查看数据栏中高相关的特征。
如果我们想要研究数据集,我们还可以通过设置plot_all = True来绘制数据中所有具备相关性的图:
3)零重要特征
前两种方法可以应用于任何结构化数据集,并且具备确定性 ——对于给定阈值,每次结果都是相同的。 而这种方法仅针对监督式机器学习问题而设计,训练的模型有相应标签,而且是非确定性的。
identify_zero_importance 函数根据梯度增强机器学习模型(GBM)找到具有零重要性的特征。
我们可以用例如增强集成之类的基于树的机器学习模型,来找到特征的重要性。 重要性的绝对值没有相对值重要,我们可以用它来确定问题中最为相关的特征,或者删除零重要性特征。 在基于树的模型中,零重要性的特征不会拆分任何节点,因此我们可以在不影响模型性能的情况下删除它们。
FeatureSelector 使用 LightGBM 库中的渐变增强模型来寻找特征重要性。 所得出的值取 GBM 训练 10 次后的平均值,以减少差异。 除此之外,模型可以用验证集提前停止(或者选择关闭)以防止过拟合训练数据。
* LightGBM:http://lightgbm.readthedocs.io/en/latest/
下面的代码调用方法并提取零重要性特征:
传递的参数如下:
•task:对应问题分别为“分类”或“回归”
•eval_metric:衡量提前停止的指标(如果禁用提前停止就不需要)
•n_iterations:为了平均特征重要性所需的训练次数
•early_stopping:是否使用提前停止来训练模型
这次我们得到两个plot_feature_importances的图:
上图,我们有plot_n个最重要的特征(将重要性归一化后绘制,总和为1)。 下图,x轴为特征数量,y轴为累积重要性。 垂线为累积重要性的阈值,此图中为99%。
基于重要性的方法有两个注意事项:
•梯度增强的训练是随机的,这意味着每次运行模型时特征重要性都会改变。这应该不会产生重大影响(最重要的特征不会突然变得最少),但它会改变某些特征的顺序。 它还可以影响所识别的零重要性特征的数量。 如果看到特征重要性每次都在变化,不用大惊小怪!
•为了训练机器学习模型,这些特征会首先被独热编码。 这意味着被识别为具有零重要性的一些特征可能是在建模期间被加进来的。
当我们进入特征删除阶段时,可以选择删除任何添加的独热编码特征。 但是如果我们在特征选择后进行机器学习,我们还是得对特征独热编码一遍!
4)低重要性特征
这个方法建立在零重要性函数的基础上,它会利用模型中的特征重要性进行进一步选择。 函数identify_low_importance能找到那些对总重要性没有贡献的低重要性特征。
举个例子,下面的函数调用找到了对实现99%总重要性不怎么重要的特征:
基于累积重要性的那张图,梯度增强会认为许多特征与学习过程无关。 和零重要性一样,此方法的结果会在每次训练运行时发生变化。
要查看数据栏中的所有特征的重要性,请执行以下操作:
low_importance方法借鉴了一种使用主成分分析(PCA)的方法,其中通常只保留有一定百分比方差的主成分(例如95%)。 保留多少总重要性也是相同思路。
实际上,我们只有在要使用基于树的模型进行预测时才会用基于特征重要性的方法。 因为除了随机性之外,基于重要性的方法也是一种黑盒方法,我们并不实际知道为什么模型认为这些特征是无关紧要的。 如果真要用这些方法,请多次运行它们以查看结果变化如何,并且尽可能创建具有不同参数的多个数据集来进行测试!
5)单一特征值
最后一种方法更为基本:查找只有单一值的列。 只有单一值的特征对于机器学习无效,因为此特征的方差为零。 例如,基于树的模型永远不能在只有一个值的特征上进行拆分(因为这样就没有组可以分了)。
和其它方法不同,此函数没有参数可供选择:
我们可以给每个类别中唯一值的数量画张直方图:
需要记住的一点是,默认情况下,在计算Pandas中的唯一值之前会去掉NaN。
6)删除特征
一旦确定要删除的特征,我们有两个办法来删掉它们。 由于要删除的所有特征都存储在FeatureSelector的ops dict中,我们可以使用这个列表手动删除。 另一种选择是使用内置的remove函数。如果你想试试用所有手段删除后的效果,需要将参数设置为methods = ‘all’。
它会返回已删除特征的数据栏。 为了一并删除机器学习期间创建的独热编码特征,还得这么做:
最好在继续操作之前检查下要删除的特征! 原始数据集作为备份存储在FeatureSelector的data属性中!
7)一次运行所有方法
与其单独使用这些方法,我们可以将所有方法与identify_all共同使用。 这就得为每个方法设个参数:
注意,由于重新运行模型,总特征的数量会发生变化。 这之后可以调用remove函数来删除这些特征。
3、结论
Feature Selector 在训练机器学习模型之前实现了几种用于删除特征的常用操作。 它能识别要删除的特征还可能进行可视化。每个方法可以单独运行,也可以集体运行,实现高效的工作流程。
缺失值、共线和单一值方法具备确定性,而基于特征重要性的方法将随每次运行而改变。 特征选择与机器学习领域非常相似,需要根据经验测试多种组合以找到最佳答案。 最好在工作流程中尝试多种配置,特征选择器提供了一种快速评估特征选择参数的方法。