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三种特征重要性计算方法对比的主要内容,如果未能解决你的问题,请参考以下文章

Xgboost中特征重要性计算方法详解

ML之R:通过数据预处理利用LiR/XGBoost等(特征重要性/交叉训练曲线可视化/线性和非线性算法对比/三种模型调参/三种模型融合)实现二手汽车产品交易价格回归预测之详细攻略

XGBoost feature importance特征重要性-实战印第安人糖尿病数据集(附代码)

Python计算树模型(随机森林xgboost等)的特征重要度及其波动程度:基于熵减的特征重要度计算及可视化基于特征排列的特征重要性(feature permutation)计算及可视化

原创xgboost 特征评分的计算原理

R语言构建xgboost模型:特征重要度计算及解读改善特征重要度数据的可解释性特征重要度可视化