1 加法模型和前向分布算法
给定训练集
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
…
,
(
x
N
,
y
N
)
}
D=\{(x_{1},y_{1}),(x_{2},y_{2}),\dots,(x_{N},y_{N})\}
D={(x1,y1),(x2,y2),…,(xN,yN)}及损失函数
L
(
y
,
f
(
x
)
)
L(y,f(x))
L(y,f(x))。假定希望构造一个如下的的加法模型
f
(
x
)
f(x)
f(x)来对数据集
D
D
D进行拟合。加法模型
f
(
x
)
f(x)
f(x)的数学表示如下:
f
(
x
)
=
∑
i
=
1
M
β
m
b
(
x
;
r
m
)
f(x)=\sum_{i=1}^{M}\beta_{m}b(x;r_{m})
f(x)=i=1∑Mβmb(x;rm)其中
b
(
x
;
r
m
)
b(x;r_{m})
b(x;rm)称为基模型(或称弱模型),
β
m
\beta_{m}
βm为基模型的系数,
r
m
r_{m}
rm为基模型的参数。此时加法模型
f
(
x
)
f(x)
f(x)的训练目标是寻找一组最优的
(
β
m
,
r
m
)
(\beta_{m},r_{m})
(βm,rm)使在数据集
D
D
D上的损失最小。即:
arg
β
m
,
r
m
min
∑
i
=
1
N
L
(
y
,
f
(
x
i
)
=
∑
m
=
1
M
β
m
b
(
x
i
;
r
m
)
)
\arg_{\beta_{m},r_{m}} \min \sum_{i=1}^{N}L(y,f(x_{i})=\sum_{m=1}^{M}\beta_{m}b(x_{i};r_{m}))
argβm,rmmini=1∑NL(y,f(xi)=m=1∑Mβmb(xi;rm))显然一次性求出所有的
β
m
\beta_{m}
βm和
r
m
r_{m}
rm是非常难的。
为了求解加法模型可以考虑使用贪心策略,每一步只学习一个基模型及其系数,使得当前基模型和之前所有的基模型组合后目标表达式取得最优值,最终就可以使得所有弱模型组合后目标表达式取得最优值。这种方法即前向分步算法,其算法步骤如下:
- 初始化 f 0 ( x ) = 0 f_{0}(x)=0 f0(x)=0
- 对于 m = 1 , 2 , … , M m=1,2,\dots,M m=1,2,…,M,分别依次执行以下两步操作:
(a)求 β m \beta_{m} βm和 r m r_{m} rm使当前的损失函数最小。即 ( β m , r m ) = arg β m , r m min ∑ i = 1 N L ( y i , f m − 1 ( x i ) + β m b ( x i ; r m ) ) (\beta_{m},r_{m})=\arg_{\beta_{m},r_{m}}\min \sum_{i=1}^{N}L(y_{i},f_{m-1}(x_{i})+\beta_{m}b(x_{i};r_{m})) (βm,rm)=argβm,rmmini=1∑NL(yi,fm−1(xi)+βmb(xi;rm))(b)更新 f m ( x ) f_{m}(x) fm(x): f m ( x ) = f m − 1 ( x ) + β m b ( x ; r m ) f_{m}(x)=f_{m-1}(x)+\beta_{m}b(x;r_{m}) fm(x)=fm−1(x)+βmb(x;rm)- 最终的模型为: f ( x ) = ∑ m = 1 M β m b ( x ; r m ) f(x)=\sum_{m=1}^{M}\beta_{m}b(x;r_{m}) f(x)=m=1∑Mβmb(x;rm)
2 梯度提升
使用前向分步算法求解加法模型时,若使用的平方损失函数有如下发现:
L
(
y
,
f
m
(
x
)
)
=
∑
i
=
1
N
(
y
i
−
(
f
m
−
1
(
x
i
)
+
β
m
b
(
x
i
;
r
m
)
)
)
2
=
∑
i
=
1
N
(
y
−
f
m
−
1
(
x
i
)
−
β
m
b
(
x
i
;
r
m
)
)
2
\begin{aligned}L(y,f_{m}(x))&=\sum_{i=1}^{N}(y_{i}-(f_{m-1}(x_{i})+\beta_{m}b(x_{i};r_{m})))^{2}\\&=\sum_{i=1}^{N}(y-f_{m-1}(x_{i})-\beta_{m}b(x_{i};r_{m}))^{2}\end{aligned}
L(y,fm(x))=i=1∑N(yi−(fm−1(xi)+βmb(xi;rm)))2=i=1∑N(y−fm−1(xi)−βmb(xi;rm))2其中
y
−
f
m
−
1
(
x
)
y_-f_{m-1}(x)
y−fm−1(x)即为残差,此时需要寻找的
β
m
\beta_{m}
βm和
r
m
r_{m}
rm只要能拟合前面模型的残差就可以了。
如果使用的不是平方损失函数,又或者损失函数很难进行优化时,使用前向分步算法求解基函数就非常困难了。为了解决这个问题,Friedman提出了梯度提升(Gradient Boosting)方法。该方法使用损失函数负梯度的方向代替残差方向,即损失函数的负梯度在当前模型的值作为残差的近似值,所以该值又被称为伪残差(当使用平方损失函数时,伪残差即为残差)。此时,加法模型的求解过程如下:
- 用一个常数值初始化 f 0 ( x ) f_{0}(x) f0(x)。 f 0 ( x ) = arg γ min ∑ i = 1 N L ( y i , γ ) f_{0}(x)=\arg_{\gamma} \min \sum_{i=1}^{N}L(y_{i},\gamma) f0(x)=argγmini=1∑NL(yi,γ)
- 对于 m = 1 , 2 , … , M m=1,2,\dots,M m=1,2,…,M分别执行以下三步:
(a)对于 i = 1 , 2 , … , N i=1,2,\dots,N i=1,2,…,N的每个样本的伪残差: γ i m = − [ ∂ L ( y i , f ( x i ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) \gamma_{im}=-[\frac{\partial L(y_{i},f(x_{i})}{\partial f(x_{i})}]_{f(x)=f_{m-1}(x)} γim=−[∂f(xi)∂L(yi,f(xi)]f(x)=fm−1(x)(b)在新的训练集 { ( x i , γ 1 m ) , ( x 2 , γ 2 m ) , … , ( x N , γ N m ) } \{(x_{i},\gamma_{1m}),(x_{2},\gamma_{2m}),\dots,(x_{N},\gamma_{Nm})\} {(xi,γ1m),(x2,γ2m),…,(xN,γNm)}训练模型 b ( x ; r m ) b(x;r_{m}) b(x;rm)。之后计算 β m \beta_{m} βm,其计算公式如下: β m = arg β min ∑ i = 1 N L ( y i , f m − 1 ( x i ) + β b ( x i ; r m ) ) \beta_{m}=\arg_{\beta}\min \sum_{i=1}^{N}L(y_{i},f_{m-1}(x_{i})+\beta b(x_{i};r_{m})) βm=argβmini=1∑NL(yi,fm−1(xi)+βb(xi;rm))之后更新模型: f m = f m − 1 ( x ) + β m b ( x ; r m ) f_{m}=f_{m-1}(x)+\beta_{m}b(x;r_{m}) fm=fm−1(x)+βmb(x;rm)- 最终的模型为: f ( x ) = ∑ m = 1 M β m b ( x ; r m ) f(x)=\sum_{m=1}^{M}\beta_{m}b(x;r_{m}) f(x)=m=1∑Mβmb(x;rm)
3 GBDT
GBDT(Gradient Boosting Decision Tree,梯度提升决策树)是以CART回归树为基模型,使用梯度提升策略进行求解的加法模型(数据集成学习的Boosting型算法)。当使用平方损失时,GBDT算法最终形成的回归模型为:
F
(
x
)
=
∑
m
=
1
M
∑
j
=
1
J
β
m
c
m
j
I
(
x
i
∈
R
m
j
)
F(x)=\sum_{m=1}^{M}\sum_{j=1}^{J}\beta_{m}c_{mj}I(x_{i}\in R_{mj})
F(x)=m=1∑Mj=1∑JβmcmjI(xi∈Rmj)其中,
J
J
J为每个决策树的叶子结点数目(每单棵决策树的叶子结点个数可以不同)。
R
m
j
R_{mj}
Rmj为第
m
m
m个回归树的第
j
j
j个叶结点区域。
c
m
j
=
arg
c
min
∑
x
i
∈
R
m
j
L
(
y
i
,
f
m
−
1
(
x
i
)
+
c
)
c_{mj}=\arg_{c}\min \sum\limits_{x_{i}\in R_{mj}}L(y_{i},f_{m-1}(x_{i})+c)
cmj=argcminxi∈Rmj∑L(yi,fm−1(xi)+c)为第
m
m
m个回归树的第
j
j
j个叶结点的预测值。
在上述模型基础上,GBDT又引入了衰减(Shrinkage), 衰减机制认为每次走一小步来逼近结果的效果比每次迈一大步很快逼近结果的方式更容易防止过拟合。加入衰减之后,最后的模型为:
F
(
x
)
=
v
∑
m
=
1
M
∑
j
=
1
J
β
m
c
m
j
I
(
x
i
∈
R
m
j
)
F(x)=v\sum_{m=1}^{M}\sum_{j=1}^{J}\beta_{m}c_{mj}I(x_{i}\in R_{mj})
F(x)=vm=1∑Mj=1∑JβmcmjI(xi∈Rmj)其中
v
v
v被称为学习率(即衰减)。
在分类问题中,由于样本输出的不是连续值,导致无法直接从输出类别去拟合输出类别误差,常用的有两种解决方案:一是使用指数损失函数;二是用类似逻辑回归的对数似然损失函数,用类别的预测概率值和真实概率值的差值来拟合损失。
4 案例
4.1 常用参数
以GradientBoostingRegreesor()为例,对其中的几个主要参数进行说明。
主要参数作用如下:
- loss:‘ls’,‘lad’,‘huber’和‘quantile’。
- learning_rate: 控制GBDT中的衰减。
- n_estimators:基模型的个数。
- max_features:寻找最优分裂时考虑的特征个数。
- alpha: 只有当loss='huber’或loss='quantile’时这个参数才有用。
import pandas as pd
import numpy as np
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
X,y=load_boston(return_X_y=True)
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0,test_size=0.2)
gbr=GradientBoostingRegressor(n_estimators=100,max_depth=3)
gbr.fit(X_train,y_train)
y_pred=gbr.predict(X_test)
print("RMSE:{:.3f}".format(np.sqrt(mean_squared_error(y_test, y_pred))))
参考资料: