Introduction to XGB

XGBoost代表“Extreme Gradient Boosting”,其中“梯度增强”一词源于弗里德曼的论文《Greedy Function Approximation: A Gradient Boosting Machine》。这是一个关于梯度增强树的教程,大部分内容都是基于这些幻灯片,作者是XGBoost的原作者陈天琦。

梯度提升树已经被提出有一段时间了,有很多关于这个主题的材料。本教程将使用监督学习的元素,以一种自包含和有原则的方式解释提升树。我们认为这种解释更简洁、更正式,并推动了XGBoost中使用的模型公式

Elements of Supervised Learning

XGBoost用于监督学习问题,我们使用训练数据(具有多个特征)x_i来预测目标变量y_i。在学习树之前,让我们先回顾一下监督学习中的基本元素。

Model and Parameters

有监督学习模型通常指的是用输入x_i来预测y_i的数学结构。一个常见的例子是一个线性模型, 给定预测值\hat{y}_i = \sum_{j} \theta_j x_{ij},其是输入特征的线性加权组合。根据任务的不同,预测值可以有不同的解释,如回归或分类。例如,它可以通过逻辑变换得到正类在逻辑回归中的概率,也可以作为我们对输出进行排序时的一个排序分数。

参数是我们需要从数据中学习的待定部分。在线性回归问题,参数是系数\theta。通常我们会使用\theta表示参数(有许多参数在一个模型中,这里我们的定义是草率的)。

Objective Function: Training Loss + Regularization

通过对y_i的合理选择,我们可以表达各种不同的任务,如回归、分类、排序等。训练模型的任务,旨在根据训练数据x_i和标签数据y_i站到最佳的参数\theta。为了训练模型,我们需要定义目标函数来度量模型与训练数据的匹配程度。

目标函数的一个显著特征是由训练损失和正则化项两部分组成:

                                                                                     obj(\theta) = L(\theta) + \Omega (\theta)

其中L是损失函数,\Omega是正则化项。训练损失衡量的是我们的模型对训练数据的预测能力。一个常见的选择是均方误差,定义为:

                                                                                    L(\theta) = \sum_i(y_i - \hat{y_i})^2

另一个常用的损失函数是logistic损失,用于logistic回归:

                                                              L(\thate) = \sum_i[y_i ln(1 + e^{-\hat{y}_i}) + (1-y_i) ln(1 + e^{\hat{y}_i}) ]

正则化项是人们经常忘记添加的,它控制了模型的复杂度,避免了过度拟合。这听起来有点抽象,所以让我们考虑下图中的问题。给定图像左上角的输入数据点,要求您在视觉上拟合一个阶跃函数。你认为三个方案中哪一个最合适?

正确答案用红色标出。请考虑这在视觉上是否适合你。总的原则是我们需要一个简单的预测模型。两者之间的权衡在机器学习中也被称为偏差-方差权衡。

Why introduce the general principle?

上面介绍的元素构成了监督学习的基本元素,它们是机器学习工具包的天然构件。例如,你应该能够描述梯度提升树和随机森林之间的差异和共性。以一种形式化的方式理解这个过程也有助于我们理解我们正在学习的目标,以及诸如剪枝和平滑等启发法背后的原因。

Decision Tree Ensembles

既然我们已经介绍了监督学习的要素,让我们从真正的树开始。首先,让我们首先了解XGBoost的模型选择:决策树集成。树集成模型由一组分类回归树(CART)组成。这里有一个简单的CART示例,它可以分类用户是否喜欢虚拟的电脑游戏X。

我们把一个家庭的成员分到不同的叶子节点,并在相应的叶子上给他们打分。CART与决策树稍有不同,在决策树中,叶子只包含决策值。在CART中,每个叶节点都有一个真实的分数,这给了我们比分类更丰富的解释。这还允许使用一种有原则的、统一的优化方法,我们将在本教程的后面部分看到这一点。

通常情况下,一棵单独的树不够强壮,不能用于实践。实际使用的是集成模型,它将多个树的预测汇总在一起。

这是一个由两棵树组成的树的例子。将每棵树的预测得分相加,得到最终得分。如果你看看这个例子,一个重要的事实是这两棵树试图互补。数学上,我们可以把模型写成这种形式:

                                                                                  \hat{y}_i = \sum_{k=1}^K f_k(x_i), \ f_k \in \math{F}

其中K为树的数量,f为函数空间F中的一个函数,F为所有可能的CARTs的集合。优化的目标函数为:

                                                                          obj(\theta) = \sum_{i}^n l(y_i, \hat{y}_i) + \sum_{k=1}^K \Omega(f_k)

现在有一个棘手的问题:随机森林中使用的模型是什么?树集成!所以随机森林和提升树是完全相同的模型;区别在于我们如何训练他们。这意味着,如果您为树集成编写一个预测服务,您只需要编写一个,它应该适用于随机森林和梯度提升树。

Tree Boosting

既然我们已经介绍了模型,现在让我们转向训练:我们应该如何学习树?答案是,就像所有监督学习模型一样,定义一个目标函数并优化它!

让下式为目标函数(请记住,它总是需要包含训练损失和正则化)::

                                                                            obj = \sum_{i=1}^n l(y_i, \hat{y}_i^{(t)}) + \sum_{i=1}^t \Omega (f_i)

Additive Training

我们要问的第一个问题是:树的参数是什么?你会发现我们需要学习的是那些函数f_i,每个函数都包含树的结构和叶子分数。学习树结构比传统的优化问题要困难得多,在传统优化问题中,你可以简单地取梯度。一次学完所有的树是很难的。相反,我们使用一种附加策略:修复我们所学的内容,并一次添加一个新树。我们把第t步的预测值写成\hat{y}_i^{(t)}。然后我们有

                                                                       \hat{y}_i^{(0)}=0

                                                                       \hat{y}_i^{(1)}=f_1(x_i)=\hat{y}_i^{(0)} + f_1(x)

                                                                      \hat{y}_i^{(2)}=f_1(x_i)+f_2(x_i)=\hat{y}_i^{(1)} + f_2(x)

                                                                        ......

                                                                      \hat{y}_i^{(t)}=\sum_{k=1}^t f_k(x_i)=\hat{y}_i^{(t-1)} + f_t(x_i)

剩下的问题是:每一步我们想要哪棵树?一个很自然的事情就是添加一个优化我们目标的。

                                                                obj^{(t)} = \sum_{i=1}^n l(y_i, \hat{y}_i^{(t)}) + \sum_{i=1}^t \Omega (f_i)

                                                                          = \sum_{i=1}^n l(y_i, \hat{y}_i^{(t-1)} + f_t(x_i)) + \Omega (f_t) + constant

如果我们考虑使用均方误差(MSE)作为损失函数,目标就变成了:

                                                              obj^{(t)} = \sum_{i=1}^n (y_i - (\hat{y}_i^{(t-1)} + f_t(x_i)))^2 + \sum_{i=1}^t \Omega (f_i)

                                                                        = \sum_{i=1}^n [2(\hat{y}_i^{(t-1)} - y_i)f_t(x_i) + f_t(x_i)^2] +\Omega (f_t) + constant

MSE的形式很友好,有一次项(通常称为残差)和二次项。对于其他的损失(例如逻辑损失),要得到这样好的表单并不容易。一般情况下,我们把损失函数的泰勒展开式推广到二阶:

                                                      obj^{(t)}= \sum_{i=1}^n [l(y_i, \hat{y}_i^{(t-1)}) + g_if_t(x_i)) + \frac{1}{2} h_i f^2_t(x_i) ] + \Omega (f_t) + constant

g_ih_i的定义为:

                                                                         g_i = \partial _{\hat{y}_i^{(t-1)}}l(y_i, \hat{y}_i^{(t-1)})

                                                                         h_i = \partial^2 _{\hat{y}_i^{(t-1)}}l(y_i, \hat{y}_i^{(t-1)})

在我们移除所有常数之后,在步骤t处的特定目标就变成了:

                                                             \sum_{i=1}^n [g_i f_t(x_i) + \frac{1}{2} h_i f^2_t(x_i)] + \Omega(f_t)

这就是我们对新树的优化目标。这个定义的一个重要优点是目标函数的值只取决于g_ih_i。这就是XGBoost支持自定义损失函数的方式。我们可以优化每一个损失函数,包括逻辑回归和成对排序,使用完全相同的解决方案,以g_ih_i为输入!

Model Complexity

我们已经介绍了训练步骤,但是等一下,有一件重要的事情,正则化术语!我们需要定义树的复杂度\Omega(f)。为了做到这一点,让我们首先改进树f(x)的定义为:

                                                       f_t(x)=w_{q(x)}, \ w \in R^T, \ q:R^d -> \{ 1, 2, ..., T \}.

其中w为叶子节点的得分向量,q为将每个数据点赋值到对应叶子的函数,T为叶子数量。在XGBoost中,我们将复杂性定义为:

                                                                             \Omega(f) = \gamma T + \frac{1}{2} \lambda \sum_{j=1}^T w_j^2

当然,定义复杂性的方法不止一种,但是这种方法在实践中很有效。正则化是大多数树包处理得不太仔细的一部分,或者干脆忽略它。这是因为传统的树学习方法只强调改善杂质,而复杂性控制则留给启发式。通过正式定义它,我们可以更好地了解我们正在学习什么,并获得表现良好的模型。

The Structure Score

这就是推导的神奇之处。重新制定树模型后,我们可以将第t颗树的目标值写成:

                                                               obj^{(t)} \approx \sum_{i=1}^n [g_i w_{q(x_i)} + \frac{1}{2} h_i w^2_{q(x_i)}] + \gamma T + \frac{1}{2} \lambda \sum_{j=1}^T w_j^2

                                                                         =\sum_{j=1}^T[(\sum_{i \in I_j} g_i)w_j + \frac{1}{2}(\sum_{i \in I_j} h_i + \lambda )w^2_j] + \gamma T

其中I_j = \{ i | q(x_i)=j \}是分配给第j个叶子的数据点的索引集。注意,在第二行中,我们更改了求和的索引,因为同一叶子上的所有数据点都得到相同的分数。我们可以进一步压缩表达式,定义G_j = \sum_{i \in I_j} g_iH_j = \sum_{i \in I_j} h_i

                                                                    obj^{(t)} = \sum_{j=1}^T [G_jw_j + \frac{1}{2}(H_j + \lambda )w^2_j] + \gamma T

在这个方程中,w_j彼此独立,公式G_jw_j + \frac{1}{2}(H_j + \lambda )w^2_j是二次的,给定结构q(x)的最佳w_j和减少最好的目标我们可以得到:

                                                                                        w^*_j = - \frac{G_j}{H_j + \lambda }

                                                                            obj^*_j = - \frac{1}{2} \sum_{j=1}^T \frac{G^2_j}{H_j + \lambda } + \gamma T

最后一个方程衡量了树结构q(x)的好坏。

如果这一切听起来有点复杂,让我们看看图片,看看如何计算分数。基本上,对于给定的树结构,我们将统计数据g_ih_i推到它们所属的叶子上,将统计数据相加,然后使用公式计算树的好坏。这个分数类似于决策树中的杂质度量,除了它还考虑了模型的复杂性。

Learn the tree structure

现在,我们有了一种方法来衡量一棵树的好坏,理想情况下,我们会列举所有可能的树,然后选出最好的一棵。在实践中,这是一个棘手的问题,因此我们将尝试一次优化树的一个级别。具体来说,我们试着把一片树叶分成两片,它得到的分数是:

                                           Gain = \frac{1}{2} \left [ \frac{G^2_L}{H_L + \lambda } + \frac{G^2_R}{H_R + \lambda } + \frac{(G_L + G_R)^2}{H_L + H_R +\lambda } \right ] - \gamma

该公式可分解为:1)新左叶分数2)新右叶分数3)原叶分数4)附加叶正则化。我们可以看到一个重要的事实:如果获得小于\gamma,我们会做的更好不是添加分支。这正是基于树的模型中的修剪技术!通过使用监督学习的原则,我们可以很自然地得出这些技术有效的原因:

对于实值数据,我们通常希望寻找最优的分割。为了有效地做到这一点,我们将所有实例排序,如下图所示。

从左到右的扫描足以计算所有可能的分裂解的结构分数,我们可以有效地找到最佳分裂。

注意

加法树学习的局限性

由于难以枚举所有可能的树结构,所以我们一次添加一个分割。这种方法在大多数情况下都能很好地工作,但是也有一些由于这种方法而失败的边缘情况。对于这些边缘情况,由于我们一次只考虑一个特征维,所以训练结果是退化模型。看一下可以学习简单的梯度增强算法吗?了一个例子。

Final words on XGBoost

现在您已经了解了什么是助推树,您可能会问,XGBoost的介绍在哪里?XGBoost正是本教程中介绍的正式原则所激发的工具!更重要的是,它是在深入考虑系统优化和机器学习原理的基础上发展起来的。这个库的目标是突破计算机的计算极限,提供一个可伸缩的、可移植的、精确的库。请务必尝试一下,最重要的是,向社区贡献您的智慧(代码、示例、教程)!

XGBoost教程

在AWS上分布XGBoost纱线

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值