最近在复习特征重要性时候,考虑到我们在使用GBDT、RF、Xgboost等树类模型建模时,往往可以通过 feature_importance 来返回特征重要性,下面收集整理了一下各模型输出特征重要性的原理与方法;

1. 计算特征重要性方法

首先,目前计算特征重要性计算方法主要有两个方面:

1.1 训练过程中计算

训练过程中通过记录特征的分裂总次数、总/平均信息增益来对特征重要性进行量化。例如实际工程中我们会用特征在整个GBDT、XgBoost里面被使用的次数或者带来的总/平均信息增益来给特征重要度打分,最后进行排序。由于本身Ensemble模型在选择特征分裂时带有一定随机性,一般会跑多个模型然后把特征重要性求平均后排序。

1.2 训练后使用OOB(Out of Bag)数据计算

第二种方式是训练好模型之后,用Out of Bag(或称Test)数据进行特征重要性的量化计算。具体来说,先用训练好的模型对OOB数据进行打分,计算出AUC或其他业务定义的评估指标;接着对OOB数据中的每个特征:

(1)随机shuffle当前特征的取值;

(2)重新对当前数据进行打分,计算评估指标;

(3)计算指标变化率

按照上面方式,对每个特征都会得到一个变化率,最后按照变化率排序来量化特征重要性。

延伸到 DNN 对特征重要性判定:

DNN不像Boosting这类模型那样存在所谓的分裂次数与信息增益,就需要使用第二种方式,对每个特征进行随机shuffle,观察模型指标的变化,最后按照变化率进行排序。比如AUC下滑率,下滑的越多说明当前这个指标越重要。当然,实际操作中需要结合业务经验先指定一个候选变量池,对这部分变量计算重要度,不然计算开销太大。

2. 树模型特征重要性判定

2.1 Random Foreast

  • 袋外数据错误率(可参考上一问的OOB特征选择方法)
  • 基尼指数

随机森林特征重要性评定可参考:

2.2 GBDT

  • 基尼指数

2.3 Xgboost

xgboost实现中Booster类get_score方法输出特征重要性,其中importance_type参数支持三种特征重要性的计算方法:

  • importance_type=weight(默认):the number of times a feature is used to split the data across all trees. 特征重要性使用特征在所有树中作为划分属性的次数。
  • importance_type=gain:is the average gain of splits which use the feature. 特征重要性使用特征在作为划分属性带来的平均增益。
  • importance_type=cover:is the average coverage of splits which use the feature where coverage is defined as the number of samples affected by the split. 使用该特作为分割影响的平均样本数。——可以理解为被分到该节点的样本的二阶导数之和,而特征度量的标准就是平均的coverage值。

cover 的解释有点晦涩,在[R-package/man/xgb.plot.tree.Rd]有比较详尽的解释:(https://github.com/dmlc/xgboost/blob/f5659e17d5200bd7471a2e735177a81cb8d3012b/R-package/man/xgb.plot.tree.Rd):the sum of second order gradient of training data classified to the leaf, if it is square loss, this simply corresponds to the number of instances in that branch. Deeper in the tree a node is, lower this metric will be。实际上coverage可以理解为被分到该节点的样本的二阶导数之和,而特征度量的标准就是平均的coverage值。

2.4 Lightgbm

  • split:result contains numbers of times the feature is used in a mode (特征重要性使用特征在所有树中作为划分属性的次数)
  • gain:result contains total gains of splits which use the feature (使用该特征作为分割带来的总增益)