概述
XGBoost是GBDT算法的一种变种,是一种常用的有监督集成学习算法;是一种伸缩性强、便捷的可并行构建模型的Gradient Boosting算法。
XGBoost官网:
http://xgboost.readthedocs.io;
XGBoost Github源码位置
https://github.com/dmlc/xgboost;
XGBoost支持开发语言:Python、R、Java、Scala、C++、GPU等。
XGBoost安装
• 安装方式一:
编译Github上的源码,参考http://xgboost.readthedocs.io/en/latest/build.html
• 安装方式二:
python的whl文件进行安装,要求python版本3.5或者3.6;
下载链接:
https://www.lfd.uci.edu/~gohlke/pythonlibs/#xgboost;
安装参考命令:pip install f:///xgboost-0.7-cp36-cp36m-win_amd64.whl
• 安装方式三:
直接pip命令安装:pip install xgboost
CART、GBDT
GBDT算法的底层一般采用CART树。
GBDT和CART都是决策树算法的变种,但是它们的实现方式和应用场景有所不同。
CART(Classification and Regression Tree)是一种二叉决策树,它可以用于分类和回归任务。它通过选择一个最优的特征,将数据集划分为两个子集,然后对每个子集递归地进行划分,直到满足某个停止条件为止。在分类任务中,CART使用基尼系数或信息增益作为特征选择的依据,而在回归任务中,它使用平方误差或平均绝对误差作为损失函数。
GBDT(Gradient Boosting Decision Tree)是一种集成学习算法,它通过组合多个决策树来提高模型的预测性能。在GBDT中,每个决策树都是在前面所有决策树的残差基础上进行训练的。GBDT的特征选择是通过梯度提升的方式进行的,它使用损失函数的负梯度来选择最优的特征。
因此,可以说GBDT是基于CART的算法,但是它们的实现方式和应用场景有所不同。
模型
- 目标函数
XGBoost
GBDT的目标函数:
o
b
j
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
(
t
)
)
obj=\sum_{i=1}^{n} l(y_i,\hat y_i^{(t)})
obj=∑i=1nl(yi,y^i(t))
XGBoost的目标函数:
o
b
j
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
(
t
)
)
+
∑
i
=
1
t
Ω
(
f
i
)
\scriptsize{ 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)
f
t
(
x
)
=
w
q
(
x
)
Ω
(
f
)
=
γ
T
+
1
2
λ
∑
j
=
1
T
w
j
2
\scriptsize{ f_t(x)=w_{q(x)} \quad\quad\quad \Omega(f)=\gamma T + \frac{1}{2}\lambda \sum_{j=1}^{T}w_j^2 }
ft(x)=wq(x)Ω(f)=γT+21λ∑j=1Twj2
我们希望CART树长得越矮越好,越矮的CART树叶子节点越少,则数据集进入CART后分到每个节点上的数据就会变多,那么异常值对结果产生的影响就会变小
为此引入了对叶子结点的惩罚项 Ω ( f ) \Omega(f) Ω(f);
T为叶子节点数,引入γ的目的是对叶子节点数进行惩罚;
引入 ∑ j = 1 T w j 2 \scriptsize{ \sum_{j=1}^{T} w_j^2 } ∑j=1Twj2的目的是对叶子分类结果进行惩罚,λ为惩罚系数;
XGBoost公式推导
- 第t次迭代后,模型的预测等于前t-1次的模型加上第t棵树的预测:
y ^ i ( t ) = y ^ i ( t − 1 ) + f t ( x i ) \scriptsize{ \hat y_i^{(t)}=\hat y_i^{(t-1)}+f_t(x_i) } y^i(t)=y^i(t−1)+ft(xi)
- 目标函数可以写成:
l
o
s
s
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
(
t
−
1
)
+
f
t
(
x
i
)
)
+
∑
i
=
1
t
−
1
Ω
(
f
i
)
+
Ω
(
f
t
)
\scriptsize{ loss=\sum_{i=1}^{n} l(y_i,\hat y_i^{(t-1)}+f_t(x_i))+\sum_{i=1}^{t-1}\Omega(f_i) +\Omega(f_t) }
loss=∑i=1nl(yi,y^i(t−1)+ft(xi))+∑i=1t−1Ω(fi)+Ω(ft)
前
t
−
1
次迭代的惩罚项
∑
i
=
1
t
−
1
Ω
(
f
i
)
,第
t
次迭代的惩罚项
Ω
(
f
t
)
\scriptsize{ 前t-1次迭代的惩罚项\sum_{i=1}^{t-1}\Omega(f_i), 第t次迭代的惩罚项\Omega(f_t) }
前t−1次迭代的惩罚项∑i=1t−1Ω(fi),第t次迭代的惩罚项Ω(ft)
- 将误差函数中的 y ^ i ( t − 1 ) + f t ( x i ) \hat y_i^{(t-1)}+f_t(x_i) y^i(t−1)+ft(xi)看成一个整体,求解这个整体取值在 y ^ i ( t − 1 ) \hat y_i^{(t-1)} y^i(t−1)处进行二阶泰勒展开:
l
o
s
s
≈
∑
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
)
]
+
∑
i
=
1
t
−
1
Ω
(
f
i
)
+
Ω
(
f
t
)
\scriptsize{ loss≈\sum_{i=1}^{n}[l(y_i,\hat y_i^{(t-1)}) +g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)]+\sum_{i=1}^{t-1}\Omega(f_i)+\Omega(f_t) }
loss≈∑i=1n[l(yi,y^i(t−1))+gift(xi)+21hift2(xi)]+∑i=1t−1Ω(fi)+Ω(ft)
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
)
)
g_i=\partial_{\hat y_i^{(t-1)}}l(y_i,\hat y_i^{(t-1)}) \quad\quad h_i=\partial_{\hat y_i^{(t-1)}}^2l(y_i,\hat y_i^{(t-1)})
gi=∂y^i(t−1)l(yi,y^i(t−1))hi=∂y^i(t−1)2l(yi,y^i(t−1))
- 最终的目标函数: l o s s = ∑ j = 1 T [ G j w j + 1 2 ( H j + λ ) w j 2 ] + γ T \scriptsize{ loss=\sum_{j=1}^{T}[G_jw_j+\frac{1}{2}(H_j+\lambda)w_j^2]+\gamma T } loss=∑j=1T[Gjwj+21(Hj+λ)wj2]+γT
- 如果树的结构确定(q函数确定),为了使目标函数最小,可以令导数为0,可以求最优的w,将w带入目标函数,可以得到最终的损失为:
w
j
∗
=
−
G
j
H
j
+
λ
l
o
s
s
∗
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
\scriptsize{ w_j^*=-\frac{G_j}{H_j+\lambda} \quad\quad\quad loss^*=-\frac{1}{2}\sum_{j=1}^{T}\frac{G_j^2}{H_j+\lambda}+\gamma T }
wj∗=−Hj+λGjloss∗=−21∑j=1THj+λGj2+γT
- loss函数的值越小,模型的效果越好(没有惩罚的情况下,太小会导致过拟合)
XGBoost的学习策略
- 当树的结构确定的时候,我们得到最优的叶子点分数以及对应的最小损失值,问题在于如何确定树的结构?
叶子点分数是指在决策树中叶子节点上的一个数值,用来表示该叶子节点所代表的类别或回归值的预测结果。在分类问题中,叶子点分数通常是一个类别标签,表示该叶子节点所属的类别。在回归问题中,叶子点分数通常是一个实数,表示该叶子节点的回归值
叶子点分数的确定是决策树构建和预测的重要组成部分,它直接影响决策树的性能和准确度
- 暴力穷举所有可能的结果,选择损失最小的(很难求解)
- 贪心法,每次尝试选择一个分裂点进行分裂,计算操作前后的增益,选择增益最大的方式进行分裂(信息增益Gain,有缺陷)
- 决策树相关算法计算指标:
- ID3算法:信息增益
- C4.5算法:Gain_ratio
- CART算法:Gini系数
- XGBoost目标函数: l o s s ∗ = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T \scriptsize{ loss^*=-\frac{1}{2}\sum_{j=1}^{T}\frac{G_j^2}{H_j+\lambda}+\gamma T } loss∗=−21∑j=1THj+λGj2+γT
- 从目标函数中,我们希望损失函数越小越好,即 G 2 H + λ \scriptsize{ \frac{G^2}{H+\lambda} } H+λG2越大越好;从而,对于一个叶子节点的分裂的分裂,分裂前后的信息增益定义为:
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 ) + λ ] − γ \scriptsize{ Gain=\frac{1}{2}[\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}]-\gamma } Gain=21[HL+λGL2+HR+λGR2−(HL+HR)+λ(GL+GR)2]−γ
- Gain值越大,分裂后减少的损失值越大。所以对于一个叶子节点分割时,计算所有候选的(feature,value)对应的gain,选择gain最大特征进行分割。
树节点分裂方法
在XGBoost中,贪心算法是精确的,而直方图算法是近似的。
- 贪心算法(精确算法):贪心算法通过计算每个可能的分裂点的增益(gain),并选择增益最大的分裂点(feature,value)进行分割。这种方法是精确的,因为它对每个可能的分裂点都进行了准确的计算。然而,由于需要计算每个分裂点的增益,贪心算法的计算复杂度较高,特别是在数据集较大时。
- 直方图算法(近似算法):直方图算法通过将特征值进行离散化,并构建特征的直方图来近似计算最佳分裂点。这种方法是近似的,因为它将特征值进行了离散化,并通过直方图来对特征进行统计。通过使用直方图,直方图算法可以有效地减少计算量,加快训练速度。然而,由于离散化和直方图的构建,直方图算法可能会丢失一些细节信息,导致近似计算的结果不如精确计算准确。
- 按位分裂算法(近似算法):对于每个特征,只考虑分位点,减少计算复杂度。将特征值转化为二进制表示,并将每个位作为一个新的特征。这样可以减少计算量,因为每个新特征只有两个取值(0和1),而不是原始特征的所有可能取值。通过计算每个新特征的分裂增益,可以选择最佳的分裂特征,从而构建决策树模型。
总的来说,贪心算法是精确的,但计算复杂度较高;直方图算法是近似的,但可以通过减少计算量来加快训练速度。在实践中,可以根据具体的需求和数据集大小选择适合的分裂方法。如果对于准确性要求较高,可以使用贪心算法;如果对于计算效率要求较高,可以使用直方图算法。
近似算法案例:三分位数
G
a
i
n
=
m
a
x
{
1
2
[
G
1
2
H
1
+
λ
+
G
23
2
H
23
+
λ
−
(
G
123
)
2
(
H
123
)
+
λ
]
−
γ
,
1
2
[
G
3
2
H
3
+
λ
+
G
12
2
H
12
+
λ
−
(
G
123
)
2
(
H
123
)
+
λ
]
−
γ
}
\scriptsize{ Gain=max\{{\frac{1}{2}[\frac{G_1^2}{H_1+\lambda}+\frac{G_{23}^2}{H_{23}+\lambda}-\frac{(G_{123})^2}{(H_{123})+\lambda}]-\gamma}, \quad {\frac{1}{2}[\frac{G_3^2}{H_3+\lambda}+\frac{G_{12}^2}{H_{12}+\lambda}-\frac{(G_{123})^2}{(H_{123})+\lambda}]-\gamma}\} }
Gain=max{21[H1+λG12+H23+λG232−(H123)+λ(G123)2]−γ,21[H3+λG32+H12+λG122−(H123)+λ(G123)2]−γ}
- XGBoost不是简单的按照样本个数进行分位的,而是按照上一轮的预测误差函数的二阶导数值作为权重来进行划分的:
XGBoost的其它特性
- 列采样(column subsampling):借鉴随机森林的做法,支持列抽样,不仅可以降低过拟合,还可以减少计算量;
- 支持对缺失值的自动处理。对于特征的值有缺失的样本,XGBoost可以自动学习分裂方向;
- XGBoost支持并行。XGBoost的并行是特征粒度上的,在计算特征的Gain的时候,会并行执行,但是在树的构建过程中,还是串行构建的;
- XGBoost算法中加入正则项,用于控制模型的复杂度,最终模型更加不容易过拟合;
- XGBoost基学习器支持CART、线性回归、逻辑回归;
- XGBoost支持自定义损失函数(要求损失函数二阶可导)。
XGBoost相关参数
参考链接:
https://xgboost.readthedocs.io/en/latest/python/python_api.html
https://xgboost.readthedocs.io/en/latest/parameter.html