当前位置: 首页 > 科技观察

使用XGBoost在Python中进行特征重要性分析和特征选择

时间:2023-03-20 00:37:43 科技观察

转载本文请联系Python中文社区公众号。使用梯度提升等决策树方法的集成的好处是它们可以自动提供来自训练有素的预测模型的特征重要性估计。在本文中,您将了解如何使用Python中的XGBoost库来估计预测建模问题的特征重要性,阅读本文后,您将了解:如何使用梯度提升算法计算特征重要性。如何绘制由XGBoost模型计算的Python中的特征重要性。如何使用XGBoost计算的特征重要性进行特征选择。梯度提升中的特征重要性使用梯度提升的好处是在构建提升树后检索每个属性的重要性分数相对简单。通常,重要性提供一个分数,指示每个特征在模型中构建增强决策树时的有用性或价值。决策树中用于关键决策的属性越多,它们的相对重要性就越高。这种重要性是为数据集中的每个属性明确计算的,允许对属性进行排序和相互比较。单个决策树的重要性由每个属性分割点改进的性能指标的数量计算,并由节点负责的观察数量加权。性能度量可以是用于选择分裂点的纯度(基尼系数),或其他更具体的误差函数。然后,对模型中所有决策树的特征重要性进行平均。有关如何在提升决策树中计算特征重要性的更多技术信息,请参阅《统计学习的要素:数据挖掘,推理和预测》(第367页)第10.13.1节“预测变量的相对重要性”。另外,请参阅MatthewDrury对StackOverflow问题“提升的相对变量重要性”的回答,他在其中提供了非常详细和实用的答案。手动绘制特征重要性经过训练的XGBoost模型会自动计算预测建模问题中的特征重要性。这些重要性分数在训练模型的feature_importances_成员变量中可用。例如,它们可以直接打印如下:print(model.feature_importances_)我们可以将这些分数直接绘制在条形图上,以可视化数据集中每个特征的相对重要性。例如:#plotpyplot.bar(range(len(model.feature_importances_)),model.feature_importances_)pyplot.show()我们可以在PimaIndiandiabetes数据集上训练XGBoost模型并计算特征重要性创建一个条形图来演示这。下载数据集并将其放在当前工作目录中。数据集文件:https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.csv数据集详细信息:https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.names#plotfeatureimportancemanuallyfromnumpyimportloadtxtfromxgboostimportXGBClassifierfrommatplotlibimportpyplot#loaddatadataset=loadtxt('pima-indians-diabetes.csv',delimiter=",")#splitdataintoXandyX=dataset[:,0:8]y=dataset[data:,8]#fitmodel=XGBClassifier()model.fit(X,y)#featureimportanceprint(model.feature_importances_)#plotpyplot.bar(range(len(model.feature_importances_)),model.feature_importances_)pyplot.show()随机性,或者数值精度的差异,你的结果可能会有所不同。考虑运行该示例几次并比较平均结果。首先运行此示例将输出重要性分数。[0.0897010.171096340.081395350.046511630.104651160.20265780.16279070.14119601]我们还获得了相对重要性的条形图。这个图的缺点是特征是按它们的输入索引而不是它们的重要性排序的。我们可以在绘图之前对特征进行排序。值得庆幸的是,有一个内置的绘图功能可以帮助我们。使用内置的XGBoost特征重要性图XGBoost库提供了一个内置函数来按重要性顺序绘制特征。该函数称为plot_importance(),可以按如下方式使用:#plotfeatureimportanceplot_importance(model)pyplot.show()()功能性。#plotfeatureimportanceusingbuilt-infunctionfromnumpyimportloadtxtfromxgboostimportXGBClassifierfromxgboostimportplot_importancefrommatplotlibimportpyplot#loaddatadataset=loadtxt('pima-indians-diabetes.csv',delimiter=",")#splitdataintoXandyX=数据集[:,0:8]y=数据集[:,8]#fitmodelnotrainingdata()模型=XGBmodel.fit(X,y)#plotfeatureimportanceplot_importance(model)pyplot.show()注意:您的结果可能因算法或评估过程的随机性或数值精度的差异而有所不同。考虑运行该示例几次并比较平均结果。运行该示例将为我们提供更有用的条形图。您可以看到,这些特征是根据它们在输入数组(X)中的索引从F0到F7自动命名的。将这些指标手动映射到问题描述中的名称,可以看到该图显示F5(体重指数)的重要性最高,而F3(皮褶厚度)的重要性最低。XGBoost特征重要性分数的特征选择特征重要性分数可用于scikit-learn中的特征选择。这是使用SelectFromModel类完成的,该类采用模型并可以将数据集转换为具有选定特征的子集。此类可以采用预训练模型,例如在整个训练数据集上训练的模型。然后它可以使用阈值来确定选择哪些特征。当您在SelectFromModel实例上调用transform()方法以在训练和测试数据集上一致地选择相同的特征时,将使用此阈值。在下面的示例中,我们首先在整个训练和测试数据集上分别训练和评估XGBoost模型。使用从训练数据集计算的特征重要性,然后将模型包装在SelectFromModel实例中。我们使用它在训练数据集上选择特征,从选定的特征子集中训练模型,然后在测试集上评估模型,遵循相同的特征选择方案。例如:#selectfeaturesusingthresholdselection=SelectFromModel(model,threshold=thresh,prefit=True)select_X_train=selection.transform(X_train)#trainmodelselection_model=XGBClassifier()selection_model.fit(select_X_train,y_train)#transyform_X_test=selection。selection_model.predict(select_X_test)出于兴趣,我们可以测试多个阈值以根据特征重要性来选择特征。具体来说,每个输入变量的特征重要性本质上允许我们按重要性测试每个特征子集,从所有特征开始,到具有最重要特征的子集结束。下面提供了完整的代码清单:#usefeatureimportanceforfeatureselectionfromnumpyimportloadtxtfromnumpyimportsortfromxgboostimportXGBClassifierfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportaccuracy_scorefromsklearn.feature_selectionimportSelectFromModel#loaddatadataset=loadtxt('pima-indians-diabetes.csv',delimiter=",")#splitdataintoXandyX=dataset[:,0:8]Y=数据集[:,8]#splitdataintotrainandtestsetsX_train,X_test,y_train,y_test=train_test_split(X,Y,test_size=0.33,random_state=7)#fitmodelonalltrainingdatamodel=XGBClassifier()model.fit(X_train,y_train)#makepredictionsfortestdataandevaluatey_pred=model.predict(X_test)predictions=[round(value)forvalueiny_pred]accuracy=accuracy_score(y_test,predictions)print("Accuracy:%.2f%%"%(accuracy*100.0))#??Fitmodelusingeachimportanceasathresholdthresholds=sort(model.feature_importances_)forthreshinthresholds:#selectfeaturesusingthresholdselection模型=SelectFromModel(模型,阈值=阈值,预fit=True)select_X_train=selection.transform(X_train)#trainmodelselection_model=XGBClassifier()selection_model.fit(select_X_train,y_train)#evalmodelselect_X_test=selection.transform(X_test)y_pred=selection_model.predict(select_X_test)预测(值)=[rforvalueiny_pred]accuracy=accuracy_score(y_test,predictions)print("Thresh=%.3f,n=%d,Accuracy:%.2f%%"%(thresh,select_X_train.shape[1],accuracy*100.0))请注意,如果您使用的是XGBoost1.0.2(可能还有其他版本),则XGBClassifier类中存在导致错误的错误:KeyError:'weight'这可以通过使用自定义XGBClassifier类来解决,该类不返回coef_attribute下面列出了完整的示例。#usefeatureimportanceforfeatureselection,withfixforxgboost1.0.2fromnumpyimportloadtxtfromnumpyimportsortfromxgboostimportXGBClassifierfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportaccuracy_scorefromsklearn.feature_selectionimportSelectFromModel#definecustomclasstofixbuginxgboost1.0.2classMyXGBClassifier(XGBClassifier):@propertydefcoef_(self):returnNone#loaddatadataset=loadtxt('pima-indians-diabetes.csv',delimiter=",")#splitdataintoXandyX=dataset[:,0:8]Y=dataset[:,8]#splitdataintotrainandtestsetsX_train,X_test,y_train,y_test=train_test_split(X,Y,test_size=0.33,random_state=7)#fitmodelonalltrainingdatamodel=MyXGBClassifier()模型。fit(X_train,y_train)#makepredictionsfortestdataandevaluatepredictions=model.predict(X_test)accuracy=accuracy_score(y_test,predictions)print("Accuracy:%.2f%%"%(accuracy*100.0))#??Fitmodelusingeachimportanceasathresholdthresholds=排序(model.feature_importances_)forthreshinthresholds:#selectfeaturesusingthresholdselection=SelectFromModel(模型,threshold=thresh,prefit=True)select_X_train=selection.transform(X_train)#trainmodelselection_model=XGBClassifier()selection_model.fit(select_X_train,y_transtrain)#evalmodelsselection_X_form_test=selectionselection_model.predict(select_X_test)精度=accuracy_score(y_test,predictions)print("Thresh=%.3f,n=%d,Accuracy:%.2f%%"%(thresh,select_X_train.shape[1],accuracy*100.0))注意:您的结果可能由于算法或评估过程中的随机性或数值精度的差异而有所不同。考虑运行该示例几次并比较平均结果。运行此示例将打印以下输出。精度:77.95%Thresh=0.071,n=8,精度:77.95%Thresh=0.073,n=7,精度:76.38%Thresh=0.084,n=6,精度:77.56%Thresh=0.090,n=5,精度:76.38%Thresh=0.128,n=4,Accuracy:76.38%Thresh=0.160,n=3,Accuracy:74.80%Thresh=0.186,n=2,Accuracy:71.65%Thresh=0.208,n=1,Accuracy:63.78%我们可以看到,模型的性能通常会随着所选特征的数量而降低。在这个问题中,需要权衡测试集精度的特征,我们可以决定采用不太复杂的模型(更少的属性,例如n=4)并接受估计精度从77.95%适度降低到76.38%.对于这么小的数据集,这可能是一种洗礼,但对于更大的数据集,使用交叉验证作为模型评估方案可能是一种更有用的策略。