Adaboost提升树
一、bagging与boosting
bagging即套袋法,通过对训练样本重新采样的方法得到不同的训练样本集,在这些新的训练样本集上分别训练学习器,最终合并每一个学习器的结果,作为最终的学习结果。随机森林就是采用的该方法,不同树之间是相互独立的,每个树的权重都是一样的,这样可以是树可以并行的运行。
boosting算法与baging算法不同的是,学习器之间是存在先后顺序的,同时,二米一个样本都是有权重的,初始时,每一个样本的权重是相等的。首先第一个学习器对训练样本进行学习,当学习完成后,增大错误样本的权重,你可能会问,为什么要增大错误样本的权重,在分类问题中,错误的样本是算法未正确预测的结果,所以我们要增大错误样本的权重,才能在之后的预测中将之前预测错误的结果预测准确,就好比在人群中,你为什么可以一眼就认出了姚明,那是因为姚明在人群中的权重较大,,增大错误样本的权重的同时,要减小正确样本的权重,在利用第二个学习器对其进行学习,依次进行下去,最终得到b个学习器,最后合并这b个学习器的结果,同时与bagging中不同的是,每一个学习器的权重也是不一样的。在bossting中最重要的就是Adaboost和GBDT。
二、adaboost算法主要步骤
- 从训练集D中无放回的抽样方式随机抽取一个训练子集d1,用于弱学习机c1的训练
- 从训练集D中以无放回的方式随机抽取一个训练子集d2,并将c1中误分分类样本中的50%加入训练集中,训练得到若学习机c2
- 从训练集D中以无放回的方式随机的抽取c1,c2分类结果不一致的训练样本生成训练样本集d3,用d3来训练第三个弱学习机c3
- 通过多数投票来组合弱学习机c1,c2,c3
boosting与bagging模型相比,boosting可以同时降低偏差和方差,bagging只能降低模型的方差,在实际的应用中,boosting算法是存在明显的高方差问题,也就是过拟合。
a、以相同的初始值来初始化样本的权重,并且样本权重和为1
∑
i
=
1
n
w
i
=
1
\sum_{i=1}^nwi=1
i=1∑nwi=1
b、在m轮boosting操作中,对第j轮做如下操作
c、训练一个加权的弱学习机,
C
(
j
)
=
t
r
a
i
n
(
X
,
y
,
w
)
C(j) = train(X,y,w)
C(j)=train(X,y,w)
d、预测样本类表 pred_y = predict(C(j), X)
e、计算权重错误率:
ϵ
=
ω
∗
(
p
r
e
d
=
=
y
)
\epsilon=\omega*(pred == y)
ϵ=ω∗(pred==y)
f、计算相关系数
0.5
∗
l
o
g
(
1
−
ϵ
)
/
ϵ
=
a
j
0.5*log(1-\epsilon)/\epsilon = a_j
0.5∗log(1−ϵ)/ϵ=aj
g、更新权重
ϵ
∗
e
(
−
a
j
∗
y
∗
y
′
)
=
ϵ
\epsilon*e^{(-a_j*y*y')} = \epsilon
ϵ∗e(−aj∗y∗y′)=ϵ
h、归一化权重,并保证权重之和为1
ϵ
=
ϵ
/
∑
i
=
1
n
w
i
\epsilon = \epsilon/\sum_{i=1}^nw_i
ϵ=ϵ/i=1∑nwi
三、举个实例
import numpy as np
y = np.array([0, 1]*5) # [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
我们假设我们的原始数据是y,然后我们需要找到一个切割点,使我们预测的错误率最低,我们将预测值左边取值为0,将预测值右边取值为1,如果在第一第二个数之间进行预测,则预测结果为[0, 1, 1, 1, 1, 1,1, 1, 1, 1 ],则错误率为60.1,如果在第二个数与第三个数之间进行分割,那么预测的结果为[0, 0, 1, 1, 1, 1, 1, 1, 1, 1],错误率则为 50.1,我们找到一个错误率最低的分割点,在第七个与第八个数之间进行分割,预测值为[0, 0, 0, 0, 0, 0, 0, 1, 0, 1],错误率为0.1*3.
所以我们通过上面的结论进行推导,
错误率为
ϵ
=
0.3
\epsilon=0.3
ϵ=0.3,
相关系数为:
a
j
=
0.5
∗
l
o
g
(
1
−
ϵ
)
/
ϵ
=
0.5
∗
l
o
g
(
1
−
0.3
)
/
0.3
=
0.424
a_j = 0.5*log (1-\epsilon)/\epsilon = 0.5*log(1-0.3)/0.3 = 0.424
aj=0.5∗log(1−ϵ)/ϵ=0.5∗log(1−0.3)/0.3=0.424
单个样本预测错误则更新后的权重为:
ω
=
0.1
∗
e
(
−
0.424
∗
(
−
1
)
∗
1
)
=
0.153
\omega = 0.1*e^{(-0.424*(-1)*1)}=0.153
ω=0.1∗e(−0.424∗(−1)∗1)=0.153
单个样本预测正确则更新后的权重为:
ω
=
0.1
∗
e
(
−
0.424
∗
1
∗
1
)
=
0.066
\omega = 0.1*e^{(-0.424*1*1) }= 0.066
ω=0.1∗e(−0.424∗1∗1)=0.066
权重归一化:
∑
i
=
1
10
ω
i
=
7
∗
0.065
+
3
∗
0.153
=
0.914
\sum_{i=1}^{10}\omega _i = 7*0.065 + 3*0.153=0.914
i=1∑10ωi=7∗0.065+3∗0.153=0.914
预测正确的权重,归一化后的权重为:
0.066
/
0.914
=
0.072
0.066/0.914 = 0.072
0.066/0.914=0.072
预测错误的权重,归一化后的权重为:
0.153
/
0.914
=
0.167
0.153/0.914 = 0.167
0.153/0.914=0.167
通过一轮权重的更新可以发现,之前预测正确的权重由0.1变成了0.072,预测错误的权重由0.1变成了0.167,所以说,在权重更新的过程中,会增大预测错误的样本的权重,同时也会减少预测正确的权重。
四、利用Adaboost进行分析
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.ensemble import AdaBoostClassifier
from sklearn import tree
X = np.arrange(10).reshape(-1, 1)
y = np.array([1, 1, 1, -1, -1, -1,1, 1, 1, -1 ])
ada = AdaBoostClassifier(n_estimators=3)
ada.fit(X, y)
ada.estimators_ # 可以看到adaboost是由三个决策树组成的
plt.figure(figsize=(9, 6))
_ = tree.plot_tree(ada[0]) # 对第一棵树进行划分
y_ = ada[0].predict(X)
# 计算误差率
e1 = 0.1 * (y! = y_).sum()
# 计算第一颗树权重
# 随机森林中每颗树的权重是一样的,在adaboost中每棵树的权重是不一样的
a1 = np.round(1/2*np.log((1-e1)/e1), 4)
# 更新权重
w2 = 0.1*n.e**(-a1*y*y_)
# 归一化
w2 = w2/w2.sum()
# 得到第一个分类函数
f1(x) = a1*G1(x) = 0.4236G1(x)
# 进行第二轮迭代
plt.figure(figsize=(9, 6))
_ = tree.plot_tree(ada[1])
# 计算误差率, 3, 4, 5预测错误
e2 = 0.0714*3
a2 = 1/2*np.log((1-e2)/e2, 4)
# 计算权重
y_ = ada[1].predict(X)
w3 = w2*np.e**(-a2*y*y_)
w3 = w3/w3.sum()
w3.round(4)
# 计算第三棵树
plt.figure(figsize=(9, 6))
_ = tree.plot_tree(ada[2])
y_ = ada[2].predict(X)
e3 = (w3*(y != y_)).sum()
a3 = 1/2*np.log((1-e3)/e3)
# 计算权重
# 弱分类器合并为强分类器
# 加和
# sign 符号函数,如果大于0变为1,小于0变为-1
G(x) = sign[f3(x) = sign[0.4236G1(x) + 0.6496G2(x) + 0.7514G3(x)]]
# 集成树
ada.predict(X) # [1, 1, 1, -1, -1, -1, 1, 1, 1, -1]
'''
y_predict = a1*ada[0].predict(X) + a2*ada[1].predict(X) + a3*ada[2].predict(X)
np.sign(y_predict).astype(np.int)
[1, 1, 1, -1, -1, -1, 1, 1, 1, -1] # 结果与预测的完成一致
'''
s i g n ∑ i = 1 N a 1 ∗ G 1 ( x ) + a 2 ∗ G 2 ( x ) + … … + a n ∗ G n ( x ) sign\sum_{i=1}^N{a_1*G1(x) + a_2*G2(x) + ……+a_n*Gn(x)} signi=1∑Na1∗G1(x)+a2∗G2(x)+……+an∗Gn(x)
网上一直流传一张非常容易理解的图。
五、以上是adaboost二分类的问题,那如果多分类该怎么预测呢?
既然是多分类,首先要对样本进行理解,所谓的多分类就是样本集中不止两类样本,比如上面的样本有5类样本。每种颜色代表一类,同时也看到是非线性的,现在进行多分类时的处理办法一般都是将多分类转换为二分类问题,很简单,因为分类问题都会产生一个分类器,产生这个分类器靠的是训练样本,前面的二分类问题就是产生一个分类器,而多分类问题根据训练集产生的不是一个分类器,而是多个分类器。
那第一种方式就是将训练样本集中的某一类当成一类,其他的所有类当成另外一类,像上面的5类,我把最中间的一类当成是第一类,并重新赋予类标签为1,而把四周的四类都认为是第二类,并重新赋予类标签维-1,好了现在的问题是不是就是二分类问题了?是的。那二分类好办,用之前的任何一个算法处理即可。好了,这是把最中间的当成一类的情况下建立的一个分类器。同理,我们是不是也可以把四周任何一类自成一类,而把其他的统称为一类呀?当然可以,这样依次类推,我们共建立了几个分类器?像上面5类就建立了5个分类器吧,好了到了这我们该怎么划分测试集的样本属于哪一类了?注意测试集是假设不知道类标签的,那么来了一个测试样本,我把它依次输入到上述建立的5个分类器中,看看最终它属于哪一类的多,那它就属于哪一类了吧。比如假设一个测试样本本来是属于中间的(假设为第5类吧),那么先输入第五类自成一类的情况,这个时候发现它属于第五类,记录一下5,然后再输入左上角(假设为1类)自成一类的情况,那么发现这个样本时不属于1类的,而是属于2,3,4,5这几类合并在一起的一类中,那么它属于2,3,4,5中的谁呢?都有可能吧,那么我都记一下,此时记一下2,3,4,5。好了再到有上角,此时又可以记一下这个样本输入1,3,4,5.依次类推,最后把这5个分类器都走一遍,就记了好多1~5的标签吧,然后去统计他们的数量,比如这里统计1类,发现出现了3次,2,3,4都出现了3次,就5出现了5次,那么我们就有理由认为这个样本属于第五类,那么现在想想是不是就把多类问题解决了呢?而这个过程参考这位大神博客中的一张图表示就如下:
可以看到,其实黑实线本类是我们想要的理想分类面,而按照这种方式建立的分类面是带阴影部分的那个分类面,那阴影部分里面表示什么呢?我们想想,假设一个样本落在了阴影里面,比如我画的那个紫色的点,按照上面计算,发现它属于三角形一类的2次,属于正方形一类的2次,属于圆形一类的1次,那这个时候你怎么办?没招,只能在最大的两次中挑一个,运气好的认为属于三角形,挑对了,运气不好的挑了个正方形,分错了。所以阴影部分是属于模棱两可的情况,这个时候只能挑其中一个了。
这是第一种方式,那还有第二种分类方式,思想类似,也是转化为二分类问题,不过实现上不同。前面我们是挑一类自成一类,剩下的所有自成一类,而这里,也是从中挑一类自成一类,然剩下的并不是自成一类,而是在挑一类自成一类,也就是说从训练样本中挑其中的两类来产生一个分类器。像上述的5类,我先把1,2,类的训练样本挑出来,训练一个属于1,2,类的分类器,然后把1,3,挑出来训练一个分类器,再1,4再1,5再2,3,等等(注意2,1与1,2一样的,所以省去了),那这**样5类样本需要建立多少个分类器呢?n(n-1)/2吧,这里就是54/2=10个分类器,可以看到比上面的5个分类器多了5个。而且n越大,多的就越多。好了建立完分类器,剩下的问题同样采取投票机制,来一个样本,带到1,2建立的发现属于1,属于1类的累加器加一下,带到1,3建立的发现也属于1,在加一下,等等等等。最后看看5个类的累加器哪个最大就属于哪一类。那么一个问题来了,会不会出现像上面那种情况,有两个或者更多个累加器的值是一样的呢?答案是有的,但是这种情况下,出现一样的概率可比上述情况的概率小多了(比较是10个分类器来的结果,怎么也得比你5个的要好吧),同样一个示意图如下:
可以看到重叠部分就是中间那么一小块,相比上面那种方式小了不少吧。
那么细比较这两种方式,其实各有优缺点。第一种方式由于建立的分类器少(n越大越明显吧,两者相差(n(n-1)/2 - n)个分类器)。也就是在运算的时候速度更快,而第二种方式虽然速度慢,但是精度高呀,而且现在计算机的速度也够快了,可以弥补第二种方式的缺点,所以个人更倾向于第二种方式了。*
望您:
“情深不寿,强极则辱,谦谦君子,温润如玉”。