树系列(五)xgboost

  • 核心思想

    核心为加法模型,优化方法采用前向分步算法

    gbdt的延伸,并且成功的添加了正则项,保证模型的泛化能力强,

  • 推导过程

    根据gbdt的公式可得,

    f m ( x ) = f m 1 ( x ) + T ( x ; θ m )

    gbdt的目标为
    确定下一棵决策树的参数的方法如下,

    O b j m = i = 1 N L ( y i , f m 1 ( x i ) + T ( x i ; θ m ) )

    而xgboost的目标是使如下公式最小,

    O b j m = i = 1 N L ( y i , f m 1 ( x i ) + T ( x i ; θ m ) ) + Ω ( T ( x ; θ m ) ) + c o n s t a n t

    通过泰勒级数展开 f ( x + Δ x ) = f ( x ) + f ( x ) Δ x + 1 2 f ( x ) Δ x 2 + 可得,

    O b j m = i = 1 N [ l ( y i , f m 1 ( x i ) ) + g i T ( x i ; θ m ) + 1 2 h i ( T ( x i ; θ m ) ) 2 ] + Ω ( T ( x i , θ m ) ) + c o n s t a n t

    其中

    g i = l ( y i , f m 1 ( x i ) ) f m 1 ( x i )

    h i = 2 l ( y i , f m 1 ( x i ) ) ( f m 1 ( x i ) ) 2

    l ( y i , f m 1 ( x i ) ) 在第m轮训练时被看成了常数,因为 , f m 1 ( x i ) y i 都已知,因而目标变为了

    O b j m = i = 1 N [ g i T ( x i ; θ m ) + 1 2 h i ( T ( x i ; θ m ) ) 2 ] + Ω ( T ( x i , θ m ) )

    这里,为了方便,把上述的 T ( x i , θ m ) 变为 T m ( x i ) 来表示,

    在这里我们需要对 T m ( x i ) 做出一个定义,

    T m ( x ) = w q ( x ) w R T , q : R d { 1 , 2 , . . . , J }

    w代表的是树中树叶的权重,q代表的是树的结构,J代表树的叶子节点个数,

    这时定义树的复杂度如下,

    Ω ( T m ) = γ J + 1 2 λ j = 1 J w j 2

    还是上面那个图,

    Ω ( T m ) = γ 3 + 1 2 λ ( 4 + 0.01 + 1 )

    定义第j个节点中数据子集的编号为如下 I j = { i | q ( x i ) = j } ,对之前的目标函数重新表达可得,

    O b j m = i = 1 N [ g i T ( x i ; θ m ) + 1 2 h i ( T ( x i ; θ m ) ) 2 ] + Ω ( T ( x i , θ m ) )

    = i = 1 N [ g i w q ( x i ) + 1 2 h i w q ( x i ) 2 ] + γ J + 1 2 λ j = 1 J w j 2

    = j = 1 J [ ( i I j g i ) w j + 1 2 i I j h i w j 2 ] + γ J + 1 2 λ j = 1 J w j 2

    = j = 1 J [ ( i I j g i ) w j + 1 2 ( i I j h i + λ ) w j 2 ] + γ J

    上述公式的意义在于把所有样本加和的公式转变为所有树的加和公式

    对于上述最后的公式求最小值,其实是一个简单的二次项求极小值的过程,

    a r g m i n x ( G x + 1 2 H x 2 ) = G H , H > 0 m i n x ( G x + 1 2 H x 2 ) = 1 2 G 2 H

    G j = i I j g i , H j = i I j h i ,可得如下公式,

    O b j m = j = 1 J [ G j w j + 1 2 ( H j + λ ) w j 2 ] + γ J

    假设现在树的结构定下,那么最优解如下,

    w j = G j H j + λ O b j = 1 2 j = 1 J G j 2 H j + λ + γ J

    上述的Obj就衡量了一个已经确定的树结构的性能如何,如下为衡量结果的一个实例,

    这时有一个问题,就是我们虽然已经知道如何衡量树的好坏了,但是不知道如何构建树,因而下面就开始讲如何启发式的构造树,


    输入:训练集 { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x N , y N ) }

    输出:决策树

    1. 从depth=0开始
    2. 对于树的每个节点,都通过一定的规则分裂节点,计算信息增益,公式如下,(只单纯考虑当前待分裂节点)

    G a i n = O b j b e f o r e O b j a f t e r

    = [ 1 2 ( G L + G R ) 2 H L + H R + λ + γ j ] [ 1 2 G L 2 H L + λ + γ j l ] [ 1 2 G R 2 H R + λ + γ j r ]

    = 1 2 [ G L 2 H L + λ + G R 2 H R + λ ( G L + G R ) 2 H L + H R + λ ] γ

    其中 j = j l + j r 1

    对于寻找合适的分割点,可以通过线性搜索的方法完成,

    1. 找到所有特征中Gain最大的特征作为分裂标准,继续分裂,直到满足分裂停止条件,

    对于算法的时间复杂度,遍历每一层(这里的每一层指的是树上同一深度的节点)时,对于每个feature,都有会进行一次快速排序,因而时间复杂度为 O ( N l o g ( N ) ) , 这里的N为样本总个数,而一共有d个feature,因而遍历一层需要的时间为 O ( d N l o g ( N ) ) ,树平均有K层,那么一个树训练完成后总的时间复杂度为 K d N l o g ( N )

  • 正则化与剪枝

    • 根据Gain的大小进行改进

      分裂的信息增益如下,

      G a i n = 1 2 [ G L 2 H L + λ + G R 2 H R + λ ( G L + G R ) 2 H L + H R + λ ] γ

      如果所有特征中最大的Gain小于0,则停止分裂,

    • 后剪枝

      已经建立好树之后,把所有的Gain为负的树枝都减掉,

  • 总体算法


    1. 添加一棵新树,
    2. 计算每个节点的 g i h i
    3. 分裂节点建立树 T m ( x ) ,分裂的目标函数为
      O b j = 1 2 j = 1 J G j 2 H j + λ + γ J
    4. T m ( x ) 添加到之前的模型中
      f m ( x ) = f m 1 ( x ) + ϵ T m ( x )   ( a c u t a l l y   T ( x ; θ m ) )

      这里的 ϵ 为学习率,
    5. 训练完成

  • 拓展之近似算法

    上述方法中最核心的内容为如何分裂节点,最先想到的是暴力搜索,就是针对每个特征以及每个特征的所有可能取值,都去计算一遍Gain,得到最大者分裂,
    注意图中加重内容,在对某一个特征计算Gain的时候需要先把数据按照这一维数据的大小排序,这样操作会让算法运行的更有效,

    但是问题是如果说数据量太大或者电脑的内存不够,不支持这么庞大的计算,论文作者就引入了近似算法的概念,

    算法的核心在于对于某一个特征,不去遍历所有可能的值作为分裂值,而只是选择最有可能成为最优分裂值的子集作为分裂值的候选者,因而算法要比之前快很多,

    首先,对于数据集的第k个特征,有如下数据集 D k = { ( x 1 k , h 1 ) , ( x 2 k , h 2 ) , . . . , ( x n k , h n ) } ,定义一个排序函数,
    r k : R [ 0 , + ) ,

    r k ( z ) = 1 ( x , h ) D k h ( x , h ) D k , x < z h

    对于上述问题,找到一系列候选值,
    | r k ( s k , j ) r k ( s k , j + 1 ) | < ε , s k 1 = m i n i x i k , s k l = m a x i x i k

    其中 ε 是一个近似值,从这里可以知道会产生 1 ε 个候选值,而且每个值都赋予了 h i 的权重,可以从下式中得到答案,

    O b j m = i = 1 N 1 2 h i ( f t ( x i ) g i h i ) 2 + Ω ( T m ) + c o n s t a n t

    这就是最初目标函数的变形,可以看出,每个样本被赋予了 h i 的权重,

    这样再通过这些候选点把样本按照桶排序的方法把相近的数据放入一个桶中,再逐桶计算 G H ,而后在这个基础上来选取最优分裂值,

  • 拓展之block储存加速

    算法大量的时间消耗在对数据的排序上面,而论文的做法是先对每个feature进行排序,并记录排序后每个数据指向其原始梯度的指针,而后把所有排好序的feature放在一起组成一个新的数据,这样每个数据都能够根据记录的指针找到其原始的梯度,这样再对feature进行线性寻找最佳分裂值时不用每次都重新排一次序了,从而大大提升算法的时间

  • 拓展之对比

    • xgboost gbdt

      1. 传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。
      2. 传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。
      3. xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
      4. 对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。
      5. 实现了一种分裂节点寻找的近似算法,用于加速和减小内存消耗。
      6. data事先对于每一个feature都排好序并以block的形式存储,利于并行计算,
发布了36 篇原创文章 · 获赞 42 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_37688445/article/details/79272565