机器学习中特征选择的三种可选方法选择归纳为三种,即“过滤方法”、“包装方法”和“嵌入方法”。在“FilterMethods”中,我们使用统计检验的方法,即基于特征分布来进行特征选择。这种方法计算速度很快,但实际上并没有为模型选择好的特征。此外,当我们拥有大型数据集时,统计检验的p值通常非常小,被放大为无关紧要的分布中显着的小差异。WrapperMethods类别包括贪婪算法,这些算法基于前向、后向或穷举搜索尝试所有可能的特征组合。对于每个特征组合,通常使用交叉验证来训练机器学习模型以准确测量模型性能。因此,包装方法在计算上很昂贵并且通常难以实现。另一方面,嵌入式方法训练单个机器学习模型并根据模型返回的特征重要性进行特征选择。它们在实践中工作得非常好,并且计算速度更快。但这种方法有三个主要缺点:我们无法从所有机器学习模型中推导出特征重要性值。共线性影响线性模型返回的系数值,或基于决策树的算法返回的重要性值,可能会掩盖它们的真正重要性。基于决策树的算法在非常大的特征空间中可能表现不佳,因此,它们的显着性值可能不可靠。过滤器方法晦涩难懂,在实践中不常用;包装方法的计算成本很高,而且通常无法实现;嵌入式方法并不适用于所有场景或所有机器学习模型。那么,我们还能如何为此选择预测特征呢?幸运的是,有更多的方法可以为监督学习选择特征。在这篇文章中,我将详细介绍三种基于模型性能的精选特征算法,因为它们兼具封装方法和嵌入方法的特点,它们通常被称为“混合方法(HybridMethods)”,一些依赖多次训练的机器学习模型有点像包装器。一些选择程序依赖于特征的重要性,有点像嵌入。FeatureSelectionAlternatives?这些方法已成功应用于工业或数据科学竞赛,并提供了训练特定机器模型进行特征预测的方法。在本文中,我将展示其中一些特征选择方法的逻辑和流程,并展示如何使用开源库Feature-engine在Python中实现它们。我们将讨论以下三种特征选择方法:featureshufflingfeatureperformancetargetaverageperformancefeatureshuffling按模型性能得分降序排列。改变特征值的顺序(在数据集的各个行中)会改变特征与目标之间的原始关系,因此模型性能得分的下降方向表明模型对该特征的依赖程度。具体过程如下:训练机器学习模型并确定其性能。选择要重新排序的功能。用第1步训练的模型进行预测,得到第2步选择的特征的性能值。如果第3步得到的特征性能值低于阈值,则保留该特征,否则删除该特征。从步骤2开始重复,直到检查完所有功能。通过变换特征进行选择有几个优点。首先,我们只需要训练一个机器学习模型,然后使用机器学习模型重新排列特征值;其次,我们可以选择有监督的机器学习模型特征。第三,这个选择过程可以使用开源代码来实现,具体方法将在下面的段落中描述。优点:只训练一种机器学习模型,所以速度很快。适用于任何监督机器学习模型。您可以使用Python开源库Feature-engine。缺点是如果两个特征相关,当其中一个特征受到干扰时,机器学习模型仍然可以通过其相关变量获取相应的信息,这可能会导致两个相关特征的重要性值出现偏差。低,即使它们实际上可能很重要。此外,为了选择特征,我们需要定义一个重要性阈值,低于该阈值的特征将被删除。阈值越高,选择的特征越少。最后,特征重排引入了随机性元素,因此对于重要性值接近阈值的特征,不同的算法运行可能会返回不同的特征子集。注意事项:相关特征可能会影响特征重要性的解释。用户需要定义一个阈值。随机因素使选择过程具有不确定性。考虑到这一点,特征排列突出了那些直接影响模型性能的变量,是一种很好的特征选择方法,我们可以用Scikit-learn手动推导排列重要性,然后选择那些重要性似乎高于某个阈值的变量。或者,我们可以使用特征引擎来自动化整个过程。Python实现?让我们看看如何使用特征引擎通过特征重排进行选择。我们采用Scikit-learn自带的糖尿病数据集。首先,加载数据:importpandasasppdffromsklearn.datasetsimportload_diabetesfromsklearn.linear_modelimportLinearRegressionfromfeature_engine.selectionimportSelectByShuffling#loaddatasetdiabetes_X,diabetes_y=load_diabetes(return_X_y=True)X=pd.DataFramed_Frame(Dataset)diabetes_y)接下来,构建感兴趣的机器学习模型:#初始化线性回归estimatorlinear_model=LinearRegression()我们将使用3折交叉验证进行基于评分下降的特征选择=''r2":#初始化特征选择器=SelectByShuffling(estimator=linear_model,scoring="r2",cv=3)transformer使用fit()方法寻找重要变量(即shuffling时导致r2下降的变量)。默认情况下,如果性能下降大于所有特征引起的平均下降,然后选择该特征。#fittransformertr.fit(X,y)使用transform()方法从数据集中删除未选择的特征:Xt=tr.transform(X)我们可以通过转换器的一个属性查询每个特征的重要性:tr。performance_drifts_{0:-0.02368121940502793,1:0.017909161264480666,2:0.18565460365508413,3:0.07655405817715671,4:0.4327180164470878,5:0.16394693824418372,6:-0.012876023845921625,7:0.01048781540981647,8:0.3921465005640224,9:-0.01427065640301245}我们可以通过另An属性访问要删除的特征的名称:tr.features_to_drop_[0,1,3,6,7,9]像这样的简单操作,我们在Xt中有一个减少的数据框。特征性能?确定特征重要性的一种直接方法是训练仅具有该特征的机器学习模型。在这种情况下,特征的“重要性”由模型的性能得分给出。也就是说,在单个特征上训练的模型对目标的预测效果如何。性能分数低表示功能薄弱或不可预测。过程如下:为每个特征训练一个机器学习模型。对每个模型进行目标预测并确定模型性能。选择性能指标高于阈值的特征。在这个选择过程中,我们为每个特征训练了一个机器学习模型。该模型使用单个特征来预测目标变量。然后,使用交叉验证计算模型的性能,最后选择性能超过设定阈值的特征。一方面,由于需要训练的模型数量多,同一数据集中的特征数量多,这种方法的计算成本较高。另一方面,在单个特征上训练的模型往往非常快。使用这种方法,我们可以学习感兴趣特征的模型,因为它们的重要性由性能指标决定。缺点是我们需要为特征选择提供一个阈值。阈值越高,选择的特征组越少。有些阈值是相当直观的,例如,如果性能指标是roc-auc,我们可以选择性能在0.5以上的特征。对于其他指标,比如准确率,我们不知道阈值设置多少才合理。优点:适用于任何受监督的机器学习模型。可以单独探索功能,避免相关性问题。您可以使用Python开源项目Feature-engine。注意事项:为每个特征训练模型在计算上是昂贵的。用户需要自定义阈值。无法识别关联的功能。我们可以使用Feature-engine来实现单特征性能的选择。Python实现?在Scikit-learn中加载糖尿病数据集:importpandasasppdffromsklearn.datasetsimportload_diabetesfromsklearn.linear_modelimportLinearRegressionfromfeature_engine.selectionimportSelectBySingleFeaturePerformance#loaddatasetdiabetes_X,diabetes_F=load_diabetes_X(retdiabetes_X)y=pd.DataFrame(diabetes_y)使用线性回归和3折交叉验证选择r2>0.01的特征。#初始化特征selectorsel=SelectBySingleFeaturePerformance(estimator=LinearRegression(),scoring="r2",cv=3,threshold=0.01)转换器使用fit()方法为每个特征拟合一个模型,计算其性能,并选择重要特征。#fittransformerssel.fit(X,y)我们可以查看将被丢弃的特征:我们可以查看将被丢弃的特征:sel.features_to_drop_[1]我们还可以检查每个特征的性能:sel.feature_performance_{0:0.029231969375784466,1:-0.003738551760264386,2:0.336620809987693,3:0.19219056680145055,4:0.037115559827549806,5:0.017854228256932614,6:0.15153886177526896,7:0.17721609966501747,8:0.3149462084418813,9:0.13876602125792703}通过transform()方法,我们从数据集中移出特征:#dropvariablesXt=sel.transform(X)所以我们得到一个减少的数据集。目标平均性能?我现在要讨论的选择方法是Miller和他的同事在KDD2009数据科学竞赛中介绍的。作者没有为该技术指定任何名称,但由于它使用每组数据的平均目标值作为预测变量,我喜欢将此技术称为“目标平均性能选择”。这种选择方法还为每个特征分配了一个“重要性”值。这个重要性值是根据性能指标来确定的。有趣的是,这个模型没有训练任何机器学习模型。相反,它使用一个非常简单的指标值来进行预测。简而言之,这种选择方法使用每个类别或每个间隔(如果变量是连续的)的平均目标值作为预测变量。从这个预测中,可以得到一个性能指标,如r2、准确性或任何其他根据事实评估预测的指标。那么这种选择方法究竟是如何工作的呢?对于分类变量:将数据框拆分为训练集和测试集。对于每个类别项目,计算每个项目的平均目标值(使用训练集)。用该类别的目标均值替换测试集中的每个类别项目。使用编码的特征和目标值(在测试集中)计算性能指标。选择性能高于阈值的特征。对于每个类别项,根据训练集确定其目标对每个类别的均值。然后,将测试集中的每个类别项替换为刚刚学习的目标平均值,这些值用于确定性能指标。对于连续变量,过程类似于分类变量的情况:将数据帧拆分为训练集和测试集。对于每一个连续的特征,它将值排序到离散的区间中(这一步使用训练集)。确定每个间隔的平均目标值(使用训练集)。将测试集中的变量按照步骤2中合适的区间进行排序,将测试集中对应区间内的值替换为对应区间的目标均值。对于测试集,它们之间的性能指标是使用特定的编码特征和目标计算的。选择性能高于阈值的特征。对于连续变量,作者首先将所有项分成不同的组,这个过程也称为离散化。他们使用1%分位数,然后计算训练集中每个组的目标均值,用相应区间的目标均值替换测试集的相应区间,并评估性能。这种特征选择方法非常简单;它计算每个区间(类别或区间)的平均值,并使用这些值来获得性能指标。虽然简单,但它有几个优点:首先,它不需要训练机器学习模型,所以计算速度非常快。其次,它捕获与对象的非线性关系。第三,与大多数现有的选择算法不同,它适用于分类变量。它也适用于异常值的处理,因为这些极值会被分配到一个极值组中。根据作者的描述,这种方法可以为分类或数值变量提供更客观的表现。此外,它与模型无关。理论上,该操作选择的特征应该适用于任何机器学习模型。优点:因为不需要训练机器学习模型,所以速度比较快。适用于分类变量和数值变量。可以处理异常值的情况。可以捕获特征和对象之间的非线性关系。不受型号限制。这种选择方法也有一定的局限性。首先,对于连续变量,用户需要定义任意数量的区间来对值进行排序。这对偏态变量提出了一个问题,其中大多数偏态变量数据可能只属于同一组。其次,不经常标记的分类变量可能会导致不可靠的结果,因为这些类别的数据很少,而且此类类别的平均目标值不可靠。在极端情况下,如果某个类不在训练集中,那么我们将无法得到一个平均目标值来计算性能。注意事项:它需要调整偏态变量的间隔数。稀有类可能会提供不可靠的性能指标,或者无法应用此方法。考虑到这些因素,我们可以使用特征引擎根据目标平均性能来选择变量。Python实现?我们将使用此方法从泰坦尼克号数据集中选择变量,该数据集是数值变量和分类变量的混合体。加载数据时,为了演示目的,我会进行一些预处理,然后将其拆分为训练集和测试集。将熊猫导入为pdimportnumpy作为npfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportroc_auc_scorefromfeature_engine.selectionimportSelectByTargetMeanPerformance#loaddatadata=pd.read_csv('https://www.openml.org/data/get_csv/16826755/phpMYEkMl')#提取客舱字母data['cabin']=data['cabin'].str[0]#用Ndata['cabin']=np.where(data['cabin'].isin(['T','G']),'N',data['cabin'])#capmaximumvaluesdata['parch']=np.where(data['parch']>3,3,data['parch'])data['sibsp']=np.where(data['sibsp']>3,3,data['sibsp'])#将变量转换为对象以作为分类数据[['pclass','sibsp','parch']]=data[['pclass','sibsp','parch']].astype('O')#分离训练集和测试集X_train,X_test,y_train,y_test=train_test_split(data.drop(['survived'],axis=1),data['survived'],test_size=0.3,random_state=0)我们将基于roc-auc,使用2折交验证进入行特征选择。首先要注意的是特征引擎允许我们使用交叉验证,这是对作者描述的原始方法的改进。特征引擎还允许我们决定如何分隔数字变量。我们可以选择等频或等宽间隔。作者使用了1%的分位数,这适用于值分布合理的连续变量,但通常不适用于偏态变量。在这个例子中,我们将数值变量分成相等的频率间隔。最后,我们要选择roc-auc大于0.6的特征。#特征引擎自动选择#分类和数值变量sel=SelectByTargetMeanPerformance(variables=None,scoring="roc_auc_score",threshold=0.6,bins=3,strategy="equal_frequency",cv=2,#crossvalidation1random_state=,#seedforreproducibility)使用fit()方法,transformer可以:用目标均值替换类别对频率相同的数值变量进行分类用目标均值替换区间内的变量编码变量returnroc-aucselectionForROC-AUC>0.6的功能我们可以为每个功能计算ROC-AUC:SEL.Feature_Performance_{'pClass':0.6802934787230475,'sex':0.74913652252482871,'age''fare':0.6600883312700917,'cabin':0.6379782658154696,'embarked':0.5672382248783936}我们可以找到将从数据中删除的特征:sel.features_to_drop_['park'']使用transform()方法,我们可以删除来自数据的特征aset:#removefeaturesX_train=sel.transform(X_train)X_test=sel.transform(X_test)就是这样,现在我们有了训练集和测试集的压缩版。摘要?过滤器、包装器、嵌入和混合特征选择方法在Python中的实现,请查看Scikit-learn、MLXtend和特征引擎中的选择模块。这些库随附大量文档,可帮助您了解基本方法。译者介绍?赵庆尧,社区编辑,从事驱动开发多年。他的研究兴趣包括安全操作系统和网络安全。曾获陕西赛区数学建模奖,发表网络相关专利。
