特征选择,在数据集中查找和选择最有用的特征的过程,是机器学习管道的关键步骤。不必要的功能会降低训练速度,降低模型可解释性,最重要的是,会降低测试集的泛化性能。
由于ad-hoc功能选择方法感到沮丧,我发现自己一遍又一遍地申请机器学习问题,我在GitHub上用Python 编写了一个功能选择类。在FeatureSelector
包括了一些最常见的特征选择方法:
在本文中,我们将使用FeatureSelector
示例机器学习数据集。我们将看到它如何允许我们快速实现这些方法,从而实现更高效的工作流程。
完整的代码可以在GitHub上获得,我鼓励任何贡献。功能选择器是一项正在进行的工作,将根据社区需求继续改进!
对于此示例,我们将使用来自Kaggle 的Home Credit Default Risk机器学习竞赛的数据样本。(要开始参加比赛,请参阅此文章)。整个数据集可供下载,在这里我们将使用示例进行说明。
示例数据。TARGET是分类的标签
竞争是一种监督分类问题,这是一个很好的数据集,因为它有许多缺失值,众多高度相关(共线)特征,以及许多无关的功能,这些功能对机器学习模型没有帮助。
要创建FeatureSelector
类的实例,我们需要传入一个结构化数据集,其中包含列中行和特征的观察结果。我们可以使用一些仅具有特征的方法,但基于重要性的方法也需要训练标签。由于我们有一个监督分类任务,我们将使用一组功能和一组标签。
(确保在同一目录中运行它feature_selector.py
)
from feature_selector import FeatureSelector
# Features are in train and labels are in train_labels
fs = FeatureSelector(data = train, labels = train_labels)
功能选择器有五种方法可用于查找要删除的功能。我们可以访问任何已识别的功能并手动将其从数据中删除,或使用remove
功能选择器中的功能。
在这里,我们将介绍每种识别方法,并展示如何同时运行所有5种识别方法。在FeatureSelector
另外有几个策划能力,因为可视化检测数据是机器学习的重要组成部分。
查找要删除的要素的第一种方法很简单:查找具有高于指定阈值的缺失值的一小部分的要素。下面的调用标识了缺失值超过60%的特征(输出粗体)。
fs.identify_missing(missing_threshold = 0.6)
17 features with greater than 0.60 missing values.
我们可以在数据帧的每一列中看到缺失值的分数:
fs.missing_stats.head()
要查看标识为要删除的功能,我们将访问 Python dict 的ops
属性,FeatureSelector
其中功能为值中的列表。
missing_features = fs.ops ['missing']
missing_features [:5]
['OWN_CAR_AGE',
'YEARS_BUILD_AVG',
'COMMONAREA_AVG',
'FLOORSMIN_AVG',
'LIVINGAPARTMENTS_AVG']
最后,我们在所有特征中都有一个缺失值分布图:
fs.plot_missing()
共线特征是彼此高度相关的特征。在机器学习中,由于高方差和较少的模型可解释性,这些导致测试集上的泛化性能降低。
该identify_collinear
方法基于指定的相关系数值找到共线特征。对于每对相关特征,它标识要删除的一个特征(因为我们只需要删除一个):
fs.identify_collinear(correlation_threshold = 0.98)
21 features with a correlation magnitude greater than 0.98.
我们可以通过相关性进行的整洁可视化是热图。这显示了至少有一个高于阈值的相关性的所有功能:
fs.plot_collinear()
和以前一样,我们可以访问将要删除的整个相关要素列表,或者查看数据框中高度相关的要素对。
# list of collinear features to remove
collinear_features = fs.ops['collinear']
# dataframe of collinear features
fs.record_collinear.head()
如果我们想要研究我们的数据集,我们还可以通过传入plot_all = True
调用来绘制数据中所有相关性的图:
前两种方法可以应用于任何结构化数据集,并且是确定性的 - 对于给定阈值,每次结果都是相同的。下一种方法仅针对受监督的机器学习问题而设计,其中我们具有用于训练模型的标签并且是非确定性的。该identify_zero_importance
函数根据梯度增强机(GBM)学习模型找到具有零重要性的特征。
使用基于树的机器学习模型,例如增强集合,我们可以找到特征重要性。重要性的绝对值不如相对值重要,我们可以使用它来确定任务的最相关特征。我们还可以通过删除零重要性功能来使用要素重选来进行要素选择。在基于树的模型中,零重要性的特征不用于拆分任何节点,因此我们可以在不影响模型性能的情况下删除它们。
该FeatureSelector
查询条件功能使用梯度从增强机器重要性有关LightGBM库。功能重要性是GBM的10次训练运行的平均值,以减少差异。此外,模型使用早期停止和验证集进行训练(可以选择关闭它)以防止过度拟合训练数据。
下面的代码调用方法并提取零重要性功能:
# Pass in the appropriate parameters
fs.identify_zero_importance(task = 'classification',
eval_metric = 'auc',
n_iterations = 10,
early_stopping = True)
# list of zero importance features
zero_importance_features = fs.ops['zero_importance']
63 features with zero importance after one-hot encoding.
我们传入的参数如下:
task
:对应于我们的问题的“分类”或“回归”eval_metric
:用于提前停止的度量标准(如果禁用早期停止则不需要)n_iterations
:训练运行次数,以平均功能重要性early_stopping
:是否使用早期停止训练模型这次我们得到两个图plot_feature_importances
:
# plot the feature importances
fs.plot_feature_importances(threshold = 0.99, plot_n = 12)
124 features required for 0.99 of cumulative importance
在左侧,我们有plot_n
最重要的特征(根据标准化的重要性绘制,总和为1)。在右侧,我们具有累积重要性与特征数量。垂直线绘制在threshold
累积重要性,在这种情况下为99%。
基于重要性的方法有两个注意事项:
这应该不会产生重大影响(最重要的功能不会突然变得最少),但它会改变某些功能的顺序。它还可以影响所识别的零重要性特征的数量。如果功能重要性每次都在变化,请不要感到惊讶!
当我们进入功能删除阶段时,可以选择删除任何添加的单热编码功能。但是,如果我们在功能选择后进行机器学习,我们将不得不对功能进行单热编码!
下一个方法建立在零重要性函数的基础上,使用模型中的特征重要性进行进一步选择。该函数identify_low_importance
查找对指定总重要性没有贡献的最低重要性要素。
例如,下面的调用找到了实现99%总重要性所不需要的最不重要的功能:
fs.identify_low_importance(cumulative_importance = 0.99)
123 features required for cumulative importance of 0.99 after one hot encoding. 116 features do not contribute to cumulative importance of 0.99.
基于累积重要性和该信息的图,梯度增强机器认为许多特征与学习无关。同样,此方法的结果将在每次训练运行时发生变化。
要查看数据框中的所有要素重要性,请执行以下操作:
fs.feature_importances.head(10)
该low_importance
方法借鉴了使用主成分分析(PCA)的方法之一,其中通常只保留PC以保持一定百分比的方差(例如95%)。占总重要性的百分比基于相同的想法。
基于特征重要性的方法实际上只有在我们要使用基于树的模型进行预测时才适用。除了随机性之外,基于重要性的方法是一种黑盒方法,因为我们并不真正知道为什么模型认为这些特征是无关紧要的。如果使用这些方法,请多次运行它们以查看结果如何更改,并且可能创建具有不同参数的多个数据集以进行测试!
最后一种方法非常基本:查找具有单个唯一值的任何列。仅具有一个唯一值的功能对于机器学习无效,因为此功能的方差为零。例如,基于树的模型永远不能在仅具有一个值的要素上进行拆分(因为没有用于将观察分成的组)。
这里没有参数可供选择,与其他方法不同:
fs.identify_single_unique()
4 features with a single unique value.
我们可以绘制每个类别中唯一值数量的直方图:
fs.plot_unique()
要记住的一点NaNs
是在默认情况下在Pandas中计算唯一值之前丢弃。
一旦我们确定要丢弃的功能,我们有两个选项可以删除它们。要删除的所有功能都存储在ops
dict中FeatureSelector
,我们可以使用列表手动删除功能。另一种选择是使用remove
内置函数。
对于此方法,我们传入methods
用于删除功能。如果我们想要使用所有实现的方法,我们只需要传入methods = 'all'
。
# Remove the features from all methods (returns a df)
train_removed = fs.remove(methods = 'all')
['missing', 'single_unique', 'collinear', 'zero_importance', 'low_importance'] methods have been run Removed 140 features.
此方法返回已删除功能的数据框。还要删除在机器学习期间创建的单热编码功能:
train_removed_all = fs.remove(methods = 'all', keep_one_hot=False)
Removed 187 features including one-hot features.
在继续操作之前检查将要删除的功能可能是个好主意!原始数据集存储在备份的data
属性中FeatureSelector
!
我们可以使用所有这些方法,而不是单独使用这些方法identify_all
。这需要每个方法的参数字典:
fs.identify_all(selection_params = {'missing_threshold': 0.6,
'correlation_threshold': 0.98,
'task': 'classification',
'eval_metric': 'auc',
'cumulative_importance': 0.99})
151 total features out of 255 identified for removal after one-hot encoding.
请注意,由于我们重新运行模型,因此总功能的数量会发生变化。remove
然后可以调用该函数来丢弃这些功能。
Feature Selector类在训练机器学习模型之前实现了几种用于删除功能的常用操作。它提供了识别要删除的功能以及可视化的功能。方法可以单独运行,也可以一次运行,以实现高效的工作流程。
的missing
,collinear
和single_unique
方法是确定性的,而基于特征的重要性的方法将每次运行时改变。特征选择与机器学习领域非常相似,主要是经验性的,需要测试多种组合才能找到最佳答案。最好在管道中尝试多种配置,功能选择器提供了一种快速评估特征选择参数的方法。
一如既往,我欢迎反馈和建设性的批评。我想强调我正在寻求帮助FeatureSelector
。任何人都可以在GitHub上做出贡献,我很欣赏那些只使用该工具的人的建议!我也可以通过Twitter @koehrsen_will与我联系。
原文:https://towardsdatascience.com/a-feature-selection-tool-for-machine-learning-in-python-b64dd23710f0