XGBoost三种特征重要性计算方法对比
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XGBoost三种特征重要性计算方法对比相关的知识,希望对你有一定的参考价值。
参考技术A 特征重要性,我们一般用来观察不同特征的贡献度。排名靠前的,我们认为是重要的。这一思路,通常被用来做 特征筛选 。剔除贡献度不高的尾部特征,增强模型的鲁棒性,起到特征降维的作用。另一方面,则是用来做模型的课解释性。我们期望的结果是:重要的特征是复合业务直觉的;符合业务直觉的特征排名靠前。在实际操作中,我们一般用树模型的分类点来做文章。常用的就是XGB和其他一般树模型。XGB内置的三种特征重要性计算方法1--weight
xgb.plot_importance这是我们常用的绘制特征重要性的函数方法。其背后用到的贡献度计算方法为weight。
'weight' - the number of times a feature is used to split the data across all trees.
简单来说,就是在子树模型分裂时,用到的特征次数。这里计算的是所有的树。这个指标在R包里也称为frequency2。
XGB内置的三种特征重要性计算方法2--gain
model.feature_importances_这是我们调用特征重要性数值时,用到的默认函数方法。其背后用到的贡献度计算方法为gain。
'gain'-the average gain across all splits the feature is used in.
gain是信息增益的泛化概念。这里是指节点分裂时,该特征带来信息增益(目标函数)优化的平均值。
XGB内置的三种特征重要性计算方法3--cover
model = XGBRFClassifier(importance_type = 'cover')这个计算方法,需要在定义模型时定义。之后再调用
model.feature_importances_得到的便是基于cover的贡献度。
'cover' - the average coverage across all splits the feature is used in.
cover形象来说,就是树模型在分裂时,特征下的叶子节点涵盖的样本数除以特征用来分裂的次数。分裂越靠近根部,cover值越大。
使用场景
weight将给予数值特征更高的值,因为它的变数越多,树分裂时可切割的空间越大。所以这个指标,会掩盖掉重要的枚举特征。
gain用到了熵增的概念,它可以方便的找出最直接的特征。即如果某个特征下的0,在label下全是0,则这个特征一定会排的靠前。
cover对于枚举特征,会更友好。同时,它没有过度拟合目标函数。不接受目标函数的量纲影响。
调用他们的方式如下
# avaliable importance_types = ['weight','gain','cover','total_gain','total_cover']
f = "gain"
XGBClassifier.get_booster().get_score(importamce_type=f)
在实践中,也会发现,gain排出来的顺序的 头尾部值差距较大 ,这是因为信息增益计算时,后续的优化可能都不是一个量级。类似于神经网络在优化损失函数时,后续的量纲可能是十倍、百倍的差异。所以,综上而言,如果 有下游业务方,更建议用cover的特征重要性计算方法 。当然,如果是单纯的模型调优,gain能指出最重要的特征。这些特征,某些场景下还能总结成硬规则。
其他重要计算方法4 -- permutation
除了上述内置的重要性计算方法外,还有其他其他第三方计算方式。
permutation :如果这个特征很重要,那么我们打散所有样本中的该特征,则最后的优化目标将折损。这里的折损程度,就是特征的重要程度。由于其计算依赖单一特征,所以对非线形模型更友好。同时,如果特征中存在多重共线性,共线性的特征重要性都将非常靠后。这是因为混淆单一特征,不影响另一个特征的贡献。这样的结果是,即使特征很重要,也会排的很靠后。
针对多重共线特征,sklearn文档中提到了一种解决方法:计算特征间的spearman rankk-order correlations,取得每一组中的头部特征,再进行特征重要性计算。这种方法,实际上是在解决特征共线的问题。
其他模型的特征重要性计算方法
对于同样的树模型,Random Forest和GBDT,同样也有内置的特征重要性。Random Forest使用rf.feature_importances_得到特征重要性。其中,分类任务计算的是gini不纯度/信息熵。回归任务计算的是树的方差。这种基于 不纯度 (Mean Decrease in Impurity)的方法,实际上会有两个问题存在:(1)会给予变量空间更大的特征更多的关注,而二分类特征则会靠后。(2)结果的拟合是基于训练集的,存在过拟合风险,没有验证集数据做验证。
针对上述的问题,建议通过out-of-bag(OOB)方法,在剩下数据上做验证,结合Permutation计算特征重要性。此外,GBDT也是基于 不纯度 计算的特征重要性,不过其在单棵树上,是回归树,所以不是基于gini系数,而是MSE或MAE。
至于为什么他们同为树模型,且都是基于不存度计算的重要性,但结果不同。主要有两个,一个是它们树结构不同;第二个则是它们的优化对象不同。
原创xgboost 特征评分的计算原理
xgboost是基于GBDT原理进行改进的算法,效率高,并且可以进行并行化运算;
而且可以在训练的过程中给出各个特征的评分,从而表明每个特征对模型训练的重要性,
调用的源码就不准备详述,本文主要侧重的是计算的原理,函数get_fscore源码如下,
源码来自安装包:xgboost/python-package/xgboost/core.py
通过下面的源码可以看出,特征评分可以看成是被用来分离决策树的次数,而这个与
《统计学习基础-数据挖掘、推理与推测》中10.13.1 计算公式有写差异,此处需要注意。
注:考虑的角度不同,计算方法略有差异。
def get_fscore(self, fmap=‘‘): """Get feature importance of each feature. Parameters ---------- fmap: str (optional) The name of feature map file """ return self.get_score(fmap, importance_type=‘weight‘) def get_score(self, fmap=‘‘, importance_type=‘weight‘): """Get feature importance of each feature. Importance type can be defined as: ‘weight‘ - the number of times a feature is used to split the data across all trees. ‘gain‘ - the average gain of the feature when it is used in trees ‘cover‘ - the average coverage of the feature when it is used in trees Parameters ---------- fmap: str (optional) The name of feature map file """ if importance_type not in [‘weight‘, ‘gain‘, ‘cover‘]: msg = "importance_type mismatch, got ‘{}‘, expected ‘weight‘, ‘gain‘, or ‘cover‘" raise ValueError(msg.format(importance_type)) # if it‘s weight, then omap stores the number of missing values if importance_type == ‘weight‘: # do a simpler tree dump to save time trees = self.get_dump(fmap, with_stats=False) fmap = {} for tree in trees: for line in tree.split(‘\n‘): # look for the opening square bracket arr = line.split(‘[‘) # if no opening bracket (leaf node), ignore this line if len(arr) == 1: continue # extract feature name from string between [] fid = arr[1].split(‘]‘)[0].split(‘<‘)[0] if fid not in fmap: # if the feature hasn‘t been seen yet fmap[fid] = 1 else: fmap[fid] += 1 return fmap else: trees = self.get_dump(fmap, with_stats=True) importance_type += ‘=‘ fmap = {} gmap = {} for tree in trees: for line in tree.split(‘\n‘): # look for the opening square bracket arr = line.split(‘[‘) # if no opening bracket (leaf node), ignore this line if len(arr) == 1: continue # look for the closing bracket, extract only info within that bracket fid = arr[1].split(‘]‘) # extract gain or cover from string after closing bracket g = float(fid[1].split(importance_type)[1].split(‘,‘)[0]) # extract feature name from string before closing bracket fid = fid[0].split(‘<‘)[0] if fid not in fmap: # if the feature hasn‘t been seen yet fmap[fid] = 1 gmap[fid] = g else: fmap[fid] += 1 gmap[fid] += g # calculate average value (gain/cover) for each feature for fid in gmap: gmap[fid] = gmap[fid] / fmap[fid] return gmap
GBDT特征评分的计算说明原理:
链接:1、http://machinelearningmastery.com/feature-importance-and-feature-selection-with-xgboost-in-python/
详细的代码说明过程:可以从上面的链接进入下面的链接:
http://stats.stackexchange.com/questions/162162/relative-variable-importance-for-boosting
以上是关于XGBoost三种特征重要性计算方法对比的主要内容,如果未能解决你的问题,请参考以下文章
ML之R:通过数据预处理利用LiR/XGBoost等(特征重要性/交叉训练曲线可视化/线性和非线性算法对比/三种模型调参/三种模型融合)实现二手汽车产品交易价格回归预测之详细攻略
XGBoost feature importance特征重要性-实战印第安人糖尿病数据集(附代码)
Python计算树模型(随机森林xgboost等)的特征重要度及其波动程度:基于熵减的特征重要度计算及可视化基于特征排列的特征重要性(feature permutation)计算及可视化