adaboost
AdaBoost是最著名的Boosting族算法,是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器,即弱分类器,然后把这些弱分类器集合起来,构造一个更强的最终分类器。算法本身是改变数据分布实现的,它根据每次训练集之中的每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改权值的新数据送给下层分类器进行训练,然后将每次训练得到的分类器融合起来,作为最后的决策分类器。
开始时,所有样本的权重相同,训练得到第一个基分类器。从第二轮开始,每轮开始前都先根据上一轮基分类器的分类效果调整每个样本的权重,上一轮分错的样本权重提高,分对的样本权重降低。之后根据新得到样本的权重指导本轮中的基分类器训练,即在考虑样本不同权重的情况下得到本轮错误率最低的基分类器。重复以上步骤直至训练到约定的轮数结束,每一轮训练得到一个基分类器。
可以想象到,远离边界(超平面)的样本点总是分类正确,而分类边界附近的样本点总是有大概率被弱分类器(基分类器)分错,所以权值会变高,即边界附近的样本点会在分类时得到更多的重视。
输入
:训练数据集
输出
:最终分类器
步骤
:
(1) 初始化训练数据的权值分布
(2) 对
- 使用具有权值分布的训练数据集学习,得到基本分类器
- 计算在训练数据集上的分类误差率
- 计算的系数这里对数取自然对数。
- 更新权值分布
是规范化因子,,它使成为一个概率分布。
(3) 构建基本分类器的线性组合,
得到最终分类器,
例子
我们用李航《统计学习方法》一个例子来看一下
x | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
y | 1 | 1 | 1 | -1 | -1 | -1 | 1 | 1 | 1 | -1 |
数据集D共有10条数据,根据x的输入得到的y可以分为两类,即y=1与y=-1。我们每一轮使用最简单的决策树桩来构建基分类器,即每轮设定一个阈值θ,只要x<θ,就判定为正类(y=1),x>θ就判定为负类(y=-1)。(或者只要x<θ,就判定为正类(y=-1),x>θ就判定为负类(y=1))
第一轮
因为是第一轮,所有样本的权重相同为0.1()
因为是离散数据,所以可以依次取[0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5]来对x进行分类,有两种分类方法,
1、 时分为正类,时为负类
2、 时分为正类,时为负类
我们采用第一种方法,先类据一个例子,取0.5时,时分为正类,此时只有一个正例,即全部分类正确,时为负类,此时有四个负例分类正确,5个正例分类错误,总共来看,有五个分类正确,有五个分类错误,即错误率为0.5;……
x=[0,1,2,3,4,5,6,7,8,9]
y=[1,1,1,-1,-1,-1,1,1,1,-1]
def err1(x,g):
r=0#比值
c=0#计数
s=0#求和
for i in range(len(x)):
c=c+g[i]
if x[i]<0:
s=s+g[i]
else:
continue
return c,s
def err2(x,g):
r=0#比值
c=0#计数
s=0#求和
for i in range(len(x)):
c=c+g[i]
if x[i]>0:
s=s+g[i]
else:
continue
return c,s
def err(x,y,g):
m=[]
for i in range(len(x)):
R1=[]
R2=[]
c1=0
c2=0
R1=y[0:i+1]
R2=y[i+1:len(y)]
c1,s1=err1(R1,g)
c2,s2=err2(R2,g)
m.append(round((s1+s2)/(c1+c2),3))
return m
err(x,y)
[0.5, 0.4, 0.3, 0.4, 0.5, 0.6, 0.5, 0.4, 0.3]
得到=[0.5, 0.4, 0.3, 0.4, 0.5, 0.6, 0.5, 0.4, 0.3]
最小值时0.3,即取2.5时(或8.5)
第一层基分类器的权重:
α1=1/2*log(1−ϵ1)/ϵ1=0.4236
def weight(e):
return 1/2*np.log((1-e)/e)
def wm(x,y,g):
wm=[]
#k是最小错误率
k=err(x,y,g).index(min(err(x,y,g)))
#a权重系数
a=weight(min(err(x,y,g)))
for i in range(k+1):
w=np.exp(-1*a*y[i]*1)*g[i]
wm.append(round(w,4))
for i in range(k+1,len(y)):
w=np.exp(-1*a*y[i]*(-1))*g[i]
wm.append(round(w,4))
zm=round(np.sum(wm),4)
wm=wm/zm
return wm,zm,a,min(err(x,y,g))
第二轮
[0.07143636 0.07143636 0.07143636 0.07143636 0.07143636 0.07143636
0.16664849 0.16664849 0.16664849 0.07143636]
权重由全部是0.1变成上面的权重
下面就需要按照上面的矩阵来进行计算,这里就不一一进行计算了,需要注意的是这里是伪代码,并未写全,因为我们只看了对x进行分类时的第一种方法,其实是需要按照两种方法进行查看的
具体的原理运算过程可参考
最终结果入下:
sign(H(x))=sign(0.4236∗g1+0.6496∗g2+0.752∗g3)
这里进行简单的说明,前面的系数就是
后面跟的是每次分类的方法,比如g1就是[1,1,1,-1,-1,-1,-1,-1,-1,-1],因为第一次我们取取2.5时进行计算,即0,1,2三个位置小于0,而其他位置大于零,其他类似。
GBDT
GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Regression Tree),是一种迭代的决策树算法,该算法由多棵决策树组成,所有树的结论累加起来做最终答案。它在被提出之初就和SVM一起被认为是泛化能力(generalization)较强的算法。近些年更因为被用于搜索排序的机器学习模型而引起大家关注。
而Gradient Boost与传统的Boost的区别是,每一次的计算是为了减少上一次的残差(residual),而为了消除残差,我们可以在残差减少的梯度(Gradient)方向上建立一个新的模型。所以说,在Gradient Boost中,每个新的模型的建立是为了使得之前模型的残差往梯度方向减少,与传统Boost对正确、错误的样本进行加权有着很大的区别。
输入
:训练数据集
输出
:提升树
步骤
:
(1) 初始化
(2) 对
- 计算残差
- 拟合残差学习一个回归树,得到
- 更新
(3) 得到回归问题提升树
例子
我们用李航《统计学习方法》一个例子来看一下
x | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
y | 5.56 | 5.7 | 5.91 | 6.4 | 6.8 | 7.05 | 8.9 | 8.7 | 9.0 | 9.05 |
我们看到x的取值范围是[0.5,10.5],y的取值范围[5.0,10.0]
按照我们上述的算法进行求解
第一步:求即回归树
首先求解优化问题:
求解训练数据的切分点s:
这里的切分点可以考虑「1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5」
我们也很容易得到在R1和R2内部使平方损失误差达到最小值的c1和c2为
对于各个切分点,求出相应的以及
我们python简易代码跑一下
x=[1,2,3,4,5,6,7,8,9,10]
y=[5.56,5.7,5.91,6.4,6.8,7.05,8.9,8.7,9.0,9.05]
def err(x):
n=len(x)
s=0
avg=np.mean(x)
for i in range(n):
s=s+pow(x[i]-avg,2)
return s
def m(x,y):
m=[]
for i in range(len(x)-1):
R1=[]
R2=[]
c1=0
c2=0
R1=y[0:i+1]
R2=y[i+1:len(y)]
m1=err(R1)
m2=err(R2)
m.append(round(m1+m2,2))
return m
m(x,y)
[15.72, 12.08, 8.37, 5.78, 3.91, 1.93, 8.01, 11.74, 15.74]
这里我们看到S=6.5时,残差值是最小的
这时
回归树
用拟合训练数据集的残差,
x | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
-0.68 | -0.54 | -0.33 | 0.16 | 0.56 | 0.81 | -0.01 | -0.21 | 0.09 | 0.14 |
第二步:
求回归树,与上面一样,不过现在需要拟合的是上表中的残差
m(x,r2)
#[1.42, 1.0, 0.79, 1.13, 1.66, 1.93, 1.93, 1.9, 1.91]
总结
-
GBDT每一轮训练时所关注的重点是本轮产生结果的残差,下一轮以本轮残差作为输入,尽量去拟合这个残差,使下一轮输出的残差不断变小。所以GBDT可以做到每一轮一定向损失函数减小的梯度方向变化,而传统的boosting算法只能是尽量向梯度方向减小,这是GBDT与传统boosting算法最大的区别,这也是为什么GBDT相比传统boosting算法可以用更少的树个数与深度达到更好的效果。
-
和AdaBoost一样,GradientBoosting也是重复选择一个表现一般的模型并且每次基于先前模型的表现进行调整。不同的是,AdaBoost是通过提升错分数据点的权重来定位模型的不足,而GBDT是通过算梯度来定位模型的不足。因此相比AdaBoost,GBDT可以使用更多种类的目标函数。
-
抽象地说,模型的训练过程是对一任意可导目标函数的优化过程,通过反复地选择一个指向负梯度方向的函数,该算法可被看作在函数空间里对目标函数进行优化。