zoukankan      html  css  js  c++  java
  • GBDT记录

      GBDT(Gradient Boosting Decision Tree),是一种迭代的决策树算法,该算法由多棵决策树组成,所有树的结论累加起来做最终答案。

      GBDT主要由三个概念组成:Regression Decistion Tree(即DT),Gradient Boosting(即GB),Shrinkage (算法的一个重要演进分枝,目前大部分源码都按该版本实现)。GBDT的思想使其具有天然优势可以发现多种有区分性的特征以及特征组合,决策树的路径可以直接作为LR输入特征使用,省去了人工寻找特征、特征组合的步骤。(CTR预估中GBDT与LR融合方案)

    1 DT(回归树 Regression Decision Tree):

      决策树分为两大类,回归树和分类树。前者用于预测实数值;后者用于分类标签值。

      要强调的是,前者的结果加减是有意义的,后者则无意义。 GBDT的核心在于累加所有树的结果作为最终结果,而分类树的结果是没办法累加的,所以GBDT中的树都是回归树,不是分类树。GBDT用来做回归预测,调整后也可以用于分类。

        分类树:常用的分类树算法有ID3、C4.5、CART。

        回归树:如CART算法。

      回归树:回归树是可以用于回归的决策树模型,一个回归树对应着输入空间(即特征空间)的一个划分以及在划分单元上的输出值.与分类树不同的是,回归树对输入空间的划分采用一种启发式的方法,会遍历所有输入变量,找到最优的切分变量jj和最优的切分点ss,即选择第jj个特征xjxj和它的取值ss将输入空间划分为两部分,然后重复这个操作。

        如何找到最优的jj和ss是通过比较不同的划分的误差来得到的。一个输入空间的划分的误差是用真实值和划分区域的预测值的最小二乘来衡量:

          ,其中,每个划分单元的预测值是该单元内每个样本点的值的均值

       一个比较形象的例子:(借用别人的

          

      回归树算法:(《统计学习方法》中截图)

      

    2 GB(Gradient Boosting,梯度迭代):

      GB是一个算法框架,即可以将已有的分类或回归算法放入其中,得到一个性能很强大的算法。

      GB总共需要进行M次迭代,每次迭代产生一个模型,我们需要让每次迭代生成的模型对训练集的损失函数最小,通过采用梯度下降的方法,在每次迭代时通过向损失函数的负梯度方向移动来使得损失函数越来越小,这样我们就可以得到越来越精确的模型。

      (基于残差优化:在学习的过程中,首先学习一颗回归树,然后将“真实值-预测值”得到残差,再把残差作为一个学习目标,学习下一棵回归树,依次类推,直到残差小于某个接近0的阀值或回归树数目达到某一阀值。其核心思想是每轮通过拟合残差来降低损失函数。)

      GBDT的核心就在于,每一棵树学的是之前所有树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量。比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄;如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学。这就是Gradient Boosting在GBDT中的意义。

    3 Shrinkage(收缩) :

      Shrinkage(缩减)的思想认为,每次走一小步逐渐逼近结果的效果,要比每次迈一大步很快逼近结果的方式更容易避免过拟合。即它不完全信任每一个棵残差树,它认为每棵树只学到了真理的一小部分,累加的时候只累加一小部分,通过多学几棵树弥补不足。

    没用Shrinkage时:(yi表示第i棵树上y的预测值, y(1~i)表示前i棵树y的综合预测值)

      y(i+1) = 残差(y1~yi), 其中: 残差(y1~yi) =  y真实值 - y(1 ~ i)

      y(1 ~ i) = SUM(y1, ..., yi)

    Shrinkage不改变第一个方程,只把第二个方程改为: 

      y(1 ~ i) = y(1 ~ i-1) + step * yi

      本质上,Shrinkage为每棵树设置了一个weight,累加时要乘以这个weight,但和Gradient并没有关系。这个weight就是step。就像Adaboost一样,Shrinkage能减少过拟合发生也是经验证明的,目前还没有看到从理论的证明。

    4 几个重要问题:

    1)为什么使用GBDT,而不是直接用一个回归决策树代替?

      解决过拟合。Boosting的最大好处在于,每一步的残差计算其实变相地增大了分错样本的权重,而已经分对的样本则都趋向于0。这样后面的树就能越来越专注那些前面被分错的样本。

    2)GBDT中的G(Gradient)有体现吗?

      GBDT并没有使用Gradient优化,而是使用残差作为全局最优的绝对方向来优化。

    3)GBDT使用的boosting,和Adaboost关系?

      GBDT是boost Decistion Tree,不是Adaboost Decistion Tree就像提到决策树大家会想起C4.5,提到boost多数人也会想到Adaboost。

      Adaboost是另一种boost方法,它按分类对错,分配不同的权重,计算损失函数时使用这些权重,从而让“错分的样本权重越来越大,使它们更被重视”。

      Bootstrap也有类似思想,它在每一步迭代时不改变模型本身,也不计算残差,而是从N个样本训练集中按一定概率重新抽取N个样本出来(单个样本可以被重复抽取),对着这N个新的样本再训练一轮。由于数据集变了迭代模型训练结果也不一样,而一个样本被前面分错的越厉害,它的概率就被设的越高,这样就能同样达到逐步关注被分错的样本,逐步完善的效果。

      Adaboost的方法被实践证明是一种很好的防止过拟合的方法,但至于为什么则至今没从理论上被证明。GBDT也可以在使用残差的同时引入Bootstrap re-sampling,GBDT多数实现版本中也增加的这个选项,但是否一定使用则有不同看法。re-sampling一个缺点是它的随机性,即同样的数据集合训练两遍结果是不一样的,也就是模型不可稳定复现,这对评估是很大挑战,比如很难说一个模型变好是因为你选用了更好的特征,还是由于这次样本的随机因素。

    4)GBDT的适用范围?

      GBDT几乎可用于所有回归问题(线性/非线性),相对logistic regression仅能用于线性回归,GBDT的适用面非常广。亦可用于二分类问题(设定阈值,大于阈值为正例,反之为负例)。

    5)特征太多的处理?

      如果feature个数太多,每一棵回归树都要耗费大量时间,这时每个分支时可以随机抽一部分feature来遍历求最优。

    6)相比GBDT,XGBoost有什么区别?有什么优点?

    变化:

      1)xgboost在目标函数中显示的加上了正则化项,基学习为CART时,正则化项与树的叶子节点的数量和叶子节点的值有关。

      2)GB中使用Loss Function对f(x)的一阶导数计算出伪残差用于学习生成fm(x),xgboost不仅使用到了一阶导数,还使用二阶导数。

      3)CART回归树中寻找最佳分割点的衡量标准是最小化均方差,xgboost寻找分割点的标准是最大化,参数lamda,gama与正则化项相关。

    优点:

    • 在寻找最佳分割点时,考虑传统的枚举每个特征的所有可能分割点的贪心法效率太低,xgboost实现了一种近似的算法。大致的思想是根据百分位法列举几个可能成为分割点的候选者,然后从候选者中根据上面求分割点的公式计算找出最佳的分割点。
    • xgboost考虑了训练数据为稀疏值的情况,可以为缺失值或者指定的值指定分支的默认方向,这能大大提升算法的效率,paper提到50倍。
    • 特征列排序后以块的形式存储在内存中,在迭代中可以重复使用;虽然boosting算法迭代必须串行,但是在处理每个特征列时可以做到并行。
    • 按照特征列方式存储能优化寻找最佳的分割点,但是当以行计算梯度数据时会导致内存的不连续访问,严重时会导致cache miss,降低算法效率。paper中提到,可先将数据收集到线程内部的buffer,然后再计算,提高算法的效率。
    • xgboost 还考虑了当数据量比较大,内存不够时怎么有效的使用磁盘,主要是结合多线程、数据压缩、分片的方法,尽可能的提高算法的效率。


    说明:主要学习的不同大佬的博客尽力理解,并引用、总计和记录。

  • 相关阅读:
    ListView与ArrayAdapter(二)
    ListView与SimpleAdapter(三)
    对于ListView的一些用法(一)
    如何使用AsyncTask
    you must restart adb and eclipse的相关解决办法
    leetcode 移动零 JAVA
    leetcode 有效的字母异位词 java
    leetcode 单词拆分 II java
    leetcode 分割回文串 java
    leetcode 验证回文串 java
  • 原文地址:https://www.cnblogs.com/xunyingFree/p/10444766.html
Copyright © 2011-2022 走看看