xgboost需不需要特征挑选

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xgboost需不需要特征挑选相关的知识,希望对你有一定的参考价值。

相当于学习速率(xgboost中的eta)。xgboost的并行是在特征粒度上的。我们知道,xgboost在训练之前,预先对数据进行了排序,用于高效地生成候选的分割点。(补充。
xgboost在代价函数里加入了正则项。
Shrinkage(缩减),这也是xgboost异于传统gbdt的一个特性,xgboost还支持线性分类器,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,防止过拟合,这也是xgboost优于传统GBDT的一个特性。

对缺失值的处理。
xgboost工具支持并行,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,让后面有更大的学习空间,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。xgboost借鉴了随机森林的做法,那么各个特征的增益计算就可以开多线程进行。

可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下。实际应用中,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点):传统GBDT的实现也有学习速率)
列抽样(column subsampling),一般把eta设置得小一点,然后迭代次数设置得大一点,不仅能降低过拟合,还能减少计算。
传统GBDT在优化时只用到一阶导数信息。boosting不是一种串行的结构吗?怎么并行的?注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值),支持列抽样,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。顺便提一下,主要是为了削弱每棵树的影响 
传统GBDT以CART作为基分类器
参考技术A xgb应该是对所有的特征的所有特征值点(快速方法是近似算法)计算了增益(这个增益网上自己查)再排序,然后挑出得分最高的最佳分裂点(这个最佳分裂点对应的特征就是第一个要分裂的特征) 进行分类,具体是否分裂(即树的深度控制)是可以通过设置正则项系数gamma来限制

XGBoost:xgb.importance 特征图

【中文标题】XGBoost:xgb.importance 特征图【英文标题】:XGBoost: xgb.importance feature map 【发布时间】:2016-05-24 10:50:26 【问题描述】:

当我尝试使用以下代码时出现以下错误。

******代码******

    importance = bst.get_fscore(fmap='xgb.fmap')
    importance = sorted(importance.items(), key=operator.itemgetter(1))

******错误******

  File "scripts/xgboost_bnp.py", line 225, in <module>
  importance = bst.get_fscore(fmap='xgb.fmap')
  File "/usr/lib/python2.7/site-packages/xgboost/core.py", line 754, in get_fscore
    trees = self.get_dump(fmap)
  File "/usr/lib/python2.7/site-packages/xgboost/core.py", line 740, in get_dump
   ctypes.byref(sarr)))
  File "/usr/lib/python2.7/site-packages/xgboost/core.py", line 92, in _check_call
raise XGBoostError(_LIB.XGBGetLastError())
xgboost.core.XGBoostError: can not open file "xgb.fmap"

【问题讨论】:

【参考方案1】:

引发错误是因为您使用可选参数 fmap 调用 get_fscore,说明每个特征的特征重要性应从名为 xgb.fmap 的特征映射文件中获取,该文件系统中不存在该文件。

这是一个返回排序后的特征名称及其重要性的函数:

import xgboost as xgb
import pandas as pd

def get_xgb_feat_importances(clf):

    if isinstance(clf, xgb.XGBModel):
        # clf has been created by calling
        # xgb.XGBClassifier.fit() or xgb.XGBRegressor().fit()
        fscore = clf.booster().get_fscore()
    else:
        # clf has been created by calling xgb.train.
        # Thus, clf is an instance of xgb.Booster.
        fscore = clf.get_fscore()

    feat_importances = []
    for ft, score in fscore.iteritems():
        feat_importances.append('Feature': ft, 'Importance': score)
    feat_importances = pd.DataFrame(feat_importances)
    feat_importances = feat_importances.sort_values(
        by='Importance', ascending=False).reset_index(drop=True)
    # Divide the importances by the sum of all importances
    # to get relative importances. By using relative importances
    # the sum of all importances will equal to 1, i.e.,
    # np.sum(feat_importances['importance']) == 1
    feat_importances['Importance'] /= feat_importances['Importance'].sum()
    # Print the most important features and their importances
    print feat_importances.head()
    return feat_importances

【讨论】:

感谢您的回答,但是这个解决方案没有显示原始特征名称,而只是返回 fxx 代表某个特征,您知道如何将真实特征名称与重要性分数映射? 我猜你的训练数据存储在 NumPy 数组中?尝试使用 Pandas DataFrame 训练模型(将适当的特征名称设置为列名)并再次运行上述函数。如果我没记错的话,XGBoost 会从 Pandas DataFrame 的列名中提取特征名。 或者如果您通过xgboost.DMatrix() 定义训练数据,您可以通过其feature_names 参数定义特征名称。 再次感谢,你说得对,我没有在 xgboost.DMatrix() 中设置 feature_names 参数,你的解决方案效果很好,我将其更改为输出到文件以查看之后的功能重要性我的特征选择训练 @tuomastik 你是对的,如果你的训练数据是 pd.DataFrame 格式,XGBoost 会提取特征名称

以上是关于xgboost需不需要特征挑选的主要内容,如果未能解决你的问题,请参考以下文章

XGBoost 中的特征重要性“增益”

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

使用 XGBoost 特征重要性分数打印出特征选择中使用的特征

xgboost 特征重要性计算

XGBoost 输出特征重要性以及筛选特征

xgboost auc值怎么判断