目标函数
假设模型的损失函数是:
L
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
)
L= \sum_{i=1}^n l(y_i,\hat y_i)
L=∑i=1nl(yi,y^i),
假设模型的目标函数是:
O
b
j
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
)
+
∑
i
=
1
t
Ω
(
f
i
)
Obj= \sum_{i=1}^n l(y_i,\hat y_i) + \sum_{i=1}^t \Omega(f_i)
Obj=∑i=1nl(yi,y^i)+∑i=1tΩ(fi),这里的第二项是正则项,假设共计生成了
t
t
t棵树,
Ω
(
f
i
)
\Omega(f_i)
Ω(fi)为第
i
i
i棵树的复杂度,防止模型的过拟合。
由于XGBoost为前向相加模型,第
t
t
t步的目标函数可改写为:
O
b
j
(
t
)
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
(
t
−
1
)
+
f
t
(
x
i
)
)
+
∑
i
=
1
t
−
1
Ω
(
f
i
)
+
Ω
(
f
t
)
Obj^{(t)}= \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)
Obj(t)=∑i=1nl(yi,y^i(t−1)+ft(xi))+∑i=1t−1Ω(fi)+Ω(ft)
利用泰勒公式:
f
(
x
+
Δ
x
)
≈
f
(
x
)
+
f
′
(
x
)
Δ
x
+
1
2
f
′
′
(
x
)
Δ
x
2
f(x+\Delta x) \approx f(x) + f^{'}(x)\Delta x + \frac{1}{2}f^{''}(x)\Delta x^{2}
f(x+Δx)≈f(x)+f′(x)Δx+21f′′(x)Δx2(对
f
(
x
+
Δ
x
)
f(x+\Delta x)
f(x+Δx)在
x
x
x处进行二阶泰勒展开)。
同理将XGBoost在第
t
t
t步的损失函数在
y
i
(
t
−
1
)
y_i^{(t-1)}
yi(t−1)处展开写成:
KaTeX parse error: {split} can be used only in display mode.
此时目标函数可改写为:
O
b
j
(
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
)
]
+
∑
i
=
1
t
−
1
Ω
(
f
i
)
+
Ω
(
f
t
)
Obj^{(t)} \approx \sum_{i=1}^n [l(y_i,\hat y_i^{(t-1)})+ g_if_{t}(x_i) + \frac{1}{2} h_i f_{t}^2(x_i)] + \sum_{i=1}^{t-1} \Omega(f_i)+\Omega(f_t)
Obj(t)≈∑i=1n[l(yi,y^i(t−1))+gift(xi)+21hift2(xi)]+∑i=1t−1Ω(fi)+Ω(ft)
由于
l
(
y
i
,
y
^
i
(
t
−
1
)
)
l(y_i,\hat y_i^{(t-1)})
l(yi,y^i(t−1))和
∑
i
=
1
t
−
1
Ω
(
f
i
)
\sum_{i=1}^{t-1} \Omega(f_i)
∑i=1t−1Ω(fi)在第
t
−
1
t-1
t−1轮迭代中已计算完毕,为常数,由此可以去除并简化目标函数:
O
b
j
(
t
)
≈
∑
i
=
1
n
[
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
Obj^{(t)} \approx \sum_{i=1}^n [g_if_{t}(x_i) + \frac{1}{2} h_i f_{t}^2(x_i)] + \Omega(f_t)
Obj(t)≈∑i=1n[gift(xi)+21hift2(xi)]+Ω(ft)
单独看目标函数中的正则项:
Ω
(
f
t
)
\Omega(f_t)
Ω(ft),此项定义了决策树的复杂程度,由两部分决定:叶子节点的数量(叶子节点越少模型越简单)和叶子节点的权重向量L2范数(各个叶子节点的权值应较为一致,不应出现某几个非常大):
Ω
(
f
t
)
=
γ
T
+
1
2
λ
∑
j
=
1
T
w
j
2
\Omega(f_t)=\gamma T+\frac{1}{2}\lambda\sum_{j=1}^{T}w_{j}^{2}
Ω(ft)=γT+21λ∑j=1Twj2
将目标函数拆分到每个叶子节点(共计
T
T
T个)上,得到最终第
t
t
t轮的目标函数为:
KaTeX parse error: {split} can be used only in display mode.
定义
G
j
=
∑
i
∈
I
j
g
i
G_j= \sum_{i\in I_j}g_i
Gj=∑i∈Ijgi,
H
j
=
∑
i
∈
I
j
h
i
H_j=\sum_{i\in I_j}h_i
Hj=∑i∈Ijhi,则
O
b
j
(
t
)
=
∑
j
=
1
T
[
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
]
+
γ
T
Obj^{(t)} = \sum_{j=1}^{T}[G_jw_j+\frac{1}{2}(H_j+\lambda)w_{j}^2]+\gamma T
Obj(t)=∑j=1T[Gjwj+21(Hj+λ)wj2]+γT
对于每一个节点中的
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来说若要使其取得极小值点,对此式求一阶导数即可求得叶子节点对应的权重:
w
j
∗
=
−
G
j
H
j
+
λ
w_j^*=-\frac{G_j}{H_j+\lambda}
wj∗=−Hj+λGj
于是最终的目标函数可化简为:
O
b
j
(
t
)
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
Obj^{(t)}=-\frac{1}{2}\sum_{j=1}^T \frac{G_j^2}{H_j+\lambda}+\gamma T
Obj(t)=−21∑j=1THj+λGj2+γT,越小则模型结构越好.
分裂方式
XGBoost的分裂过程所选取的增益标准不是基尼系数或者信息增益率等,而是上节所提到的决策树目标函数评分,节点分裂过程可见下图:
节点分裂收益是树A的评分减去树B的评分,比较分裂前的
S
S
S节点与分裂后的
L
L
L、
R
R
R节点,则分裂收益的表达式可以理解:
当节点
S
S
S不分裂时,可以给目标函数带来的是评分为:
G
S
2
H
S
+
λ
+
γ
\frac{G_S^2}{H_S+\lambda}+\gamma
HS+λGS2+γ,
而如果它分裂为两个叶子节点
L
L
L、
R
R
R,那么它们给目标函数带来的评分(此时原本的叶子节点
S
S
S由于分裂,不再作为叶子节点)为:
G
L
2
H
L
+
λ
+
G
R
2
H
R
+
λ
+
2
γ
\frac{G_L^2}{H_L+\lambda}+ \frac{G_R^2}{H_R+\lambda}+2\gamma
HL+λGL2+HR+λGR2+2γ
则它们的差可以作为分裂的收益:
KaTeX parse error: {split} can be used only in display mode.
精确贪心算法(Exact Greedy Algorithm)
贪心准则分裂的思路与CART回归树一样,遍历特征值计算分裂收益,排序后选取最优特征,但是如果碰到连续值,按照决策树的方法遍历特征的每个值计算量会较大,因此作者提出了其他分裂算法。
近似算法(Approximate Algorithm)
第一种精确贪心分裂策略的计算复杂度较高,为减小计算量,作者在论文中提出了一种近似算法,即按照特征值的分布进行数据的分桶离散化,这样大大减小了划分的遍历次数。
这种方法包括两种不同的策略:
- Global,全局近似,在树建立的初始阶段就对特征进行分桶离散化,只进行一次分桶操作,得到候选切分点,并在接下来的所有分裂过程中均使用这些离散点进行分裂决策。
- Local,局部近似,在每次需要对节点进行分裂前,对该节点上的候选样本进行分位数离散分桶化,得到该节点上的候选切分点,每次分裂都需要进行分桶计算。
加权分位数缩略图算法(Weighted Quantile Sketch)
简单地按照分位数计算候选切分点的方式可能比较粗糙不合理,作者提出了加权分位数缩略图的近似分裂算法。
假设数据集
D
k
=
{
(
x
1
k
,
h
1
)
,
(
x
2
k
,
h
2
)
,
.
.
.
,
(
x
n
k
,
h
n
)
}
D_k=\{(x_{1k},h_1),(x_{2k},h_2),...,(x_{nk},h_n)\}
Dk={(x1k,h1),(x2k,h2),...,(xnk,hn)}样本中每个样本第
k
k
k个特征值
x
n
k
x_{nk}
xnk和对应的二阶导数
h
n
h_{n}
hn集合。
定义排名函数为:
r
k
(
z
)
=
1
∑
(
x
,
h
)
∈
D
k
h
∑
(
x
,
h
)
∈
D
k
,
x
<
z
h
r_{k}(z)=\frac{1}{\sum_{(x,h)\in D_k}h} \sum_{(x,h)\in D_k, x<z} h
rk(z)=∑(x,h)∈Dkh1∑(x,h)∈Dk,x<zh
这里表示第
k
k
k个特征值小于
z
z
z的样本集合中,其二阶导数的占比。
于是可将样本特征离散化为
{
s
k
,
1
,
s
k
,
2
,
.
.
.
,
s
k
,
l
}
\{s_{k,1},s_{k,2},...,s_{k,l}\}
{sk,1,sk,2,...,sk,l}个候选切分点,其中
s
k
i
s_{ki}
ski则代表第
i
i
i个箱子上的右临界值,且候选切分点需满足条件:
∣
r
k
(
s
k
,
j
)
−
r
k
(
s
k
,
j
+
1
)
∣
>
ε
|r_k(s_{k,j})-r_k(s_{k,j+1})| > \varepsilon
∣rk(sk,j)−rk(sk,j+1)∣>ε
其中
ε
\varepsilon
ε决定着切分点之间的宽度,大致数据集的划分个数有
1
ε
\frac{1}{\varepsilon}
ε1个,且
s
k
,
1
=
m
i
n
(
x
i
k
)
s_{k,1}=min(x_{ik})
sk,1=min(xik)、
s
k
,
l
=
m
a
x
(
x
i
k
)
s_{k,l}=max(x_{ik})
sk,l=max(xik)
在划分过程中为什么要切分二阶导数的占比,可以重写之前推导的第
t
t
t轮的目标函数:
KaTeX parse error: {split} can be used only in display mode.
而
1
2
∑
i
=
1
n
(
g
i
h
i
)
2
\frac{1}{2}\sum_{i=1}^n(\frac{g_i}{h_i})^2
21∑i=1n(higi)2中的
g
i
g_i
gi、
h
i
h_i
hi均为前一轮计算的已知常数,因此上式可改写为:
O
b
j
(
t
)
=
∑
i
=
1
n
1
2
h
i
[
f
t
(
x
i
)
−
(
−
g
i
h
i
)
]
2
+
Ω
(
f
t
)
+
c
o
n
s
t
a
n
t
Obj^{(t)}=\sum_{i=1}^{n}\frac{1}{2}h_i[f_{t}(x_i)-(-\frac{g_i}{h_i})]^2 + \Omega(f_t)+constant
Obj(t)=∑i=1n21hi[ft(xi)−(−higi)]2+Ω(ft)+constant
此时的
h
i
h_i
hi可以看成是每个样本与其标签标签
(
−
g
i
h
i
)
(-\frac{g_i}{h_i})
(−higi)间的损失计算权重,如果样本的
h
i
h_i
hi越小,则其对损失函数的影响越小,这样利用
h
i
h_i
hi进行分位数的划分,能将对损失函数影响较为接近的样本划分在同一个箱子中,因此在可以由二阶梯度作为候选切分点的选择依据。
稀疏感知(Sparsity Aware Split Finding)
在训练阶段,首先对于非缺失的数据进行候选节点的切分,对于特征缺失的样本而言,首先尝试将所有缺失该特征的样本划分到左子树计算增益,再尝试划分到右子树计算增益,取其中最大收益的方向作为分裂方向。在预测阶段,如果预测样本缺失某个特征,则按之前学习的方向分裂,如果预测样本在训练阶段没有缺失,也就没有学习过的分裂方向,则默认将其分到右子树。
面试问题
1. XGBoost为什么使用二阶泰勒展开?
● 精准性:相对于GBDT的一阶展开,采用二阶展开能够更为精准地逼近真实的损失函数
● 可扩展性:只需损失函数二阶可导,即可自定义。
2. XGBoost如何防止过拟合?
● 目标函数添加正则项:具体形式为叶子节点数量+节点权重的L2范数。
● 列抽样:训练时只考虑部分特征。
● 子采样:每轮计算可以使用部分样本,使算法更保守。
● Shrinkage:通过学习率/步长逐步缩小偏差。