XGBoost:最小化连续线性特征而不是分类特征的影响

XGBoost: minimize influence of continuous linear features as opposed to categorical

假设我有 100 个独立特征 - 90 个是二元的(例如 0/1),10 个是连续变量(例如年龄、身高、体重等)。我使用这 100 个特征来预测具有足够样本量的分类器问题。

当我设置 XGBClassifier 函数并对其进行拟合时,从 gain 的角度来看,最重要的 10 个特征始终是 10 个连续变量。现在我对 coverfrequency 不感兴趣。 10 个连续变量在 gain 列表中占 space 的 .8 到 .9 ( sum(gain) = 1).

我尝试调整 gammareg_alphareg_lambdamax_depthcolsample。增益排名前 10 位的特征始终是 10 个连续特征。

有什么建议吗?

小更新 -- 有人问我为什么认为会发生这种情况。我相信这是因为连续变量可以在每个决策树上多次拆分。二进制变量只能拆分一次。因此,树中连续变量的流行率更高,因此 gain 得分更高

我可以推荐一些东西供您尝试。

  1. 在没有此数据(仅 90 个特征)的情况下测试您的模型并评估您的分数下降情况。如果它无关紧要,您可能想要删除这些功能。
  2. 把他们分组。 例如,年龄可以分为组,0 : 0-7, 1 : 8-16, 2 : 17-25等。

  3. 将它们转换成二进制。关于如何选择最佳值将它们拆分为二元的开箱即用的想法是:构建具有 1 个节点(最大深度 = 1)的 1 棵树并仅使用 1 个特征。 (连续特征中的 1 个)。然后,将模型转储到 .txt 文件并查看它选择拆分的值。使用此值,您可以将所有特征列转换为 binary

我现在正在处理非常相似的问题,所以我很高兴听到你的结果和你选择尝试的路径。

是的,众所周知,树(/森林)算法(xgboost/rpart/etc。)在其变量选择中通常 'prefer' 连续变量优于二进制分类变量,因为它可以在任何想要最大化信息增益的地方选择连续的分裂点(并且可以在其他节点或其他树中为同一变量自由选择不同的分裂点)。如果那是最优树(对于那些特定变量),那么它就是最优树。请参阅姊妹网站 CrossValidated 上的 Why do Decision Trees/rpart prefer to choose continuous over categorical variables?

当你说 "any suggestions" 时,取决于你到底想要什么,它可以是以下之一:

如果您想探索 a)...c),建议像这样含糊不清:

  • 排除 10 个连续变量的各个子集,然后查看哪些二元特征显示出增益最大。假设这给了你 N 个候选特征。 N 将 << 90,让我们假设 N < 20 以提高以下计算效率。
  • 然后计算 N 个特征中每个特征之间的关联或相关性(Spearman 或 Kendall)的成对度量。看一个corrplot。选择彼此最相关的变量簇。创建组合这些单独的二进制特征的复合 n 位变量。然后重新训练树,包括复合变量,并排除单个二进制变量(以避免改变输入中的总方差)。
  • 迭代以排除 10 个连续变量的各个子集。查看复合变量中出现了哪些模式。我确定有一种算法可以更正式、更有条理地执行此操作(n 位分类的复合特征工程),我只是不知道。

  • 无论如何,为了获得更好的性能而破解基于树的方法,我想最天真的方法是"at every step, pick the two most highly-correlated/associated categorical features and combine them"。然后重新训练树(包括新特征,排除其组成特征)并使用修改后的增益数。

  • 也许更稳健的方式可能是:

    • 为 correlation/association 选择一些阈值 T,比如从高水平开始 T = 0.9 或 0.95
    • 在每一步中,合并绝对 correlation/association 彼此 >= T
    • 的所有特征
    • 如果在这一步没有合并,将 T 减少某个值(如 T -= 0.05)或比率(例如 T *= 0.9 。如果仍然没有合并,继续减少 T 直到有合并,或直到你达到了一些终止值(例如 T = 0.03)
    • 重新训练包含复合变量的树,排除它们的组成子变量。
    • 现在回去重新训练应该是改进树的所有 10 个连续变量,以及复合分类特征。
    • 或者您可以提前终止复合特征选择以查看完整的再训练树的样子。

此问题出现于 2014 年 Kaggle Allstate Purchase Prediction Challenge, where the policy coverage options A,B,C,D,E,F,G were each categoricals with between 2-4 values, and very highly correlated with each other. (The current option of C, "C_previous", is one of the input features). See that competitions's forums 并发布了更多解决方案。请注意 policy = (A,B,C,D,E,F,G) 是输出。但是C_previous是一个输入变量。

Kaggle 中关于特征选择的一些一般的快速和肮脏的经验法则是:

  • 丢弃任何接近常数/非常低方差的变量(因为它们的信息含量接近于零)
  • 丢弃任何非常高基数的分类变量(基数 >~ training-set-size/2),(因为它们也往往信息含量低,但会导致大量虚假过度拟合并增加训练时间) .这可能包括客户 ID、行 ID、交易 ID、序列 ID 和其他本来不应训练但意外出现在训练集中的变量。

我从@smci 的回答中学到了很多,所以我建议听从他的建议。

在这种情况下,如果您的二元分类特征实际上是几个分类特征的 OHE 表示,每个分类特征有几个 类,您可以采用另外两种方法:

  • 将 OHE 转换为标签编码。是的,这有一个警告,即在分类特征中引入一个顺序,这可能没有意义,例如 green=3 > red=2 > blue=1。但在实践中,树似乎可以很好地处理标签=编码的分类变量(即使是无意义的顺序)。
  • 将 OHE 转换为 target-/mean-/likelihood 编码。这很棘手,因为您需要应用正则化来避免数据泄漏。

这两个想法都是为了根据关于特征含义的先验知识,将几个二元特征组合成一个单一的特征。如果你没有那么奢侈,你也可以尝试通过对列进行标量积并找到那些给出零积的那些来推导出这样的组。