今天学习了梯度提升决策树(Gradient Boosting Decision Tree, GBDT),准备写点东西作为记录。后续,我会用python 实现GBDT, 发布到我的Github上,敬请Star。
梯度提升算法是一种通用的学习算法,除了决策树,还可以使用其它模型作为基学习器。梯度提升算法的思想是通过调整模型,让损失函数的值不断减小, 然后将各个模型加起来作为最终的预测模型。而梯度提升决策树则是以决策树为基学习器。通常,我们认为决策树是没有参数的模型,可以用if-else规则来表达。因此,在理解梯度提升决策树的一个关键点和难点便是梯度!梯度提升体现在哪?决策树不是没有参数吗,如何求梯度?这是我在学习过程中遇到的两个问题。下面会一一解答。
首先,我们来回顾一下机器学习的基础知识。
机器学习算法一个基础知识是损失函数(loss function),损失函数用于指导模型的训练。
其中的(f)就是我们的模型,梯度提升算法就是根据损失函数对模型的一阶导数(梯度)来对模型进行更新。什么,可以对模型求导数???,等等,别急,没有想像的那么难。
对于回归问题,通常采用least square error (最小二乘误差)作为损失函数。
(Lleft(f ight) = sumfrac{1}{2}left(y_i - fleft(x_i ight) ight)^2)
对函数(f)求导数为:
(-frac{delta Lleft(f ight)}{delta f} = sumleft(y_i - fleft(x_i ight) ight))
于是,当函数(f)的值往梯度方向改变一定的值时,损失函数就会减小的最快,是不是很酷?
在 the elements of statistic learning 一书中,在361页的Algorithm 10.3中,步长可以算出来。不过,在实际的代码中,我们通常会设置一个学习率,这个学习率就是步长。假设我们设置的学习率为(lr),那么:
(fleft(x_{i+1} ight) = fleft(x_i ight) + lr * left(y_i - fleft(x_i ight) ight))
一个比较骚的操作时,不用上面的方式来更新函数值。而是先用一颗决策树来拟合上面的梯度,然后用决策树的预测值来替代上面的梯度,进行函数值的更新。
(fleft(x_{i+1} ight) = fleft(x_i ight) + lr * treeleft(x_i ight))
为什么不直接使用计算出来的梯度值呢? 为了防止过拟合, 提高模型的范化能力。
算法的整体流程图如下(摘自《the elements of statistic learning》):
需要注意的是,在代码实现的时候,并没有执行步骤(c), 取而代之的是设置的常量学习率。
好了,GBDT部分暂时就到这里了。如果有不懂的地方,欢迎留言提问。
结合前面提到的那本书看,另外还有我放到Github上面的代码看,学习效果会比较好。