XGBoost算法梳理
- 算法原理
XGBT中的预测值是所有弱分类器上的叶子权重直接求和得到
y i ^ = ∑ j w j x i j \widehat{y_{i}}=\sum _{j}w_{j}x_{ij} yi =∑jwjxij
损失函数: l ( y i , y i ^ ) = ( y i − y i ^ ) 2 l(y_{i},\widehat{y_{i}})=(y_{i}-\widehat{y_{i}})^{2} l(yi,yi )=(yi−yi )2
XGB的核心是每次迭代都是基于上一次的残差去拟合,大致过程如下
y i ^ ( 0 ) = 0 \widehat{y_{i}}^{(0)}=0 yi (0)=0
y i ^ ( 1 ) = f 1 ( x i ) = y i ^ 0 + f 1 ( x i ) \widehat{y_{i}}^{(1)}=f_{1}(x_{i})=\widehat{y_{i}}^{0}+f_{1}(x_{i}) yi (1)=f1(xi)=yi 0+f1(xi)
y i ^ ( 2 ) = f 1 ( x i ) + f 2 ( x i ) = y i ^ 1 + f 2 ( x i ) \widehat{y_{i}}^{(2)}=f_{1}(x_{i})+f_{2}(x_{i})=\widehat{y_{i}}^{1}+f_{2}(x_{i}) yi (2)=f1(xi)+f2(xi)=yi 1+f2(xi)
…
y i ^ ( t ) = ∑ k = 1 t f k ( x i ) = y i ^ ( t − 1 ) + f t ( x i ) \widehat{y_{i}}^{(t)}=\sum_{k=1}^{t}f_{k}(x_{i})=\widehat{y_{i}}^{(t-1)}+f_{t}(x_{i}) yi (t)=∑k=1tfk(xi)=yi (t−1)+ft(xi)
这里 y i ^ ( t ) \widehat{y_{i}}^{(t)} yi (t)表示是第t轮的模型预测, f t ( x i ) f_{t}(x_{i}) ft(xi)表示加入一个新的函数
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,...,T} ft(x)=wq(x),w∈RT,q:Rd→1,2,...,T
接下来就是f的求解了,每一轮中,我们选取一个f来使得我们的目标函数尽量最大地降低
O b j ( t ) = ∑ i = 1 n l ( y i , y i ^ ( t ) + ∑ i = 1 t Ω ( f 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 Obj^{(t)}=\sum_{i=1}^{n}l(y^{i},\widehat{y_{i}}^{(t)}+\sum_{i=1}^{t}\Omega(f_{t})=\sum_{i=1}^{n}l(y_{i},\widehat{y_{i}}^{(t-1)}+f_{t}(x_{i}))+\Omega(f_{t})+constant Obj(t)=∑i=1nl(yi,yi (t)+∑i=1tΩ(ft)=∑i=1nl(yi,yi (t−1)+ft(xi))+Ω(ft)+constant
O b j ( t ) = ∑ i = 1 n ( y i − ( y i ^ ( t − 1 ) + f t ( x i ) ) ) 2 + Ω ( f t ) + c o n s t a n t Obj^{(t)}=\sum_{i=1}^{n}(y_{i}-(\widehat{yi}^{(t-1)}+f_t(x_{i})))^{2}+\Omega(f_{t})+constant Obj(t)=∑i=1n(yi−(yi (t−1)+ft(xi)))2+Ω(ft)+constant
∑ i = 1 n [ 2 ( y i ^ ( t − 1 ) − y i ) + f t ( x i ) 2 ] + Ω ( f t ) + c o n s t a n t \sum_{i=1}^{n}[2(\widehat{yi}^{(t-1)}-y_{i})+f_t(x_{i})^{2}]+\Omega(f_{t})+constant ∑i=1n[2(yi (t−1)−yi)+ft(xi)2]+Ω(ft)+constant
- [注 ] 一般我们把
y
i
^
(
t
−
1
)
−
y
i
\widehat{yi}^{(t-1)}-y_{i}
yi
(t−1)−yi叫做残差,这里的
Ω
(
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表示叶子结点的个数,w表示叶子节点的分数。 γ \gamma γ可以控制叶子结点的个数, λ \lambda λ可以控制叶子节点的分数不会过大,防止过拟合。
下一步,用泰勒展开来近似我们原来的目标函数:
∑
i
=
1
n
l
(
y
i
,
y
i
^
(
t
−
1
)
+
f
t
(
x
i
)
)
+
Ω
(
f
t
)
+
c
o
n
s
t
a
n
t
\sum_{i=1}^{n}l(y_{i},\widehat{y_{i}}^{(t-1)}+f_{t}(x_{i}))+\Omega(f_{t})+constant
∑i=1nl(yi,yi
(t−1)+ft(xi))+Ω(ft)+constant
泰勒二阶展开:
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
定义:
g
i
=
∂
l
(
y
i
,
y
^
(
t
−
1
)
)
∂
y
^
(
t
−
1
)
g_{i}=\frac{\partial l(yi,\widehat{y}^{(t-1)})}{\partial \widehat{y}^{(t-1)}}
gi=∂y
(t−1)∂l(yi,y
(t−1))
h
i
=
∂
l
(
y
i
,
y
^
(
t
−
1
)
)
∂
2
y
^
(
t
−
1
)
h_{i}=\frac{\partial l(yi,\widehat{y}^{(t-1)})}{\partial^{2} \widehat{y}^{(t-1)}}
hi=∂2y
(t−1)∂l(yi,y
(t−1))
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
)
]
+
Ω
(
f
t
)
+
c
o
n
s
t
a
n
t
Obj(t)\approx \sum_{i=1}^{n}[l(y_{i},\widehat{y_{i}}^{(t-1)})+g_{i}f_{t}(x_{i})+\frac{1}{2}h_{i}f{t}^{2}(xi)]+\Omega(f_{t})+constant
Obj(t)≈∑i=1n[l(yi,yi
(t−1))+gift(xi)+21hift2(xi)]+Ω(ft)+constant
进一步化简,因为这里的
l
(
y
i
,
y
i
^
(
t
−
1
)
)
l(y_{i},\widehat{y_{i}}^{(t-1)})
l(yi,yi
(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_{i}f_{t}(x_{i})+\frac{1}{2}h_{i}f{t}^{2}(xi)]+\Omega(f_{t})
Obj(t)≈∑i=1n[gift(xi)+21hift2(xi)]+Ω(ft)
因为样本最终会落到树的叶结点上,故我们可以直接在树上遍历,所以我们的求和可以基于树来进行:
O
b
j
(
t
)
≈
∑
i
=
1
n
[
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
≈
∑
i
=
1
n
[
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
γ
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
Obj(t)\approx \sum_{i=1}^{n}[g_{i}f_{t}(x_{i})+\frac{1}{2}h_{i}f{t}^{2}(xi)]+\Omega(f_{t})\approx \sum_{i=1}^{n}[g_{i}f_{t}(x_{i})+\frac{1}{2}h_{i}f{t}^{2}(xi)]+\gamma T+\frac{1}{2}\lambda \sum_{j=1}^{T}w_{j}^{2}=\sum_{j=1}^{T}[(\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
Obj(t)≈∑i=1n[gift(xi)+21hift2(xi)]+Ω(ft)≈∑i=1n[gift(xi)+21hift2(xi)]+γT+21λ∑j=1Twj2=∑j=1T[(∑i∈Ijgi)wj+21(∑i∈Ijhi+λ)wj2]+γT
=
∑
j
=
1
T
[
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
]
+
γ
T
\sum_{j=1}^{T}[G_{j}w_{j}+\frac{1}{2}(H_{j}+\lambda )w^{2}_{j}]+\gamma T
∑j=1T[Gjwj+21(Hj+λ)wj2]+γT
每棵树的损失函数对
w
j
w_{j}
wj进行偏导令其为零,有
G
j
+
(
H
j
+
λ
)
w
j
=
0
G_{j}+(H_{j}+\lambda)w_{j}=0
Gj+(Hj+λ)wj=0
所以
w
j
=
−
G
j
H
j
+
λ
w_{j}=-\frac{G_{j}}{H_{j}+\lambda}
wj=−Hj+λGj
带回原目标函数
O
b
j
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
λ
T
Obj=-\frac{1}{2}\sum_{j=1}^{T}\frac{G_{j}^{2}}{H_{j}+\lambda}+\lambda T
Obj=−21∑j=1THj+λGj2+λT
. sklearn中的使用
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 4 20:48:14 2018
@author: muli
"""
'''
xgb使用sklearn接口(推荐)--官方:
会改变的函数名是:
eta -> learning_rate
lambda -> reg_lambda
alpha -> reg_alpha
#参数
params = { 'booster': 'gbtree',
'objective': 'multi:softmax', # 多分类的问题
'num_class': 10, # 类别数,与 multisoftmax 并用
'gamma': 0.1, # 用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子。
'max_depth': 12, # 构建树的深度,越大越容易过拟合
'reg_lambda': 2, # 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。
'subsample': 0.7, # 随机采样训练样本
'colsample_bytree': 0.7, # 生成树时进行的列采样
'min_child_weight': 3,
'silent': 1, # 设置成1则没有运行信息输出,最好是设置为0.
'learning_rate': 0.007, # 如同学习率
'reg_alpha':0, # L1 正则项参数
'seed': 1000,
'nthread': 4, # cpu 线程数
}
# 回归
# m_regress = xgb.XGBRegressor(n_estimators=1000,seed=0)
'''
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.datasets import make_hastie_10_2
from xgboost.sklearn import XGBClassifier
# make_hastie_10_2:
# 产生一个相似的二元分类器数据集,有10个维度
X, y = make_hastie_10_2(random_state=0)
# X:(12000, 10)
# y:(12000,)
# test_size测试集合所占比例
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
clf = XGBClassifier(
#树的个数
n_estimators=100,
# 如同学习率
learning_rate= 0.3,
# 构建树的深度,越大越容易过拟合
max_depth=6,
# 随机采样训练样本 训练实例的子采样比
subsample=1,
# 用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子
gamma=0,
# 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。
reg_lambda=1,
#最大增量步长,我们允许每个树的权重估计。
max_delta_step=0,
# 生成树时进行的列采样
colsample_bytree=1,
# 这个参数默认是 1,是每个叶子里面 h 的和至少是多少,对正负样本不均衡时的 0-1 分类而言
# 假设 h 在 0.01 附近,min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。
#这个参数非常影响结果,控制叶子节点中二阶导的和的最小值,该参数值越小,越容易 overfitting。
min_child_weight=1,
#随机种子
seed=1000
# L1 正则项参数
# reg_alpha=0,
#如果取值大于0的话,在类别样本不平衡的情况下有助于快速收敛。平衡正负权重
#scale_pos_weight=1,
#多分类的问题 指定学习任务和相应的学习目标
#objective= 'multi:softmax',
# 类别数,多分类与 multisoftmax 并用
#num_class=10,
# 设置成1则没有运行信息输出,最好是设置为0.是否在运行升级时打印消息。
# silent=0 ,
# cpu 线程数 默认最大
# nthread=4,
#eval_metric= 'auc'
)
# 模型 训练
clf.fit(X_train,y_train,eval_metric='auc')
# 预测值
y_pred=clf.predict(X_test)
# 真实值 赋值
y_true= y_test
# 计算精度
print("Accuracy : %.4g" % metrics.accuracy_score(y_true, y_pred))
#运行结果
Accuracy : 0.9258