XGBoost算法原理详解与参数详解
R语言XGBoost参数详解
XGBoost部分细节补充
- 1. XGBoost线性模型的实现
- 2.XGBoost对二分类和多分类的处理方法
1. XGBoost线性模型的实现
前面文章中已经详细的介绍了
XGBoost
基于决策树的实现,今天我们主要介绍XGBoost
基于线性模型的实现。
我们主要介绍简单的三种线性模型:Lasso、Ridge、弹性网
。
Lasso
:采用了L1
正则化的惩罚,目标函数为 J ( ω ) = ∑ i = 1 m ( y i − ω T X i ) 2 + λ ∑ j = 1 n ω j 2 \mathcal{J}(\omega)=\sum_{i=1}^{m}(y_{i}-\omega^{T}X_{i})^{2}+\lambda\sum_{j=1}^{n}\omega_{j}^{2} J(ω)=∑i=1m(yi−ωTXi)2+λ∑j=1nωj2.
Ridge
:采用了L2
正则化的惩罚,目标函数为 J ( ω ) = ∑ i = 1 m ( y i − ω T X i ) 2 + λ ∑ j = 1 n ∣ ω j ∣ \mathcal{J}(\omega)=\sum_{i=1}^{m}(y_{i}-\omega^{T}X_{i})^{2}+\lambda\sum_{j=1}^{n}\left|\omega_{j}\right| J(ω)=∑i=1m(yi−ωTXi)2+λ∑j=1n∣ωj∣.
弹性网
:结合了L1
与L2
正则项的惩罚,目标函数为 J ( ω ) = ∑ i = 1 m ( y i − ω T X i ) 2 + λ 1 ∑ j = 1 n ω j 2 + λ 2 ∑ j = 1 n ∣ ω j ∣ \mathcal{J}(\omega)=\sum_{i=1}^{m}(y_{i}-\omega^{T}X_{i})^{2}+\lambda_{1}\sum_{j=1}^{n}\omega_{j}^{2}+\lambda_{2}\sum_{j=1}^{n}\left|\omega_{j}\right| J(ω)=∑i=1m(yi−ωTXi)2+λ1∑j=1nωj2+λ2∑j=1n∣ωj∣.
线性模型通过学习特征的线性组合进行预测,即:
y
=
ω
T
X
+
β
,
ω
T
=
(
ω
1
,
ω
2
,
ω
3
,
.
.
.
,
ω
m
)
y=\omega^{T}X+\beta,\omega^{T}=(\omega_{1},\omega_{2},\omega_{3},...,\omega_{m})
y=ωTX+β,ωT=(ω1,ω2,ω3,...,ωm)
m
m
m为特征的数量,模型的训练即为确定参数
ω
\omega
ω与
β
\beta
β.
XGBoost线性模型的目标函数定义为:
O
b
j
(
s
)
=
1
n
∑
i
=
1
n
L
(
y
i
,
y
^
i
(
s
)
)
+
Ω
(
ω
,
β
)
Obj^{(s)}=\frac{1}{n}\sum_{i=1}^{n}L(y_{i},\hat{y}_{i}^{(s)})+\Omega(\omega,\beta)
Obj(s)=n1i=1∑nL(yi,y^i(s))+Ω(ω,β).
其中
y
^
i
(
s
)
\hat{y}_{i}^{(s)}
y^i(s)为第
i
i
i个样本在模型
s
s
s轮时得到的预测值;
y
i
y_{i}
yi为第
i
i
i个样本的真实值;
L
L
L为损失函数;
Ω
\Omega
Ω为正则化项。
这里的正则化项
Ω
\Omega
Ω采用了弹性网
的惩罚方式:
Ω
(
ω
,
β
)
=
1
2
λ
∑
j
=
1
m
ω
j
2
+
1
2
λ
β
β
2
+
α
∑
j
=
1
m
∣
ω
j
∣
\Omega(\omega,\beta)=\frac{1}{2}\lambda\sum_{j=1}^{m}\omega_{j}^{2}+\frac{1}{2}\lambda_{\beta}\beta^{2}+\alpha\sum_{j=1}^{m}\left|\omega_{j}\right|
Ω(ω,β)=21λj=1∑mωj2+21λββ2+αj=1∑m∣ωj∣.
由于向量乘积满足分配律
,所以对于线性模型的参数进行如下的改写:
ω
s
T
X
+
β
s
=
(
ω
s
−
1
T
+
Δ
ω
T
)
X
+
β
s
−
1
+
Δ
β
\omega_{s}^{T}X+\beta_{s}=(\omega_{s-1}^{T}+\Delta\omega^{T})X+\beta_{s-1}+\Delta\beta
ωsTX+βs=(ωs−1T+ΔωT)X+βs−1+Δβ
其中
ω
s
T
\omega_{s}^{T}
ωsT为第
s
s
s轮训练时的参数;
ω
s
−
1
T
\omega_{s-1}^{T}
ωs−1T为
s
−
1
s-1
s−1轮的参数;
Δ
ω
\Delta\omega
Δω为先后两轮训练中
ω
\omega
ω的变化;
β
s
\beta_{s}
βs与
β
s
−
1
\beta_{s-1}
βs−1为前后两轮训练中的截距项;
Δ
β
\Delta\beta
Δβ为两轮训练下截距项的变化。所以目标函数可写为:
O
b
j
(
s
)
=
1
n
∑
i
=
1
n
L
(
y
i
,
y
^
i
(
s
−
1
)
+
Δ
ω
T
x
i
+
Δ
β
)
+
Ω
(
ω
,
β
)
Obj^{(s)}=\frac{1}{n}\sum_{i=1}^{n}L(y_{i},\hat{y}_{i}^{(s-1)}+\Delta\omega^{T}x_{i}+\Delta\beta)+\Omega(\omega,\beta)
Obj(s)=n1i=1∑nL(yi,y^i(s−1)+ΔωTxi+Δβ)+Ω(ω,β).
O
b
j
(
s
)
=
1
n
∑
i
=
1
n
L
(
y
i
,
y
^
i
(
s
−
1
)
+
Δ
ω
T
x
i
+
Δ
β
)
+
Ω
(
ω
,
β
)
≈
1
n
∑
j
=
1
m
∑
i
=
1
n
[
L
(
y
i
,
y
^
(
s
−
1
)
+
Δ
β
)
+
g
i
(
Δ
ω
j
x
i
j
)
+
1
2
h
i
(
Δ
ω
j
x
i
j
)
2
]
+
1
2
λ
∑
j
=
1
m
(
ω
(
s
−
1
)
j
+
Δ
ω
j
)
2
+
1
2
λ
β
β
2
+
α
∑
j
=
1
m
∣
ω
(
s
−
1
)
j
+
Δ
ω
j
∣
\begin{align} Obj^{(s)}&=\frac{1}{n}\sum_{i=1}^{n}L(y_{i},\hat{y}_{i}^{(s-1)}+\Delta\omega^{T}x_{i}+\Delta\beta)+\Omega(\omega,\beta) \\ & \approx \frac{1}{n} \sum_{j=1}^{m}\sum_{i=1}^{n}[L(y_{i},\hat{y}^{(s-1)}+\Delta\beta)+g_{i}(\Delta\omega_{j}x_{ij})+\frac{1}{2}h_{i}(\Delta\omega_{j}x_{ij})^{2}] + \frac{1}{2} \lambda \sum_{j=1}^{m}(\omega_{(s-1)j}+\Delta \omega_{j})^{2} + \frac{1}{2} \lambda_{\beta} \beta^{2} + \alpha \sum_{j=1}^{m}\left| \omega_{(s-1)j} + \Delta\omega_{j} \right| \end{align}
Obj(s)=n1i=1∑nL(yi,y^i(s−1)+ΔωTxi+Δβ)+Ω(ω,β)≈n1j=1∑mi=1∑n[L(yi,y^(s−1)+Δβ)+gi(Δωjxij)+21hi(Δωjxij)2]+21λj=1∑m(ω(s−1)j+Δωj)2+21λββ2+αj=1∑m
ω(s−1)j+Δωj
上式和XGBoost
对CART
的优化方式相同:二阶泰勒展开。
此时上述的目标函数相当于一个以
Δ
ω
j
\Delta\omega_{j}
Δωj为自变量的一元二次函数,判读
ω
(
s
−
1
)
j
+
Δ
ω
j
\omega_{(s-1)j}+\Delta\omega_{j}
ω(s−1)j+Δωj与
0
0
0的大小关系,再根据一元二次函数最值公式求出
Δ
ω
j
\Delta\omega_{j}
Δωj的最优值。
若
ω
(
s
−
1
)
j
+
Δ
ω
j
≥
0
\omega_{(s-1)j}+\Delta\omega_{j}\geq0
ω(s−1)j+Δωj≥0,
Δ
ω
j
=
max
(
−
∑
i
=
1
n
g
i
x
i
j
+
λ
ω
(
s
−
1
)
j
+
α
∑
i
=
1
n
h
i
x
i
j
2
+
λ
,
−
ω
(
s
−
1
)
j
)
\Delta\omega_{j}=\max(-\frac{\sum_{i=1}^{n}g_{i}x_{ij}+\lambda\omega_{(s-1)j}+\alpha}{\sum_{i=1}^{n}h_{i}x_{ij}^{2}+\lambda},-\omega_{(s-1)j})
Δωj=max(−∑i=1nhixij2+λ∑i=1ngixij+λω(s−1)j+α,−ω(s−1)j).
若
ω
(
s
−
1
)
j
+
Δ
ω
j
<
0
\omega_{(s-1)j}+\Delta\omega_{j}<0
ω(s−1)j+Δωj<0,
Δ
ω
j
=
min
(
−
∑
i
=
1
n
g
i
x
i
j
+
λ
ω
(
s
−
1
)
j
−
α
∑
i
=
1
n
h
i
x
i
j
2
+
λ
,
−
ω
(
s
−
1
)
j
)
\Delta\omega_{j}=\min(-\frac{\sum_{i=1}^{n}g_{i}x_{ij}+\lambda\omega_{(s-1)j}-\alpha}{\sum_{i=1}^{n}h_{i}x_{ij}^{2}+\lambda},-\omega_{(s-1)j})
Δωj=min(−∑i=1nhixij2+λ∑i=1ngixij+λω(s−1)j−α,−ω(s−1)j).
对于截距项
β
\beta
β采用上述方法求解得到:
Δ
β
=
−
∑
i
=
1
n
g
i
+
λ
β
β
(
s
−
1
)
∑
i
=
1
n
h
i
+
λ
β
\Delta\beta=-\frac{\sum_{i=1}^{n}g_{i}+\lambda_{\beta}\beta_{(s-1)}}{\sum_{i=1}^{n}h_{i}+\lambda_{\beta}}
Δβ=−∑i=1nhi+λβ∑i=1ngi+λββ(s−1).
以上就是XGBoost
线性模型实现的步骤以及参数的优化求解。
2.XGBoost对二分类和多分类的处理方法
问题:
我想关于
XGBoost
算法的原理以及理论证明大家在论文、书籍以及相关的博客上应该都可以看懂,可能对XGBoost
如何解决分类等问题不是很清楚,比如二分类问题下XGBoost
的输出概率值是如何做到的?这个问题如果理解了大家对XGBoost
解决问题的逻辑就会十分明了。
以R语言
自带的数据集agaricus
为例进行二分类.
> library(xgboost)
> data(agaricus.train, package='xgboost')
>
> bst <- xgboost(data = agaricus.train$data, label = agaricus.train$label, max_depth = 3,
+ eta = 1, nthread = 2, nrounds = 2,objective = "binary:logistic")
[1] train-logloss:0.161178
[2] train-logloss:0.064728
>
>
> xgb.plot.tree(model = bst) # 可视化xgboost生成的树模型
以上图片对于agaricus
数据集生成了两颗树模型,XGboost
在预测测试集的输出概率时会把测试集的样本按照树模型的划分规则分别使其落入Tree0
与Tree1
的叶节点上. 比如测试集中的样本1
在Tree0
与Tree1
的叶节点上的value
进行相加,然后通过Sigmoid
激活函数转换为测试集中正类标签的预测概率.
以下为上述的验证部分:通过对Tree0
与Tree1
的叶子节点的值进行排列后求和,然后通过Sigmoid
激活函数转为概率输出值;另一部分对测试集进行了概率预测. 自然而然地对测试集进行了概率预测
应该是上述过程的子集
.
> print(xgb.dump(bst, with_stats = TRUE))
[1] "booster[0]"
[2] "0:[f28<-9.53674316e-07] yes=1,no=2,missing=1,gain=4000.53101,cover=1628.25"
[3] "1:[f55<-9.53674316e-07] yes=3,no=4,missing=3,gain=1158.21204,cover=924.5"
[4] "3:[f59<-9.53674316e-07] yes=7,no=8,missing=7,gain=568.215576,cover=812"
[5] "7:leaf=1.90174532,cover=772.5"
[6] "8:leaf=-1.95061731,cover=39.5"
[7] "4:[f20<-9.53674316e-07] yes=9,no=10,missing=9,gain=114.297333,cover=112.5"
[8] "9:leaf=1.77777779,cover=8"
[9] "10:leaf=-1.98104262,cover=104.5"
[10] "2:[f108<-9.53674316e-07] yes=5,no=6,missing=5,gain=198.173828,cover=703.75"
[11] "5:[f66<-9.53674316e-07] yes=11,no=12,missing=11,gain=86.3969727,cover=690.5"
[12] "11:leaf=-1.98531032,cover=679.75"
[13] "12:leaf=0.808510661,cover=10.75"
[14] "6:leaf=1.85964918,cover=13.25"
[15] "booster[1]"
[16] "0:[f28<-9.53674316e-07] yes=1,no=2,missing=1,gain=480.158417,cover=719.00769"
[17] "1:[f20<-9.53674316e-07] yes=3,no=4,missing=3,gain=276.744751,cover=414.977539"
[18] "3:leaf=1.14570117,cover=296.038025"
[19] "4:[f35<-9.53674316e-07] yes=7,no=8,missing=7,gain=392.998077,cover=118.939491"
[20] "7:leaf=-6.8755784,cover=8.36453247"
[21] "8:leaf=-0.127376497,cover=110.574959"
[22] "2:[f108<-9.53674316e-07] yes=5,no=6,missing=5,gain=28.7784424,cover=304.030151"
[23] "5:[f38<-9.53674316e-07] yes=9,no=10,missing=9,gain=26.1188354,cover=297.850983"
[24] "9:leaf=-0.0386054367,cover=22.8540649"
[25] "10:leaf=-1.15275192,cover=274.996918"
[26] "6:leaf=0.994743764,cover=6.17916679"
> tree0 = c(1.90174532, -1.95061731, 1.77777779, -1.98104262, -1.98531032, 0.808510661,
+ 1.85964918)
>
> tree1 = c(1.14570117, -6.8755784, -0.127376497, -0.0386054367, -1.15275192, 0.994743764)
>
>
> df = expand.grid(tree0,tree1)
>
>
> f = function(x) 1 / (1 + exp(-sum(x)))
>
> pred1 = round(apply(df, 1, f),4)
>
> data(agaricus.test, package='xgboost')
> pred2 = round(predict(bst, agaricus.test$data),4)
> length(unique(pred2))
[1] 11
>
> all(unique(pred2) %in% unique(pred1)) # 成立
[1] TRUE
以上就是XGBoost
个人想到的一些细节补充,本片内容到此为止.