Python 基于xgbs分类器的特征重要性分析

Python 基于xgbs分类器的特征重要性分析,python,scikit-learn,xgboost,Python,Scikit Learn,Xgboost,希望我读错了,但是在XGBoost库中,有一个注释是使用feature\u importances\u提取特征重要性属性,很像sklearn的随机森林 然而,由于某些原因,我一直遇到这样的错误:AttributeError:'XGBClassifier'对象没有属性'feature\u importances' 我的代码片段如下: from sklearn import datasets import xgboost as xg iris = datasets.load_iris() X = i

希望我读错了,但是在XGBoost库中,有一个注释是使用
feature\u importances\u
提取特征重要性属性,很像sklearn的随机森林

然而,由于某些原因,我一直遇到这样的错误:
AttributeError:'XGBClassifier'对象没有属性'feature\u importances'

我的代码片段如下:

from sklearn import datasets
import xgboost as xg
iris = datasets.load_iris()
X = iris.data
Y = iris.target
Y = iris.target[ Y < 2] # arbitrarily removing class 2 so it can be 0 and 1
X = X[range(1,len(Y)+1)] # cutting the dataframe to match the rows in Y
xgb = xg.XGBClassifier()
fit = xgb.fit(X, Y)
fit.feature_importances_
从sklearn导入数据集
将xgboost作为xg导入
iris=数据集。加载\u iris()
X=iris.data
Y=iris.target
Y=iris.target[Y<2]#任意删除类2,使其可以是0和1
X=X[范围(1,len(Y)+1)]#剪切数据帧以匹配Y中的行
xgb=xg.XGBClassifier()
拟合=xgb。拟合(X,Y)
适合、特征和重要性_

似乎可以通过调用
get\u fscore
属性,使用
Booster
对象来计算特征重要性。我使用
XGBClassifier
而不是
Booster
的唯一原因是它能够被包装在sklearn管道中。对特征提取有什么想法吗?还有其他人遇到过这种情况吗?

如评论所示,我怀疑您的问题是版本控制问题。但是,如果您不想/无法更新,那么下面的函数应该适合您

def get_xgb_imp(xgb, feat_names):
    from numpy import array
    imp_vals = xgb.booster().get_fscore()
    imp_dict = {feat_names[i]:float(imp_vals.get('f'+str(i),0.)) for i in range(len(feat_names))}
    total = array(imp_dict.values()).sum()
    return {k:v/total for k,v in imp_dict.items()}


>>> import numpy as np
>>> from xgboost import XGBClassifier
>>> 
>>> feat_names = ['var1','var2','var3','var4','var5']
>>> np.random.seed(1)
>>> X = np.random.rand(100,5)
>>> y = np.random.rand(100).round()
>>> xgb = XGBClassifier(n_estimators=10)
>>> xgb = xgb.fit(X,y)
>>> 
>>> get_xgb_imp(xgb,feat_names)
{'var5': 0.0, 'var4': 0.20408163265306123, 'var1': 0.34693877551020408, 'var3': 0.22448979591836735, 'var2': 0.22448979591836735}

我找到了答案。版本
0.4a30
似乎没有
功能重要性属性。因此,如果使用
pip install xgboost
安装xgboost包,将无法从
XGBClassifier
对象中进行特征提取,如果需要解决方法,可以参考@David的答案

然而,我所做的是通过克隆repo并运行
从源代码构建它/build.sh
将安装
0.4版
,其中
特性
属性起作用


希望这能帮助别人

获取作为排序数据帧的特征重要性

import pandas as pd
import numpy as np
def get_xgb_imp(xgb, feat_names):
    imp_vals = xgb.booster().get_fscore()
    feats_imp = pd.DataFrame(imp_vals,index=np.arange(2)).T
    feats_imp.iloc[:,0]= feats_imp.index    
    feats_imp.columns=['feature','importance']
    feats_imp.sort_values('importance',inplace=True,ascending=False)
    feats_imp.reset_index(drop=True,inplace=True)
    return feats_imp

feature_importance_df = get_xgb_imp(xgb, feat_names)

对于
xgboost
,如果使用
xgb.fit()
,则可以使用以下方法获取特征重要性

import pandas as pd
xgb_model=xgb.fit(x,y)
xgb_fea_imp=pd.DataFrame(list(xgb_model.get_booster().get_fscore().items()),
columns=['feature','importance']).sort_values('importance', ascending=False)
print('',xgb_fea_imp)
xgb_fea_imp.to_csv('xgb_fea_imp.csv')

from xgboost import plot_importance
plot_importance(xgb_model, )

对于那些与“TypeError:'str'对象不可调用”相同的问题,我找到了一个解决方案(至少对我来说是有效的)

简而言之,我发现修改的代码来自

imp_vals = xgb.booster().get_fscore()

为我工作

要了解更多详细信息,我建议访问上面的链接


非常感谢接受答案的更新,因为它不再有效:

def get_xgb_imp(xgb_model, feat_names):
    imp_vals = xgb_model.get_fscore()
    imp_dict = {feat: float(imp_vals.get(feat, 0.)) for feat in feat_names}
    total = sum(list(imp_dict.values()))
    return {k: round(v/total, 5) for k,v in imp_dict.items()}
似乎api一直在变化。对于xgboost版本1.0.2,只需将
imp\u vals=xgb.booster().get\u fscore()
更改为
imp\u vals=xgb.get\u booster().get\u fscore()
,在@David中的答案就行了。更新后的代码是-

from numpy import array

def get_xgb_imp(xgb, feat_names):
    imp_vals = xgb.get_booster().get_fscore()
    imp_dict = {feat_names[i]:float(imp_vals.get('f'+str(i),0.)) for i in range(len(feat_names))}
    total = array(imp_dict.values()).sum()
    return {k:v/total for k,v in imp_dict.items()}

您还可以使用内置的“绘图重要性”功能:

from xgboost import XGBClassifier, plot_importance
fit = XGBClassifier().fit(X,Y)
plot_importance(fit)

内置功能重要性的替代方案可以是:

  • 来自scikit学习的基于排列的重要性(
  • 具有Shapley值的重要性()
我非常喜欢
shap
package,因为它提供了额外的绘图。例如:

重要性图

概要图

依赖图


你可以在我的这篇文章中阅读到计算Xgboost中功能重要性的其他方法。

我无法用你的代码片段重现这个问题。你有什么版本的Xgboost?从我的
pip freeze
,我有
Xgboost==0.4a30
这有帮助吗?我以前见过这个问题。问题是
get\fscore根据我的理解,
方法绑定到
Booster
对象,而不是
XGBClassifier
。请参阅文档I have 0.4,您的代码片段工作没有问题。有趣的方法!但是,如果我调整
XGBClassifier
的参数,这有什么关系吗?我如何确保它与
Booster
您正在XGBClassifier()对象中引用Booster()对象,因此它将匹配:
xgb.Booster()
我意识到了一些奇怪的事情,这是应该发生的吗?从xgb.Booster()返回的值。get\fscore()这应该包含模型所针对的所有列的值?因为我发现imp_vals中缺少2列,它们出现在列列中,但不是imp_colsI中的键。我必须使用
xgb.get_booster().get_fscore()
。否则,我得到的是
类型错误:“str”对象不可调用
。我使用的是xgboost 0.6。我对XGB对象进行了pickle处理,无法调用
get\u booster()
文件/usr/local/lib/python3.5/dist packages/xgboost/sklearn.py”,第193行,在get\u booster raiser中(“需要事先调用fit或load\u model”)
from xgboost import XGBClassifier, plot_importance
fit = XGBClassifier().fit(X,Y)
plot_importance(fit)