Boosted Trees 介绍

Boosted Trees 介绍

官方地址原文介绍:https://github.com/dmlc/xgboost.git

Boosted Trees 是一种机器学习算法,它使用多棵决策树来提高模型的预测准确性。Boosted Trees 的主要思想是将多棵树组合起来,以提高模型的泛化能力和鲁棒性。Boosted Trees 是一种通用的机器学习算法,可以使用不同的损失函数和优化算法来实现。随机森林通过构建多个相互独立的决策树来形成一个强学习器。提升树通过逐步构建多个决策树,每棵新树尝试修正前一棵树的错误预测。

XGBoost 是一种具体的 Boosted Trees 算法实现,它是由 Tianqi Chen 等人在 2014 年开发的。XGBoost 是一个开源的机器学习库,提供了一个高效、可扩展的 Boosted Trees 实现。XGBoost 使用了许多技术来提高模型的性能,例如二阶梯度优化、列抽样、并行计算等。

XGBoost 代表“Extreme Gradient Boosting”,其中“Gradient Boosting”一词源自 Friedman 的论文 Greedy Function Approximation: A Gradient Boosting Machine。XGBoost 是一个优化的分布式梯度提升库,旨在高效、灵活和便携。 它在 Gradient Boosting 框架下实现机器学习算法。 XGBoost 提供了并行树提升(也称为 GBDT、GBM),可以快速准确地解决许多数据科学问题。 相同的代码在主要分布式环境(Kubernetes、Hadoop、SGE、Dask、Spark、PySpark)上运行,可以解决超过数十亿个示例的问题。

梯度提升树已经存在了一段时间,有很多相关的材料。本教程将使用监督学习的元素,以自包含和原则的方式解释提升树。我们认为这种解释更加清晰、正式,并激发了 XGBoost 中使用的模型公式。

监督学习要素

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

模型和参数

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

参数是我们需要从数据中学习的未确定部分。在线性回归问题中,参数是系数 θ \theta θ。通常我们会用 θ \theta θ 来表示参数(模型中有许多参数,我们在此的定义是宽松的)。

目标函数:训练损失 + 正则化

通过对 y i y_i yi 的合理选择,我们可以表示各种任务,例如回归、分类和排序。训练模型的任务是找到最适合训练数据 x i x_i xi 和标签 y i y_i yi 的最佳参数 θ \theta θ。为了训练模型,我们需要定义目标函数来衡量模型对训练数据的拟合程度。

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

obj ( θ ) = L ( θ ) + Ω ( θ ) \text{obj}(\theta) = L(\theta) + \Omega(\theta) obj(θ)=L(θ)+Ω(θ)

其中 L L L 是训练损失函数,而 Ω \Omega Ω 是正则化项。训练损失衡量我们的模型相对于训练数据的预测能力。常用的 L L L均方误差,其公式为

L ( θ ) = ∑ i ( y i − y ^ i ) 2 L(\theta) = \sum_i (y_i-\hat{y}_i)^2 L(θ)=i(yiy^i)2

另一个常用的损失函数是用于逻辑回归的逻辑损失:

L ( θ ) = ∑ i [ y i ln ⁡ ( 1 + e − y ^ i ) + ( 1 − y i ) ln ⁡ ( 1 + e y ^ i ) ] L(\theta) = \sum_i[ y_i\ln (1+e^{-\hat{y}_i}) + (1-y_i)\ln (1+e^{\hat{y}_i})] L(θ)=i[yiln(1+ey^i)+(1yi)ln(1+ey^i)]

正则化项是人们通常忘记添加的部分。正则化项控制模型的复杂度,帮助我们避免过拟合。这个听起来有点抽象,所以让我们考虑以下图中的问题。你被要求根据图中左上角的数据点拟合一个阶跃函数。你认为哪种解决方案是最好的拟合?

step functions to fit data points, illustrating bias-variance tradeoff

正确答案用红色标记。请考虑这在视觉上是否是一个合理的拟合。一般原则是我们既想要一个简单具有预测性的模型。两者之间的权衡在机器学习中也被称为偏差-方差权衡

为什么介绍一般原则?

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

决策树集成

现在我们已经介绍了监督学习的要素,让我们开始了解真实的树模型。首先,让我们了解 XGBoost 的模型选择:决策树集成。树集成模型由一组分类和回归树(CART)组成。以下是一个 CART 的简单示例,用于分类某人是否会喜欢假想的计算机游戏 X。

a toy example for CART

我们将一个家庭的成员分类到不同的叶子上,并在相应的叶子上赋予他们分数。CART 与决策树有点不同,决策树的叶子仅包含决策值。在 CART 中,每个叶子都关联一个实际分数,这为我们提供了超越分类的更丰富的解释。这也允许我们在优化时使用一种有原则的、统一的方法,如我们将在本教程后面部分看到的。

通常,单棵树不够强大,无法在实际中使用。实际使用的是集成模型,它将多棵树的预测结果相加。

a toy example for tree ensemble, consisting of two CARTs

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

y ^ i = ∑ k = 1 K f k ( x i ) , f k ∈ F \hat{y}_i = \sum_{k=1}^K f_k(x_i), f_k \in \mathcal{F} y^i=k=1Kfk(xi),fkF

其中 K K K 是树的数量, f k f_k fk 是函数空间 F \mathcal{F} F 中的一个函数, F \mathcal{F} F 是所有可能的 CART 的集合。要优化的目标函数为

obj ( θ ) = ∑ i n l ( y i , y ^ i ) + ∑ k = 1 K ω ( f k ) \text{obj}(\theta) = \sum_i^n l(y_i, \hat{y}_i) + \sum_{k=1}^K \omega(f_k) obj(θ)=inl(yi,y^i)+k=1Kω(fk)

其中 ω ( f k ) \omega(f_k) ω(fk) 是树 f k f_k fk 的复杂度,稍后将详细定义。

现在来个有趣的问题:随机森林使用的模型是什么?树集成!所以随机森林和提升树实际上是相同的模型;区别在于我们如何训练它们。这意味着,如果你为树集成写了一个预测服务,你只需写一个,它应该同时适用于随机森林和梯度提升树。(请参见 Treelite 了解实际示例。)这就是监督学习要素如此重要的一个例子。
树提升

Tree Boosting

现在我们介绍了模型,让我们来讨论训练:我们应该如何学习这些树?答案是,和所有监督学习模型一样:定义目标函数并优化它

以下是目标函数(记住它总是包含训练损失和正则化):
obj = ∑ i = 1 n l ( y i , y ^ i ( t ) ) + ∑ i = 1 t ω ( f i ) \text{obj} = \sum_{i=1}^n l(y_i, \hat{y}_i^{(t)}) + \sum_{i=1}^t\omega(f_i) obj=i=1nl(yi,y^i(t))+i=1tω(fi)

Additive Training

我们首先要问的问题是:树的参数是什么?你会发现我们需要学习的是那些函数 f i f_i fi,每个函数都包含树的结构和叶子的分数。学习树结构比传统优化问题难得多,在传统优化问题中你可以简单地取梯度。一次学习所有的树是不可能的。相反,我们使用加法策略:固定我们已经学到的东西,每次添加一棵新树。我们将步骤 t t t 的预测值写为 y ^ i ( t ) \hat{y}_i^{(t)} y^i(t)。然后我们有

y ^ i ( 0 ) = 0 y ^ i ( 1 ) = f 1 ( x i ) = y ^ i ( 0 ) + f 1 ( x i ) y ^ i ( 2 ) = f 1 ( x i ) + f 2 ( x i ) = y ^ i ( 1 ) + f 2 ( x i ) … y ^ i ( t ) = ∑ k = 1 t f k ( x i ) = y ^ i ( t − 1 ) + f t ( x i ) \begin{align*} \hat{y}_i^{(0)} &= 0\\ \hat{y}_i^{(1)} &= f_1(x_i) = \hat{y}_i^{(0)} + f_1(x_i)\\ \hat{y}_i^{(2)} &= f_1(x_i) + f_2(x_i)= \hat{y}_i^{(1)} + f_2(x_i)\\ &\dots\\ \hat{y}_i^{(t)} &= \sum_{k=1}^t f_k(x_i)= \hat{y}_i^{(t-1)} + f_t(x_i) \end{align*} y^i(0)y^i(1)y^i(2)y^i(t)=0=f1(xi)=y^i(0)+f1(xi)=f1(xi)+f2(xi)=y^i(1)+f2(xi)=k=1tfk(xi)=y^i(t1)+ft(xi)

我们还需要问:每一步我们需要哪棵树?每一步添加的树 f t ( x ) f_t(x) ft(x)都是为了优化当前的目标函数。
obj ( t ) = ∑ i = 1 n l ( y i , y ^ i ( t ) ) + ∑ i = 1 t ω ( f i ) = ∑ i = 1 n l ( y i , y ^ i ( t − 1 ) + f t ( x i ) ) + ω ( f t ) + c o n s t a n t \begin{align*} \text{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) + \mathrm{constant} \end{align*} obj(t)=i=1nl(yi,y^i(t))+i=1tω(fi)=i=1nl(yi,y^i(t1)+ft(xi))+ω(ft)+constant
如果我们考虑使用均方误差(MSE)作为损失函数,则目标变为
obj ( t ) = ∑ i = 1 n ( y i − ( y ^ i ( t − 1 ) + f t ( x i ) ) ) 2 + ∑ i = 1 t ω ( f i ) = ∑ i = 1 n [ 2 ( y ^ i ( t − 1 ) − y i ) f t ( x i ) + f t ( x i ) 2 ] + ω ( f t ) + c o n s t a n t \begin{align*} \text{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) + \mathrm{constant} \end{align*} obj(t)=i=1n(yi(y^i(t1)+ft(xi)))2+i=1tω(fi)=i=1n[2(y^i(t1)yi)ft(xi)+ft(xi)2]+ω(ft)+constant
MSE 的形式很友好,有一个一阶项(通常称为残差)和一个二阶项。对于其他感兴趣的损失(例如逻辑损失),不容易得到如此好的形式。因此在一般情况下,我们对损失函数进行二阶泰勒展开

泰勒公式:
f ( x + Δ x ) ≃ f ( x ) + f ′ ( x ) Δ x + 1 2 f ′ ′ ( x ) Δ x 2 f(x+\Delta x)\simeq f(x)+f'(x)\Delta x+\frac12f''(x)\Delta x^2 f(x+Δx)f(x)+f(x)Δx+21f′′(x)Δx2
损失函数进行二阶泰勒展开
obj ( t ) = ∑ i = 1 n l ( y i , y ^ i ( t − 1 ) + f t ( x i ) ) + ω ( f t ) + c o n s t a n t ≃ ∑ i = 1 n [ l ( y i , y ^ i ( t − 1 ) ) + g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + ω ( f t ) + c o n s t a n t \begin{align*} \text{obj}^{(t)} & = \sum_{i=1}^n l(y_i, \hat{y}_i^{(t-1)} + f_t(x_i)) + \omega(f_t) + \mathrm{constant}\\ & \simeq \sum_{i=1}^n [l(y_i, \hat{y}_i^{(t-1)}) + g_i f_t(x_i) + \frac{1}{2} h_i f_t^2(x_i)] + \omega(f_t) + \mathrm{constant} \end{align*} obj(t)=i=1nl(yi,y^i(t1)+ft(xi))+ω(ft)+constanti=1n[l(yi,y^i(t1))+gift(xi)+21hift2(xi)]+ω(ft)+constant
其中 g i g_i gi h i h_i hi 定义为
g i = ∂ y ^ i ( t − 1 ) l ( y i , y ^ i ( t − 1 ) ) h i = ∂ y ^ i ( t − 1 ) 2 l ( y i , y ^ i ( t − 1 ) ) \begin{align*} g_i &= \partial_{\hat{y}_i^{(t-1)}} l(y_i, \hat{y}_i^{(t-1)})\\ h_i &= \partial_{\hat{y}_i^{(t-1)}}^2 l(y_i, \hat{y}_i^{(t-1)}) \end{align*} gihi=y^i(t1)l(yi,y^i(t1))=y^i(t1)2l(yi,y^i(t1))
在我们移除所有常数后,步骤 t t t​ 的具体目标变为
∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + ω ( f t ) \sum_{i=1}^n [g_i f_t(x_i) + \frac{1}{2} h_i f_t^2(x_i)] + \omega(f_t) i=1n[gift(xi)+21hift2(xi)]+ω(ft)
这成为我们新树的优化目标。这个定义的一个重要优点是目标函数的值仅依赖于 g i g_i gi h i h_i hi。这就是 XGBoost 支持自定义损失函数的方式。我们可以使用完全相同的求解器,通过以 g i g_i gi h i h_i hi 作为输入,来优化包括逻辑回归和对偶排名在内的每个损失函数!

Model Complexity

我们已经介绍了训练步骤,但等等,还有一个重要的事情,正则化项!我们需要定义树 ω ( f ) \omega(f) ω(f) 的复杂度。为此,让我们首先将树 f ( x ) f(x) f(x) 的定义细化为

f t ( x ) = w q ( x ) , w ∈ R T , q : R d → { 1 , 2 , ⋯   , T } f_t(x) = w_{q(x)}, w \in R^T, q:R^d\rightarrow \{1,2,\cdots,T\} ft(x)=wq(x),wRT,q:Rd{1,2,,T}

这里 w w w 是叶子上的分数向量, q q q 是将每个数据点分配到相应叶子的函数, T T T 是叶子的数量。在 XGBoost 中,我们将复杂度定义为
ω ( f ) = γ T + 1 2 λ ∑ j = 1 T w j 2 \omega(f) = \gamma T + \frac{1}{2}\lambda \sum_{j=1}^T w_j^2 ω(f)=γT+21λj=1Twj2
当然,有不止一种定义复杂度的方法,但这种方法在实践中效果很好。正则化是大多数树包处理得不太仔细的部分,或简单忽略。这是因为传统的树学习处理仅强调提高纯度,而复杂度控制留给了启发式方法。通过正式定义,我们可以更好地了解我们在学习什么,并获得在实际中表现良好的模型。

The Structure Score

这里是推导的神奇部分。在重新定义树模型后,我们可以用 t t t​-th 树的目标值表示为:
obj ( t ) ≈ ∑ i = 1 n [ g i w q ( x i ) + 1 2 h i w q ( x i ) 2 ] + γ T + 1 2 λ ∑ j = 1 T w j 2 = ∑ j = 1 T [ ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ] + γ T \begin{align*} \text{obj}^{(t)} &\approx \sum_{i=1}^n [g_i w_{q(x_i)} + \frac{1}{2} h_i w_{q(x_i)}^2] + \gamma T + \frac{1}{2}\lambda \sum_{j=1}^T w_j^2\\ &= \sum^T_{j=1} [(\sum_{i\in I_j} g_i) w_j + \frac{1}{2} (\sum_{i\in I_j} h_i + \lambda) w_j^2 ] + \gamma T \end{align*} obj(t)i=1n[giwq(xi)+21hiwq(xi)2]+γT+21λj=1Twj2=j=1T[(iIjgi)wj+21(iIjhi+λ)wj2]+γT
其中 I j = { i ∣ q ( x i ) = j } I_j = \{i|q(x_i)=j\} Ij={iq(xi)=j} 是分配到第 j j j 叶子的数据点的索引集。注意,在第二行中,我们更改了求和的索引,因为所有相同叶子上的数据点得到相同的分数。我们可以通过定义 G j = ∑ i ∈ I j g i G_j = \sum_{i\in I_j} g_i Gj=iIjgi H j = ∑ i ∈ I j h i H_j = \sum_{i\in I_j} h_i Hj=iIjhi 进一步压缩表达式:
obj ( t ) = ∑ j = 1 T [ G j w j + 1 2 ( H j + λ ) w j 2 ] + γ T \text{obj}^{(t)} = \sum^T_{j=1} [G_jw_j + \frac{1}{2} (H_j+\lambda) w_j^2] +\gamma T obj(t)=j=1T[Gjwj+21(Hj+λ)wj2]+γT
在这个方程中, w j w_j wj 彼此独立,形式为 G j w j + 1 2 ( H j + λ ) w j 2 G_jw_j+\frac{1}{2}(H_j+\lambda)w_j^2 Gjwj+21(Hj+λ)wj2 是二次的,并且给定结构 q ( x ) q(x) q(x) 的最佳 w j w_j wj (二次函数求导,令导数等于0)和我们可以获得的最佳目标减小值为:
w j ∗ = − G j H j + λ o b j ∗ = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T \begin{aligned}w_{j}^{*}&=-\frac{G_j}{H_j+\lambda}\\\mathrm{obj}^{*}&=-\frac12\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T\end{aligned} wjobj=Hj+λGj=21j=1THj+λGj2+γT
最后一个等式衡量树结构 q ( x ) q(x) q(x)的好坏。

如果所有这些听起来有点复杂,让我们看看图片,看看如何计算分数。基本上,对于给定的树结构,我们将统计 g i g_i gi h i h_i hi推送到它们所属的叶节点上,将统计数据相加,然后使用公式计算树的好坏。这分数类似于决策树中的杂质度量,但它还考虑了模型的复杂度。

Learn the tree structure

现在我们有了一种方法来衡量一棵树的好坏,在实际中,由于枚举所有可能的树结构是不可能的,我们采用的是逐步添加的方法:每次仅添加一个分裂。具体来说,我们试图将一个叶子节点分成两个叶子节点,并计算其增益(Gain)。公式如下:

Gain = 1 2 [ G L 2 H L + λ + G R 2 H R + λ − ( G L + G R ) 2 H L + H R + λ ] − γ \text{Gain} = \frac{1}{2} \left[\frac{G_L^2}{H_L + \lambda} + \frac{G_R^2}{H_R + \lambda} - \frac{(G_L + G_R)^2}{H_L + H_R + \lambda}\right] - \gamma Gain=21[HL+λGL2+HR+λGR2HL+HR+λ(GL+GR)2]γ
此公式可以分解为以下部分:

  1. 新左叶子的得分。

  2. 新右叶子的得分。

  3. 原叶子的得分。

  4. 新增叶子的正则化项。

我们可以得出一个重要结论:如果增益小于 γ \gamma γ,我们最好不要添加该分裂。这就是树模型中的剪枝技术的核心理念。通过使用监督学习的原则,我们能够自然地理解这些技术的有效性。

对于连续值数据,我们通常希望寻找最佳分裂点。为了有效地实现这一点,我们将所有实例按某一特征值排序,如下图所示。

选择最佳分裂的示意图

从左到右扫描就足以计算所有可能分裂方案的结构得分,从而高效地找到最佳分裂点。

[!NOTE]

注意:加法树学习的局限性

由于枚举所有可能的树结构是不可能的,我们采用逐步添加的方法,即每次仅添加一个分裂。这种方法在大多数情况下效果良好,但在某些极端情况下可能会失败,因为我们每次只考虑一个特征维度。有关示例,请参见 Can Gradient Boosting Learn Simple Arithmetic?

关于 XGBoost 的最后话语

现在你已经了解了什么是提升树,你可能会问,XGBoost 的介绍在哪里?XGBoost 是一个受本教程中介绍的正式原理所激发的工具!更重要的是,它是在系统优化机器学习原理方面经过深思熟虑开发的。这个库的目标是将机器的计算极限推向极致,提供一个可扩展可移植准确的库。确保你尝试一下,最重要的是,为社区贡献你的智慧(代码、示例、教程)!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值