集成学习概述-特征选择

RF、GBDT、XGboost都可以做特征选择,属于特征选择中的嵌入式方法;在用sklearn的时候经常用到feature_importances_ 来做特征筛选,分析gbdt的源码发现来源于每个base_estimator的决策树的
feature_importances_;
决策树的feature_importances_:impurity就是gini值,weighted_n_node_samples 就是各个节点的加权样本数,最后除以根节点nodes[0].weighted_n_node_samples的总样本数。最后还要归一化处理。

from sklearn import ensemble
#grd = ensemble.GradientBoostingClassifier(n_estimators=30)
grd = ensemble.RandomForestClassifier(n_estimators=30)
grd.fit(X_train,y_train)
grd.feature_importances_

计算特征重要性方法

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

1)训练过程中计算

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

作为单个决策树模型,在模型建立时实际上是寻找到某个特征合适的分割点。这个信息可以作为衡量所有特征重要性的一个指标。

基本思路如下:
如果一个特征被选为分割点的次数越多,那么这个特征的重要性就越强。这个理念可以被推广到集成算法中,只要将每棵树的特征重要性进行简单的平均即可。

分别根据特征1和特征4进行分割,显然x1出现的次数最多,这里不考虑先分割和后分割的情况,只考虑每次分割属性出现的次数。
在这里插入图片描述
计算得:
x1的特征重要度:出现在2棵树上,两棵树一共分裂了6次,x1出现了3次。
x1特征重要度 = 3/6 = 1/2
x2的特征重要度= 4/6 = 2/3
x3的特征重要度= 3/6 = 1/2
x4的特征重要度: 出现在1棵树上,一个树分裂了3次,x4出现了1次。
x4的特征重要度= 1/3

根据特征重要度进行特征选择。

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

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

  • (1)随机shuffle当前特征的取值;
  • (2)重新对当前数据进行打分,计算评估指标;
  • (3)计算指标变化率
    按照上面方式,对每个特征都会得到一个变化率,最后按照变化率排序来量化特征重要性。
    延伸到 DNN 对特征重要性判定:
    DNN不像Boosting这类模型那样存在所谓的分裂次数与信息增益,就需要使用第二种方式,对每个特征进行随机shuffle,观察模型指标的变化,最后按照变化率进行排序。比如AUC下滑率,下滑的越多说明当前这个指标越重要。当然,实际操作中需要结合业务经验先指定一个候选变量池,对这部分变量计算重要度,不然计算开销太大。

随机森林(Random Forest)

  • 袋外数据错误率(可参考OOB特征选择方法)
    RF的数据是boostrap的有放回采样,形成了袋外数据。因此可以采用袋外数据(OOB)错误率进行特征重要性的评估。
    袋外数据错误率定义为:袋外数据自变量值发生轻微扰动后的分类正确率与扰动前分类正确率的平均减少量。
    (1)对于每棵决策树,利用袋外数据进行预测,将袋外数据的预测误差记录下来,其每棵树的误差为vote1,vote2,…,voteb
    (2)随机变换每个预测变量,从而形成新的袋外数据,再利用袋外数据进行验证,其每个变量的误差是votel1,votel2,…votelb

  • 基尼指数(和GBDT的方法相同)

梯度提升树(GBDT)

基尼指数

在sklearn中,GBDT和RF的特征重要性计算方法是相同的,都是基于单棵树计算每个特征的重要性,探究每个特征在每棵树上做了多少的贡献,再取个平均值。

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. 特征重要性使用特征在作为划分属性带来的平均增益。特征重要性使用特征在作为划分属性时loss平均的降低量。
  • 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值。 特征重要性使用特征在作为划分属性时对样本的覆盖度。
    importance_type=total_gain: the total gain across all splits the feature is used in.
    importance_type=total_cover: the total coverage across all splits the feature is used in

weight 将给予数值特征更高的值,因为它的变数越多,树分裂时可切割的空间越大。所以这个指标,会掩盖掉重要的枚举特征。
gain 用到了熵增的概念,它可以方便的找出最直接的特征。即如果某个特征的下的0,在label下全是0,则这个特征一定会排得靠前。
cover 对于枚举特征,会更友好。同时,它也没有过度拟合目标函数,不受目标函数的量纲影响。

Lightgbm

split: 特征重要性使用特征在所有树种作为划分属性的次数
gain: 使用该特征作为分割带来的总增益

上一篇:阿里云发送国内短信怎样编程