1. XGBoost介绍
XGBoost模型即是一些“串联”树结构的组合,最终预测结果由多棵树共同决定。
模型公式:y=f(z)=∑Kk=1fk(z)y=f(z)=∑k=1Kfk(z)
模型预测:y^i=∑Kk=1f^k(xi)y^i=∑k=1Kf^k(xi)
类似模型预测,第tt步的估计可以表示为 。如何有效的估计每棵树,且如何重组多棵树使得XGBoost成为如今竞赛的常胜将军?我们需要解决以下三个问题:
问题0:树的组合方式
问题1:每棵树的结构-分枝
问题2:每个枝节点的预测值
下面分别按步骤依次解决上面三个问题:
解决方案0:树的组合方式是“串联”,即每一个树是建立在前面所有树预测残差的基础上优化得到。所以后续树的结构和枝节点的预测值也将按照“并联”方式逐个估计。
解决方案2:常规的解决方案是先解决树的结构,再确定每个节点的估计值,但XGBoost的推导过程是先假设树的结构的基础上先估计每个节点预测值,进而完善树的结构。任何优化问题之前,损失函数的确定是重中之重。XGBoost采用的是惩罚式损失Obj=L+ΩObj=L+Ω,其中LL为损失函数,为惩罚项。且惩罚函数为:Ω=γT+λ∑Tj=1ω2jΩ=γT+λ∑j=1Tωj2,其中TT是枝节点的个数,是jj枝上的得分。假设已得到棵树,我们来估计第tt棵树的结构和节点估计。首先将数据和估计带入损失函数得:
将以上损失函数部分进行二次Taylor展开得:Obj(t)∼∑i=1n(ℓ(yi,y^(t−1)i)+gifi+12hif2i)+γT+λ∑j=1Tω2j∼∑i=1n(gifi+12hif2i)+γT+λ∑j=1Tω2j∼∑j=1T∑i∈Ij(gifi+12hif2i)+γT+λ∑j=1Tω2j=∑j=1T((∑i∈Ijgi)ωj+12(∑i∈Ijhi)ω2j)+γT+λ∑j=1Tω2j=∑j=1T((∑i∈Ijgi)ωj+12(∑i∈Ijhi+λ)ω2j)+γT=∑j=1T12(∑i∈Ijhi+λ)(ω2j+2∑i∈Ijgi∑i∈Ijhi+λωj)+γT=∑j=1T12(∑i∈Ijhi+λ)(ωj+∑i∈Ijgi∑i∈Ijhi+λ)2−12∑j=1T(∑i∈Ijgi)2∑i∈Ijhi+λ+γT=0(788)(789)Obj(t)∼∑i=1n(ℓ(yi,y^i(t−1))+gifi+12hifi2)+γT+λ∑j=1Tωj2∼∑i=1n(gifi+12hifi2)+γT+λ∑j=1Tωj2∼∑j=1T∑i∈Ij(gifi+12hifi2)+γT+λ∑j=1Tωj2=∑j=1T((∑i∈Ijgi)ωj+12(∑i∈Ijhi)ωj2)+γT+λ∑j=1Tωj2(788)=∑j=1T((∑i∈Ijgi)ωj+12(∑i∈Ijhi+λ)ωj2)+γT=∑j=1T12(∑i∈Ijhi+λ)(ωj2+2∑i∈Ijgi∑i∈Ijhi+λωj)+γT(789)=∑j=1T12(∑i∈Ijhi+λ)(ωj+∑i∈Ijgi∑i∈Ijhi+λ)2−12∑j=1T(∑i∈Ijgi)2∑i∈Ijhi+λ+γT=0
其中gi=∂y(t−1)ℓ(yi,y^(t−1)i)gi=∂y(t−1)ℓ(yi,y^i(t−1))和hi=∂2y(t−1)ℓ(yi,y^(t−1)i)hi=∂y(t−1)2ℓ(yi,y^i(t−1)),且IjIj为jj个节点包含的数据指标集。将上面(84)式对求导得dObj(t)dωj=∑i∈Ijgi+(∑i∈Ijhi+λ)ωj=0dObj(t)dωj=∑i∈Ijgi+(∑i∈Ijhi+λ)ωj=0或从上式(85)的二次函数重组可以得到
ω∗j=−∑i∈Ijgi∑i∈Ijhi+λωj∗=−∑i∈Ijgi∑i∈Ijhi+λ且此时的目标函数可表达为:Obj(t)=−12∑j=1T(∑i∈Ijgi)2∑i∈Ijhi+λ+γT=−12∑j=1T((∑i∈Ijgi)2∑i∈Ijhi+λ+γ)=−12∑j=1T(GH+λ−2γ)Obj(t)=−12∑j=1T(∑i∈Ijgi)2∑i∈Ijhi+λ+γT=−12∑j=1T((∑i∈Ijgi)2∑i∈Ijhi+λ+γ)=−12∑j=1T(GH+λ−2γ)- 解决方案1:如何得到树的结构呢?关键是确定每棵树的节点变量和如何划分节点。首先方案是:a. 对于每个节点,遍历全部变量 b. 对于每个变量,将所有的观测进行排序并进行扫描式,得到最好的切分点。如何判定切分点的好坏呢?根据以上增加该切分点,目标函数得变化量:Δ=Obj(t)−(Obg(t)L+Obj(t)R)=12(GLHL+λ+GRHR+λ−GH+λ)−γΔ=Obj(t)−(ObgL(t)+ObjR(t))=12(GLHL+λ+GRHR+λ−GH+λ)−γ达到最大。
2. R简单实现
# Load packages
library(xgboost)
# Read data from xgboost package
data('agaricus.train', package = 'xgboost')
data('agaricus.test', package = 'xgboost')
tr <- agaricus.train
te <- agaricus.test
# Investigate data set
str(tr$data) ## dgCMatrix: Sparse matrix class from package Matrix
# Train xgboost model
## Input features: dense or sparse matrix both are ok
## Target variable: numeric vector(0-n for classification and real values for regression)
## Objective: 'reg:linear' for regression or 'binary:logistic'
## Number of iteration: number of trees added to the model
cv.res <- xgb.cv(data = tr$data, nfold = 5, label = tr$label,
nround = 10, objective = 'binary:logistic') # Cross Validation
cv.res <- xgb.cv(data = tr$data, nfold = 5, label = tr$label,
nround = 10, objective = 'binary:logistic',
eval_metric = 'auc') # Cross Validation
bst <- xgboost(data = tr$data, label = tr$label,
nround = 2, objective = 'binary:logistic',
eval_metric = 'auc')
pred <- predict(bst, te$data)
table(pred, te$label)