版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kabuto_hui/article/details/88106258
1. AdaBoost
在周志华先生的《机器学习》的集成学习(第8章)一章中,给出了Adaboost算法的伪代码,这里对继续对这个算法进行详细的解释。 AdaBoost的基本原理就是训练N个弱学习器,将这N个弱学习器进行加权结合:
【上面的算法可以总结为 】:
初始化样本的分布,一般初始化为1/m, m为样本的个数;
训练T个基学习器(弱学习器);对于每个学习器
h
t
h_t
h t :
计算该基学习器的误差:
ϵ
t
\epsilon_t
ϵ t
根据误差计算该基学习器的权重:
α
t
=
1
2
l
n
(
1
−
ϵ
t
ϵ
t
)
\alpha_t = \frac{1}{2}ln(\frac{1-\epsilon_t}{\epsilon_t})
α t = 2 1 l n ( ϵ t 1 − ϵ t )
然后根据权重修改样本的分布,减小分类正确的样本权重,增加分类错误的样本权重:
D
t
+
1
(
x
)
=
D
t
(
x
)
e
x
p
(
−
α
t
f
(
x
)
h
t
(
x
)
)
z
t
D_{t+1}(x)=\frac{D_t(x)exp(-\alpha_t f(x)h_t(x))}{z_t}
D t + 1 ( x ) = z t D t ( x ) e x p ( − α t f ( x ) h t ( x ) ) 。其中$ f(x)h_t(x)
分
类
正
确
的
时
候
是
1
,
分
类
错
误
的
时
候
是
−
1
,
这
样
就
实
现
了
更
改
样
本
权
重
的
目
的
。
而
对
于
分类正确的时候是1,分类错误的时候是-1,这样就实现了更改样本权重的目的。而对于
分 类 正 确 的 时 候 是 1 , 分 类 错 误 的 时 候 是 − 1 , 这 样 就 实 现 了 更 改 样 本 权 重 的 目 的 。 而 对 于 z_t
,
书
中
称
为
规
范
化
因
子
,
在
周
志
华
先
生
的
书
中
:
,书中称为规范化因子,在周志华先生的书中:
, 书 中 称 为 规 范 化 因 子 , 在 周 志 华 先 生 的 书 中 : z_t = \frac{上一轮迭代的误差}{本轮迭代的误差}
,
而
在
实
际
编
程
中
我
们
可
以
直
接
将
,而在实际编程中我们可以直接将
, 而 在 实 际 编 程 中 我 们 可 以 直 接 将 z_t
表
示
为
权
重
值
之
和
:
表示为 权重值之和:
表 示 为 权 重 值 之 和 : z_t = D.sum()$【见《Machine Learning in Action》】
最后将这T个基学习器,加权叠加:
H
(
x
)
=
s
i
g
n
(
∑
i
=
1
T
α
t
h
t
(
x
)
H(x) = sign(\sum_{i=1}^{T} \alpha_t h_t(x)
H ( x ) = s i g n ( ∑ i = 1 T α t h t ( x )
分布的变化是怎么影响基学习器的生成的? 举个例子:如果基学习器是一个决策树树桩,我们需要找到误差最小的特征作为分类特征,而这个时候计算的误差是加权误差,也就是我们的分布起作用的地方。 所以分布的变化影响了每个树桩的分类特征的选取,从而形成不同的树桩。因此我们可以说样本分布的变化通过影响每个基学习器的错误率而影响了基学习器的生成。
2. Boosting Tree
提升树是以分类树或者回归树为基本分类器的提升方法。对分类问题决策树是二叉分类树,对回归问题决策树是二叉回归树。针对于不同问题的提升树学习算法,其主要区别在于使用的损失函数不同:回归问题用平方误差损失函数、分类问题用指数损失函数等。可以说如果Adaboost中的基学习器是决策树桩,那么这时可以说提升数算法是Adaboost的一种特殊情况。 提升树与AdaBoost不同的地方在于:AdaBoost是训练出N个基学习器,然后加权叠加;提升数是基于 前向分步算法 ,即第一次训练出一个学习器,然后后面训练的学习器都是基于之前所有学习器叠加之后样本的误差(残差)来训练本次的学习器的。 可以说前向分步算法 是每迭代一次,模型的效果都会有提升;而Adaboost每次训练出来学习器可能都不尽人意,然后加权叠加之后,效果就非常好了。 这里仅仅给出回归问题中的提升树算法 :
输入: 训练集
T
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
…
,
(
x
n
,
y
n
)
}
T=\{(x_1, y_1), (x_2, y_2), …,(x_n, y_n)\}
T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x n , y n ) } 输出: 提升树
f
M
(
x
)
f_M(x)
f M ( x ) (1) 初始化
f
0
(
x
)
f_0(x)
f 0 ( x ) (2) 对m=1,2,…,M: a. 计算残差
r
m
i
=
y
i
−
f
m
−
1
(
x
i
)
r_{mi}=y_i - f_{m-1}(x_i)
r m i = y i − f m − 1 ( x i ) 【每轮迭代,求每个样本的残差】 b. 拟合残差
r
m
i
r_{mi}
r m i ,学习一个回归树
T
(
x
;
Θ
m
)
T(x;\Theta_m)
T ( x ; Θ m ) c. 更新
f
m
(
x
)
=
f
m
−
1
(
x
)
+
T
(
x
;
Θ
m
)
f_m(x) = f_{m-1}(x) + T(x;\Theta_m)
f m ( x ) = f m − 1 ( x ) + T ( x ; Θ m ) (3)输出最后的回归树
f
M
(
x
)
f_M(x)
f M ( x )
其实最后的回归树就是叠加所有残差的拟合结果:
f
M
(
x
)
=
∑
i
=
1
M
T
(
x
;
Θ
m
)
f_M(x) = \sum_{i=1}^{M}T(x;\Theta_m)
f M ( x ) = ∑ i = 1 M T ( x ; Θ m )
所以提升树就是:在前一个学习器的基础上,学习其残差,即拟合的不好的部分,然后再将这部分的结果叠加在原来的学习器上,原来拟合不好的部分,被这新增加的部分弥补了部分。所以每轮迭代,提升树的效果都会得到提升。
3. GBDT-梯度提升决策树(Gradient Boosting Decision Tree
在第二节的提升树中我们知道提升树通过拟合残差来提高模型的效果,因为提升树是利用加法模型和前向分步算法实现学习的优化过程。这对于损失函数是平方损失函数和指数损失函数来说是很简单的,但是对于一般的损失函数而言,优化往往没有那么容易。针对这个问题
3.1 GBDT 回归算法
Freidman 提出了梯度提升算法,利用最速下降法的近似方法,利用损失函数的负梯度来近似残差,其算法描述可以表示为:
输入: 训练集
T
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
…
,
(
x
n
,
y
n
)
}
T=\{(x_1, y_1), (x_2, y_2), …,(x_n, y_n)\}
T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x n , y n ) } 和损失函数
L
(
y
,
f
(
x
)
)
L(y, f(x))
L ( y , f ( x ) ) 输出: 强学习器f(x) (1). 初始化弱学习器$f_0(x) = \arg \min_{c} \sum_{i=1}^{m}L(y_i,c) $ (2). 每轮迭代t={1,2,…,T}有: a. 对每个样本i={1,2,…,m}计算负梯度:
r
t
i
=
−
[
∂
L
(
y
i
,
f
(
x
i
)
∂
f
(
x
i
)
]
f
(
x
)
=
f
t
−
1
(
x
)
r_{ti} = -[\frac{\partial L(y_i, f(x_i)}{\partial f(x_i)}]_{f(x) = f_{t-1}(x)}
r t i = − [ ∂ f ( x i ) ∂ L ( y i , f ( x i ) ] f ( x ) = f t − 1 ( x ) b. 利用
(
x
i
,
r
t
i
)
(x_i, r_{ti})
( x i , r t i ) (i=1,2,…,m),拟合一颗CART回归树,得到第t颗回归树,其对应的叶子节点区域为
R
t
j
R_{tj}
R t j (j=1,2,…,J),其中J为叶子节点的个数。 c. 求取叶子区域的最佳拟合值:
c
t
j
=
arg
min
c
∑
x
i
∈
R
t
j
L
(
y
i
,
f
t
−
1
(
x
)
+
c
)
c_{tj} = \arg \min_{c} \sum_{x_i ∈ R_{tj}}L(y_i, f_{t-1}(x)+c)
c t j = arg min c ∑ x i ∈ R t j L ( y i , f t − 1 ( x ) + c ) d. 更新树:
f
t
(
x
)
=
f
t
−
1
(
x
)
+
∑
j
=
1
J
I
(
x
∈
R
m
j
)
f_t(x) = f_{t-1}(x) + \sum_{j=1}^{J}I(x∈R_{mj})
f t ( x ) = f t − 1 ( x ) + ∑ j = 1 J I ( x ∈ R m j ) (3) 最后得到的强学习器为:
f
(
x
)
=
∑
t
=
1
T
∑
j
=
1
J
c
t
j
I
(
x
∈
R
t
j
)
f(x) = \sum_{t=1}^{T} \sum_{j=1}^{J}c_{tj}I(x∈R_{tj})
f ( x ) = ∑ t = 1 T ∑ j = 1 J c t j I ( x ∈ R t j )
最后的结果其实就是每轮训练的学习器结果的线性叠加。
3.2 GBDT分类算法
GBDT的分类算法从思想上和GBDT的回归算法没有区别,但是由于样本输出不是连续的值,而是离散的类别,导致我们无法直接从输出类别去拟合类别输出的误差。 为了解决这个问题,主要有两个方法,一个是用指数损失函数,此时GBDT退化为Adaboost算法。另一种方法是用类似于逻辑回归的对数似然损失函数的方法。也就是说,我们用的是类别的预测概率值和真实概率值的差来拟合损失。本文仅讨论用对数似然损失函数的GBDT分类。而对于对数似然损失函数,我们又有二元分类和多元分类的区别。 【对于二元分类算法: 】
用逻辑回归的对数似然损失函数为:
L
(
y
,
f
(
x
)
)
=
l
o
g
(
1
+
e
x
p
(
−
y
f
(
x
)
)
)
)
L(y, f(x)) = log(1+exp(-yf(x))))
L ( y , f ( x ) ) = l o g ( 1 + e x p ( − y f ( x ) ) ) ) ,其中
y
∈
{
−
1
,
1
}
y∈\{-1, 1\}
y ∈ { − 1 , 1 }
此时负梯度误差为:
r
t
i
=
−
[
∂
L
(
y
i
,
f
(
x
i
)
∂
f
(
x
i
)
]
f
(
x
)
=
f
t
−
1
(
x
)
=
y
i
1
+
e
x
p
(
y
i
f
(
x
i
)
)
r_{ti} = -[\frac{\partial L(y_i, f(x_i)}{\partial f(x_i)}]_{f(x) = f_{t-1}(x)}=\frac{y_i}{1+exp(y_if(x_i))}
r t i = − [ ∂ f ( x i ) ∂ L ( y i , f ( x i ) ] f ( x ) = f t − 1 ( x ) = 1 + e x p ( y i f ( x i ) ) y i
各个叶子节点的 最佳拟合值为:
c
t
j
=
arg
min
c
∑
x
i
∈
R
t
j
l
o
g
(
1
+
e
x
p
(
−
y
i
(
f
(
x
i
)
+
c
)
)
)
c_{tj}= \arg \min_{c} \sum_{x_i∈R_{tj}} log(1+exp(-y_i(f(x_i)+c)))
c t j = arg min c ∑ x i ∈ R t j l o g ( 1 + e x p ( − y i ( f ( x i ) + c ) ) ) ,上式比较难优化,于是使用近似值来代替:
c
t
j
=
∑
x
i
∈
R
t
j
r
t
i
/
∑
x
i
∈
R
t
j
∣
r
t
i
∣
(
1
−
∣
r
t
i
∣
)
c_{tj} = \sum_{x_i∈R_{tj}}r_{ti} / \sum_{x_i∈R_{tj}}|r_{ti}|(1-|r_{ti}|)
c t j = ∑ x i ∈ R t j r t i / ∑ x i ∈ R t j ∣ r t i ∣ ( 1 − ∣ r t i ∣ ) 除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,二元GBDT分类和GBDT回归算法过程相同。
【对于多元分类算法: 】
此时的对数似然损失函数:
L
(
y
,
f
(
x
)
)
=
−
∑
k
=
1
K
y
k
log
(
p
k
(
x
)
)
L(y, f(x)) = -\sum_{k=1}^{K}y_k \log(p_k(x))
L ( y , f ( x ) ) = − ∑ k = 1 K y k log ( p k ( x ) ) ;如果样本输出类别为k,则
y
k
=
1
y_k = 1
y k = 1 ,第k类的概率
p
k
(
x
)
=
e
x
p
(
f
k
(
x
)
)
/
∑
l
=
1
K
e
x
p
(
f
l
(
x
)
)
p_k(x) = exp(f_k(x)) / \sum_{l=1}^{K}exp(f_l(x))
p k ( x ) = e x p ( f k ( x ) ) / ∑ l = 1 K e x p ( f l ( x ) ) ,其中
f
k
(
x
)
f_k(x)
f k ( x ) 在初始化的时候一般为0;
计算出第t轮的第i个样本对应类别l的负梯度误差为:$r_{ti} = -[\frac{\partial L(y_i, f(x_i)}{\partial f(x_i)}]{f_k(x)=f {l,t-1}(x)} = y_{il}-p_{l,t-1}(x_i) $;其实这里的误差就是样本i对应类别l的真实概率和t−1轮预测概率的差值。
最佳拟合值为:
c
t
i
l
=
arg
min
c
∑
t
=
0
T
∑
k
=
1
K
L
(
y
k
,
f
t
−
1
,
l
(
x
)
+
∑
j
=
0
J
c
j
l
I
(
x
i
∈
R
t
j
)
)
c_{til}=\arg \min_{c} \sum_{t=0}^{T}\sum_{k=1}^{K}L(y_k, f_{t-1, l}(x) + \sum_{j=0}^{J}c_{jl}I(x_i∈R_{tj}))
c t i l = arg min c ∑ t = 0 T ∑ k = 1 K L ( y k , f t − 1 , l ( x ) + ∑ j = 0 J c j l I ( x i ∈ R t j ) ) ,这个式子不好优化,一般采用近似值:
c
t
j
l
=
K
−
1
K
∑
x
i
∈
R
t
j
l
r
t
i
l
∑
x
i
∈
R
t
i
l
∣
r
t
i
l
∣
(
1
−
∣
r
t
i
l
∣
)
c_{tjl} = \frac{K-1}{K}\frac{\sum_{x_i∈R_{tjl}}r_{til}}{\sum_{x_i∈R_{til}}|r_{til}|(1-|r_{til}|)}
c t j l = K K − 1 ∑ x i ∈ R t i l ∣ r t i l ∣ ( 1 − ∣ r t i l ∣ ) ∑ x i ∈ R t j l r t i l
GBDT主要的优点有:
可以灵活处理各种类型的数据,包括连续值和离散值。
在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。
3)使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数。
GBDT的主要缺点有:
1)由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。
参考资料:
梯度提升树(GBDT)原理小结
机器学习算法GBDT的面试要点总结-上篇