1、基本知识
来源
1.1、名词解释
Boosting (提升)是一种将弱分类器 h ( x ) h(x) h(x)组合起来形成强分类器 F ( x ) F(x) F(x)的算法框架。
**参数估计:**在参数空间内进行数值优化(以参数作为变量)
**函数估计:**在函数空间内进行数值优化(以函数作为变量)
模型的含义:
假设我们的模型可以用下面的函数来表示,
P
P
P表示参数,可能有多个参数组成,
P
=
{
p
0
,
p
1
,
p
2
…
}
P=\{p_0,p_1,p_2\dots\}
P={p0,p1,p2…},
F
(
x
;
P
)
F(x;P)
F(x;P)表示以P为参数的x的函数。我们的模型是由多个模型叠加起来的,
β
\beta
β表示每个模型的权重,
α
\alpha
α表示单个模型内部的参数。即
F
(
x
)
=
F
(
x
,
P
)
=
∑
m
=
1
M
β
m
h
(
x
;
α
m
)
F(x)=F(x,P)=\sum_{m=1}^M\beta _m h(x;\alpha_m)
F(x)=F(x,P)=m=1∑Mβmh(x;αm)
式中
h
(
x
;
α
m
)
h(x;\alpha_m)
h(x;αm)表示弱分类器,
β
m
\beta_m
βm表示其他对应的权重。
我们的目标是:
X
−
F
∗
(
x
)
−
>
y
X-F*(x) ->y
X−F∗(x)−>y,式中->表示趋近于,
F
∗
(
x
)
F^*(x)
F∗(x)表示从属性到目标函数的最优映射,最佳体现在
F
∗
(
x
)
F^*(x)
F∗(x)满足样本集
{
x
,
y
}
\{x,y\}
{x,y}的分布。
我们用
ϕ
(
P
)
\phi(P)
ϕ(P)表示P的likelihood(似然函数),似然函数与损失函数一样都可作为目标函数(这里是以参数优化而非函数优化为例)。
总体目标抽象为似然函数
ϕ
(
y
,
F
(
x
;
P
)
)
\phi(y,F(x;P))
ϕ(y,F(x;P))期望最小化:
上面包含了boosting算法的三个要素
1)函数模型
Boosting的函数模型是叠加型的,
F
(
x
)
=
F
(
x
,
P
)
=
∑
m
=
1
M
β
m
h
(
x
;
α
m
)
F(x)=F(x,P)=\sum_{m=1}^M\beta _m h(x;\alpha_m)
F(x)=F(x,P)=∑m=1Mβmh(x;αm)
2)目标函数
选定某种损失函数作为优化目标;$ \phi §]$
3)优化算法
贪婪地逐步优化,
P
∗
=
a
r
g
m
i
n
(
ϕ
(
P
)
)
=
a
r
g
m
i
n
P
E
y
,
x
[
L
(
y
,
F
(
x
;
P
)
)
]
P^*={arg\ min }(\phi(P))={arg\ min \atop P}E_{y,x}[L (y,F(x;P))]
P∗=arg min(ϕ(P))=Parg minEy,x[L(y,F(x;P))]
1.2、数值优化在参数空间的基本流程(用梯度下降的思维来求解)
选择一个参数化的模型(就是固定函数,来寻找参数使模型最优?),就将模型优化变成参数优化问题。
P
∗
=
a
r
g
m
i
n
(
ϕ
(
P
)
)
ϕ
(
P
)
=
E
y
,
x
[
L
(
y
,
F
(
x
;
P
)
)
]
P^*={arg\ min}(\phi(P))\\ \phi(P)=E_{y,x}[L (y,F(x;P))]
P∗=arg min(ϕ(P))ϕ(P)=Ey,x[L(y,F(x;P))]
既然模型
F
(
x
;
P
)
F(x;P)
F(x;P)是可叠加的,对于参数P,我们也可以得到下面的式子:
P
∗
=
∑
m
=
0
M
p
m
P^*=\sum_{m=0}^Mp_m
P∗=m=0∑Mpm
这样优化P的过程就可以是一个梯度下降的过程了。假如当前已经得到了
m
−
1
m-1
m−1个模型,想要得到第m个模型的时候,我们首先对前
m
−
1
m-1
m−1个模型求梯度,得到最快下降的方向。假如
g
m
g_m
gm就是最快下降方向。
g
m
=
{
g
j
m
}
=
{
∂
ϕ
(
P
)
∂
P
j
∣
p
=
p
m
−
1
}
g_m=\{g_{jm}\}= \left\{ \frac{\partial \phi(P)}{\partial P_j} \bigg| _{p=p_{m-1}} \right\}
gm={gjm}={∂Pj∂ϕ(P)
p=pm−1}
这里有一个很重要的假设,对于求出的前
m
−
1
m-1
m−1个模型,我们认为是已知的了,不要去改变它。我们的目标是放在之前模型的建立上。
P
m
−
1
=
∑
i
=
0
M
−
1
p
i
P_{m-1}=\sum_{i=0}^{M-1}p_i
Pm−1=i=0∑M−1pi
我们得到的新模型就是,它在P似然函数的梯度方向。
ρ
\rho
ρ是在梯度方向上下降的距离。
p
m
=
−
ρ
m
g
m
p_m=-\rho_m g_m
pm=−ρmgm
我们最终可以通过优化下面的式子来得到最优的
ρ
\rho
ρ:
ρ
m
=
a
r
g
m
i
n
ϕ
(
P
m
−
1
−
ρ
m
g
m
)
\rho_m={arg\ min\ } \phi(P_{m-1}-\rho_m g_m)
ρm=arg min ϕ(Pm−1−ρmgm)
1.3、数值优化在函数空间的基本流程(用梯度下降的思维来求解)
上面通过参数P的可加性,得到了参数P似然函数梯度下降的方法。我们可以将参数P的可加性推广到函数空间,得到下面的函数。此处的
f
i
(
x
)
f_i(x)
fi(x)是上面
h
(
x
,
α
)
h(x,\alpha)
h(x,α)的另一种表示。
F
m
−
1
(
x
)
=
∑
i
=
0
m
−
1
f
i
(
x
)
类似于
P
m
−
1
=
∑
i
=
0
m
−
1
p
i
F_{m-1}(x)=\sum_{i=0}^{m-1}f_i(x)类似于P_{m-1}=\sum_{i=0}^{m-1}p_i
Fm−1(x)=i=0∑m−1fi(x)类似于Pm−1=i=0∑m−1pi
同样我们可以得到
F
(
x
)
F(x)
F(x)的梯度下降方向
g
(
x
)
g(x)
g(x)
g
m
(
x
)
=
E
y
[
∂
L
(
y
,
F
(
x
)
)
∂
F
(
x
)
∣
x
]
F
(
x
)
=
F
m
−
1
(
x
)
类似于
g
m
=
{
g
j
m
}
=
{
∂
ϕ
(
P
)
∂
P
j
∣
p
=
p
m
−
1
}
g_m(x)=E_y \left [ \frac{\partial L(y,F(x))}{\partial F(x)} \bigg|_x \right ]_{F(x)=F_{m-1}(x)} 类似于g_m=\{g_{jm}\}= \left\{ \frac{\partial \phi(P)}{\partial P_j} \bigg| _{p=p_{m-1}} \right\}
gm(x)=Ey[∂F(x)∂L(y,F(x))
x]F(x)=Fm−1(x)类似于gm={gjm}={∂Pj∂ϕ(P)
p=pm−1}
最终可以得到第m个模型
f
m
(
x
)
f_m(x)
fm(x)的表达式:
f
m
(
x
)
=
−
ρ
m
g
m
(
x
)
f_m(x)=-\rho_m g_m(x)
fm(x)=−ρmgm(x)
1.4、几个关键点的解释
1.为什么总体目标是求损失函数的期望?
损失函数,反映了模型与实际值之间的差距,其总和越小,表示模型对数据的拟合度越高,也反映了模型对数据分布的拟合越好。
期望,是某变量的总体均值,是评估整体的一个有效指标。
2.为什么需要线性搜索?
线性搜索,可以保证下降方向上移动最大,是下降步幅的控制。
3.有限样本与无限样本
无限样本下的期望是真实的反映;有限样本则是近似;
4.F的理解
F 作为模型函数,一直处于概念化的状态。
其中在参数空间内优化的过程中,没有明显地体现,只是在参数P上体现了不断累计的思想。
在函数空间内优化的过程中,则是表现为最好的模型函数是由一点点的增量函数累计起来的。
5.模型评估策略的选择
根据不同问题类型,可以有多重评估策略
回归问题:
可以选择最小均方误差策略[yi−F(xi)]2;
求导为:gm(xi)=−[yi−Fm−1(xi)]
也可以选择Least-squares|yi−F(xi)|;
求导得:gm(xi)=−sign[yi−Fm−1(xi)]
也可以选择其他的策略等等。
分类问题:
logistic likelihood crit
1.5、boosting算法实例
将上述框架中的
h
(
x
)
h(x)
h(x)选为决策树,
E
{
F
(
x
)
}
E\{F(x)\}
E{F(x)}选为指数损失函数,就可以得到adaboost,根据不同的loss function还可以有其他算法,比如L2Boosting, logitboost…
针对于这种提升方法而言,需要回答两个问题,一是在每一轮如何改变训练样本的权值或概率分布;二是如何将弱分类器组合成一个强分类器。Adaboost属于Boosting一种,它可以很好的解决上述两个问题,针对第一个问题,Adaboost的做法是提高那些被前一轮弱分类器错误分类样本的权值,而降低那些被正确分类的样本的权重。从而使得那些被错误分类的样本由于其权值被加大而受到后一轮弱分类器的更多的关照(关注)。而针对第二个问题,Adaboost采取加权多数表决的方法,加大分类误差率小的弱分类器的权重,使其在最终的分类器表决中起较大作用,减小分类误差率大的弱分类器的权重,使其在表决中起较小的作用。总结起来,有两个权重的概念,一个是增大错误分类样本的权重,一个增大分类误差率小的弱分类器的权重。
1.6、Gradient Boosting
来源
Gradient Boosting是一种Boosting方法的具体实现,其基本思想是每一次建立模型是在之前建立的模型梯度下降的方向。损失函数描述的是模型的不靠谱程度,损失函数值越大,说明模型的越容易出错(其实这里有一个方差、偏差的问题,但这里假设,损失函数值越大越容易出错)。如果我们的模型能够让损失函数持续的下降,那说明我们的模型在不断地改进,其中的一种方式就是让损失函数在梯度方向上下降。这一点还是比较好理解,我们在单一的算法中,如逻辑回归寻找模型最优参数的时候也是采用损失函数或似然值梯度下降的方向来不断逼近最优模型参数。
F
(
x
;
p
)
=
∑
m
=
1
M
β
m
h
m
(
x
;
α
m
)
F(x;p)=\sum_{m=1}^M \beta_m h_m(x;\alpha_m)
F(x;p)=m=1∑Mβmhm(x;αm)
对于模型的参数
{
β
,
α
}
\{\beta,\alpha\}
{β,α},我们可以用下面的式子来表示。这个式子的意思是,对于N个样本点,
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi),计算其在模型
F
(
x
;
α
;
β
)
F(x;\alpha;\beta)
F(x;α;β)下的损失函数,最优的
(
α
;
β
)
(\alpha;\beta)
(α;β)就是能使这个损失函数最小的
(
α
;
β
)
(\alpha;\beta)
(α;β)。
{
β
m
;
α
m
}
1
M
\{\beta_m;\alpha_m\}_1^M
{βm;αm}1M表示两个m维的参数:
{
β
m
;
α
m
}
1
M
=
a
r
g
m
i
n
∑
i
=
1
N
L
(
y
i
,
∑
m
=
1
M
β
m
h
(
x
;
α
m
)
)
\{\beta_m;\alpha_m\}_1^M={arg\ min}\sum_{i=1}^N L(y_i,\sum_{m=1}^M \beta_m h(x;\alpha_m))
{βm;αm}1M=arg mini=1∑NL(yi,m=1∑Mβmh(x;αm))
写成梯度下降的方式就是下面的形式,也就是我们将要得到的模型
f
m
(
x
)
f_m(x)
fm(x)的参数
(
α
m
;
β
m
)
(\alpha_m;\beta_m)
(αm;βm),能够使得
f
m
f_m
fm的方向是之前得到的模型
F
m
−
1
(
x
)
F_{m-1}(x)
Fm−1(x)的损失函数下降最快的方向:
β
m
;
α
m
=
a
r
m
m
i
n
∑
i
=
1
N
L
(
y
,
F
m
−
1
(
x
i
)
+
β
h
(
x
i
;
α
)
)
\beta_m;\alpha_m={arm\ min} \sum_{i=1}^N L(y,F_{m-1}(x_i)+\beta h(x_i;\alpha))
βm;αm=arm mini=1∑NL(y,Fm−1(xi)+βh(xi;α))
对于每一个数据点
x
i
x_i
xi都可以得到一个
g
m
(
x
i
)
g_m(x_i)
gm(xi),最终我们可以得到一个完整梯度下降方向。
→
g
m
=
{
−
g
m
(
x
i
)
}
1
N
−
g
m
(
x
i
)
=
−
[
∂
L
(
y
i
,
F
(
x
i
)
)
∂
F
(
x
i
)
∣
x
]
F
(
x
)
=
F
m
−
1
(
x
)
{\rightarrow \atop g_m }=\{-g_m(x_i)\}_1^N\\ -g_m(x_i)=-\left [ \frac{\partial L(y_i,F(x_i))}{\partial F(x_i)} \bigg|_x \right ]_{F(x)=F_{m-1}(x)}
gm→={−gm(xi)}1N−gm(xi)=−[∂F(xi)∂L(yi,F(xi))
x]F(x)=Fm−1(x)
为了使得
f
m
(
x
)
f_m(x)
fm(x)能够在
g
m
(
x
)
g_m(x)
gm(x)的方向上,我们可以优化下面的式子得到,可以使用最小二乘法:
α
m
=
a
r
g
m
i
n
∑
i
=
1
N
(
−
g
m
(
x
i
)
−
β
h
(
x
;
α
)
)
2
\alpha_m={arg\ min} \sum_{i=1}^N (-g_m(x_i)-\beta h(x;\alpha))^2
αm=arg mini=1∑N(−gm(xi)−βh(x;α))2
得到
α
\alpha
α的基础上可以得到
β
m
\beta_m
βm。
β
m
=
a
r
g
m
i
n
∑
i
=
1
N
L
(
y
i
,
F
m
−
1
(
x
i
)
+
β
h
(
x
i
;
α
m
)
)
\beta_m={arg\ min} \sum_{i=1}^N L(y_i,F_{m-1}(x_i)+\beta h(x_i;\alpha_m))
βm=arg mini=1∑NL(yi,Fm−1(xi)+βh(xi;αm))
最终合并到模型中:
F
m
(
x
)
=
F
m
−
1
(
x
)
+
ρ
m
h
(
x
;
α
m
)
F_m(x)=F_{m-1}(x)+\rho_m h(x;\alpha_m)
Fm(x)=Fm−1(x)+ρmh(x;αm)
算法的流程图如下:
####1.6.1、Gradient Boosting 算法实现
https://blog.csdn.net/qq_36510261/article/details/78875278
https://www.kaggle.com/grroverpr/gradient-boosting-simplified/
http://bbs.pinggu.org/thread-3716235-1-1.html
下面是网上的一段代码,初步探索了梯度下降提升算法的实现方向(代码写的比较差,最终梯度下降提升的功能也没实现,但有这么点意思在里面)。
# -*- coding: utf-8 -*-
__author__ = 'mike-bowles'
import numpy
import matplotlib.pyplot as plot
from sklearn import tree
from sklearn.tree import DecisionTreeRegressor
from math import floor
import random
# Build a simple data set with y = x + random
nPoints = 1000
# x values for plotting
xPlot = [(float(i) / float(nPoints) - 0.5) for i in range(nPoints + 1)]
# x needs to be list of lists.
x = [[s] for s in xPlot]
# y (labels) has random noise added to x-value
# set seed
numpy.random.seed(1)
y = [s + numpy.random.normal(scale=0.1) for s in xPlot]
# take fixed test set 30% of sample
nSample = int(nPoints * 0.30)
idxTest = random.sample(range(nPoints), nSample)
idxTest.sort()
idxTrain = [idx for idx in range(nPoints) if not (idx in idxTest)]
# Define test and training attribute and label sets
xTrain = [x[r] for r in idxTrain]
xTest = [x[r] for r in idxTest]
yTrain = [y[r] for r in idxTrain]
yTest = [y[r] for r in idxTest]
# train a series of models on random subsets of the training data
# collect the models in a list and check error of composite as list grows
# maximum number of models to generate
numTreesMax = 30
# tree depth - typically at the high end
treeDepth = 5
# initialize a list to hold models
modelList = []
predList = []
eps = 0.3
# initialize residuals to be the labels y
residuals = list(yTrain)
for iTrees in range(numTreesMax):
modelList.append(DecisionTreeRegressor(max_depth=treeDepth))
modelList[-1].fit(xTrain, residuals)
# make prediction with latest model and add to list of predictions
latestInSamplePrediction = modelList[-1].predict(xTrain)
# use new predictions to update residuals
residuals = [residuals[i] - eps * latestInSamplePrediction[i] for i in range(len(residuals))]#各维度的误差,后面并没有使用到
latestOutSamplePrediction = modelList[-1].predict(xTest)
predList.append(list(latestOutSamplePrediction))#获得各树的预测结果。
# build cumulative prediction from first "n" models
mse = []
allPredictions = []
for iModels in range(len(modelList)):
# add the first "iModels" of the predictions and multiply by eps
prediction = []
for iPred in range(len(xTest)):
prediction.append(sum([predList[i][iPred] for i in range(iModels + 1)]) * eps)#第n次的预测值是其前n-1次预测值的之和再乘以eps
allPredictions.append(prediction)
errors = [(yTest[i] - prediction[i]) for i in range(len(yTest))]#某一次的预测误差
mse.append(sum([e * e for e in errors]) / len(yTest))#利用均方根误差整个预测的误差。
nModels = [i + 1 for i in range(len(modelList))]
plot.plot(nModels, mse)
plot.axis('tight')
plot.xlabel('Number of Models in Ensemble')
plot.ylabel('Mean Squared Error')
plot.ylim((0.0, max(mse)))
plot.show()
plotList = [0, 14, 29]
lineType = [':', '-.', '--']
plot.figure()
for i in range(len(plotList)):
iPlot = plotList[i]
textLegend = 'Prediction with ' + str(iPlot) + ' Trees'
plot.plot(xTest, allPredictions[iPlot], label=textLegend,
linestyle=lineType[i])
plot.plot(xTest, yTest, label='True y Value', alpha=0.25)
plot.legend(bbox_to_anchor=(1, 0.3))
plot.axis('tight')
plot.xlabel('x value')
plot.ylabel('Predictions')
plot.show()
结果如下所示:
上面的代码展示了对不同决策进行线性组合得到的新的预测结果与真实值之间的误差可能会减小,也可能会增加。
那么我们应该怎么利用梯度下降来提升算法准确度呢?
观察上面的误差曲线能发现,当有些模型加进组合的时候,综合误差得到下降,但有些模型加进组合时,综合误差反而上升。我们应该选择使误差下降的模型。通过求误差曲线的梯度(导数),在梯度为负的地方,该模型我们应该选择。
但是上面代码简单地将前n-1个模型的预测结果相加再乘以一个系数的做法是错误的。我们可以这样考虑这个问题,假设各模型预测结果都不错,接近真实值,组合预测值为y_n,eps=0.3,那么第一次组合预测的时候,预测结果为
0.3
y
1
0.3y_1
0.3y1,其值误差自然就比较大;第二次组合预测时,预测结果为
0.3
y
1
+
0.3
y
2
0.3y_1+0.3y_2
0.3y1+0.3y2,其误差很可能减小,这样我们就分不清是后面模型更好带来的优化,还是组合值在接近真实值而带来的优化;同样可以想象,当模型增多,远大于3个时,组合预测值必然会远远大于真实值而使误差变大(图中虽然不明显,应该是数据特殊的问题)。
为了对各模型公平,我认为在组合计算时,应该使用各模型的加权平均值作为预测值,并计算误差,各误差曲线的梯度。在梯度下降(导数为负)处的模型做为优质模型或权重得到加强,梯度上升处的模型应被削弱或剔除。
当然后续还可以进行其他的一些操作。
下次再来改写这个程序。
1.6.2、Gradient Boosting 调参
https://blog.csdn.net/han_xiaoyang/article/details/52663170