1 XGB vs LGB

2 直方图算法

2.1 缘起

XGBoost的Exact greedy算法流程

  1. 对每个特征都按照特征值进行排序
  2. 在每个排好序的特征都寻找最优切分点
  3. 用最优切分点进行切分

这个算法比较精确,但是缺点明显:

  1. 空间消耗大。需要保存数据的特征值。XGBoost采用Block结构,存储指向样本的索引,需要消耗两倍的内存。
  2. 时间开销大。在寻找最优切分点时,要对每个特征都进行排序,还要对每个特征的每个值都进行了遍历,并计算增益。
  3. 对Cache不友好。使用Block块预排序后,特征对梯度的访问是按照索引来获取的,是一种随机访问,而不同特征访问顺序也不一样,容易照成命中率低的问题。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的Cache miss。

使用直方图算法进行划分点的查找可以很好的克服这些缺点

2.2 算法描述

直方图算法(Histogram algorithm)的做法是把连续的浮点特征值离散化为k个整数(其实又是分桶的思想,而这些桶称为bin)比如[0,0.1)→0, [0.1,0.3)→1。

关键点(个人理解)

  • pre-bin,先分箱后分裂
  • LightGBM采用的直方图方法与XGBoost的”加权分位图”类似,直方图的边界即分裂值

同时,将特征根据其所在的bin进行梯度累加。这样,遍历一次数据后,直方图累积了需要的梯度信息,然后可以直接根据直方图,寻找最优的切分点。

流程描述(似乎loss计算那块有些问题,不过不影响理解直方图)

结合伪代码一起看

仔细看上面的伪代码,相信你有几个问题:

  • 如何将特征映射到bin呢?即如何分桶?
  • 如何构建直方图?直方图算法累加的g是什么?
  • 构建完直方图如何找最优特征,有用到二阶信息么?

2.2.1 分桶(bin)策略

对于数值型特征

  • 如果特征取值数比max_bin数量少,直接取distinct_values的中点放置
  • 特征取值比max_bin来得大,说明几个特征取值要共用一个bin
    • 计算mean size for one bin
    • 标记一个特征取值数超过mean,因为这些特征需要单独一个bin
    • 剩下的特征取值中平均每个bin的取值个数

对于类别特征