集成学习有两大类:bagging和boosting。随机森林是bagging的一个例子,而Adaboost是boosting的典型算法。
什么是boosting
bagging算法是由多个学习器组成的,但是学习器之间是
并
行
\color{#FF0000}{并行}
并行的,意思就是学习器之间互补干扰,各自训练各自的,各自测试各自的数据,然后通过整合每个学习器返回的数据最终得到结果。
整合的方式有很多种:
- 投票法,少数服从多数,比如:10个学习器,8个的结果是1,2个的结果是0,那么最终结果为1;
- 平均法,最终的结果求平均或者给每个学习器加个权重;
- 学习法,把每个学习器输出数据再学习一下得到最终结果,代表方法有stacking。
boosting也是有多个学习器组成,但是学习器之间是有
串
联
\color{#FF0000}{串联}
串联的。
举个例子,从一批数据中抽样70%,第一个学习器训练这70%,训练完之后测试这批数据,标记出错的样本,第二个学习器再重点训练这些第一个学习器出错的样本,训练完之后测试这批数据,再标记出错的样本,第三个学习器再重点训练第一个学习器和第二个学习器都出错的样本。最后利用集成学习整合这些数据,第一个学习器和第二个学习器输出一致时那就输出他们的结果,不一致时就输出第三个学习器的结果。这样误差率就大大下降了。
那么就刚刚的例子中,我们能够看到算法实现的时候需要
标
记
样
本
\color{#FF0000}{标记样本}
标记样本,并且最后需要
整
合
\color{#FF0000}{整合}
整合每个学习器的输出。
那接下来我们来看一下Adaboost是如何标记样本和整合输出的吧。
Adaboost算法
Adaboost具体实现如下图:
其中,
ϵ
t
\epsilon_t
ϵt是第
t
t
t个学习器的误差率,
α
t
\alpha_t
αt是第
t
t
t个学习器的更新权重系数
(
整
合
输
出
)
\color{#FF0000}{(整合输出)}
(整合输出),
D
t
(
i
)
D_t(i)
Dt(i)是第
t
t
t个学习器对第
i
i
i个样本的权重
(
标
记
样
本
)
\color{#FF0000}{(标记样本)}
(标记样本)。
Adaboost算法有很好地数学特性,就是说它的误差率的收敛,更新权重的系数都是可以通过数学推导出来的,那我们就来看一下是如何推导出来的吧,在推导之前先明确一下几个定义:
- h t ( x i ) h_t(x_i) ht(xi)是第 i i i个样本在第 t t t个学习器的输出;
- f ( x i ) = ∑ t = 1 T α t h t ( x i ) f(x_i)=\sum_{t=1}^T\alpha_th_t(x_i) f(xi)=∑t=1Tαtht(xi), T T T个学习器之后的输出,如果不加权重 α t \alpha_t αt,二分类最终输出结果相当于投票,这明显不可合理的,之前说过boost算法的学习器是串行的有针对性的(某个学习器它对某些样本的分类会准确些),所以引入了权重 α t \alpha_t αt,但是我们看到这个权重只和当前学习器的误差率有关,它也没用针对某个样本变化啊,这个就是Adaboost的局限性,RegionBoost算法会在这方面对其进行处理;
- H ( x i ) = s i g n ( f ( x i ) ) H(x_i)=sign(f(x_i)) H(xi)=sign(f(xi))是最后的输出结果;
- ϵ t = ∑ h t ( x i ) ≠ y i D t ( i ) \epsilon_t=\sum_{h_t(x_i)\neq y_i}D_t(i) ϵt=∑ht(xi)̸=yiDt(i),第 t ( t 不 等 于 T ) t(t不等于T) t(t不等于T)个学习器的误差率是误判样本的权重和。
ϵ t \epsilon_t ϵt, α t \alpha_t αt的推导
误差率当然越小越好,但是这个误差率和什么有关呢,我们不知道啊,但是仔细想想boost的原理,这个误差率会不会和
学
习
器
输
出
结
果
的
整
合
方
式
\color{#FF0000}{学习器输出结果的整合方式}
学习器输出结果的整合方式与
选
取
的
训
练
的
样
本
\color{#FF0000}{选取的训练的样本}
选取的训练的样本有关呢?在Adaboost中难道和参数
α
t
\alpha_t
αt和
D
t
(
i
)
D_t(i)
Dt(i)有关?算了,想那么多干嘛,先看看误差率长什么样吧!
误
差
率
ϵ
=
H
(
x
i
)
不
等
于
y
i
的
个
数
样
本
总
个
数
m
=
1
m
∑
i
=
1
m
[
​
[
H
(
x
i
)
̸
=
y
i
]
​
]
\begin{aligned} 误差率\epsilon&=\frac{H(x_i)不等于y_i的个数}{样本总个数m}\\ &=\frac{1}{m}\sum_{i=1}^m[\![H(x_i) \not= y_i]\!] \end{aligned}
误差率ϵ=样本总个数mH(xi)不等于yi的个数=m1i=1∑m[[H(xi)̸=yi]]
其中,
a
a
a成立,
[
​
[
a
]
​
]
=
1
[\![a]\!]=1
[[a]]=1,
a
a
a不成立,
[
​
[
a
]
​
]
=
0
[\![a]\!]=0
[[a]]=0。
这个误差率表达式好像不怎么好处理,能不能转化一下。
我们看一下下面的式子
[
​
[
H
(
x
i
)
̸
=
y
i
]
​
]
=
1
⇒
y
i
f
(
x
i
)
<
0
⇒
e
−
y
i
f
(
x
i
)
>
1
[
​
[
H
(
x
i
)
̸
=
y
i
]
​
]
=
0
⇒
y
i
f
(
x
i
)
>
0
⇒
e
−
y
i
f
(
x
i
)
>
0
[\![H(x_i) \not= y_i]\!]=1\Rightarrow y_if(x_i)<0\Rightarrow e^{-y_if(x_i)}>1\\ [\![H(x_i) \not= y_i]\!]=0\Rightarrow y_if(x_i)>0\Rightarrow e^{-y_if(x_i)}>0
[[H(xi)̸=yi]]=1⇒yif(xi)<0⇒e−yif(xi)>1[[H(xi)̸=yi]]=0⇒yif(xi)>0⇒e−yif(xi)>0
好像有点意思,那我们整理一下不就可以得到:
[
​
[
H
(
x
i
)
̸
=
y
i
]
​
]
≤
e
−
y
i
f
(
x
i
)
[\![H(x_i) \not= y_i]\!]\leq e^{-y_if(x_i)}
[[H(xi)̸=yi]]≤e−yif(xi)。那么
ϵ
≤
1
m
∑
i
=
1
m
e
−
y
i
f
(
x
i
)
\epsilon\leq \frac{1}{m}\sum_{i=1}^m e^{-y_if(x_i)}
ϵ≤m1∑i=1me−yif(xi),虽然误差率整理的好像有点样子了,但是接下来也不知道怎么处理,我们暂时放一下。刚刚猜测误差率和
D
t
(
i
)
D_t(i)
Dt(i)有关来着,我们先看看
D
t
(
i
)
D_t(i)
Dt(i)的表达吧!
D
t
D_t
Dt是样本的权重,我们一开始初始化
D
t
(
i
)
D_t(i)
Dt(i)为
1
m
\frac{1}{m}
m1,接下来通过不同学习器的学习训练,每个样本的权重都会变化,具体怎么变化呢?
- 当前学习器 t t t对于样本 x i x_i xi如果预测正确了,即 y i α t h t ( x i ) > 0 y_i\alpha_th_t(x_i)>0 yiαtht(xi)>0,那下一个学习器对这个样本的权重应该减小;
- 当前学习器 t t t对于样本 x i x_i xi如果预测错误了,即 y i α t h t ( x i ) < 0 y_i\alpha_th_t(x_i)<0 yiαtht(xi)<0,那下一个学习器对这个样本的权重应该增大。
综上,样本的权重为
D
t
(
i
)
e
−
y
i
f
(
x
i
)
D_t(i)e^{-y_if(x_i)}
Dt(i)e−yif(xi),但是考虑每个样本的权重和应该为1,需要将权重标准化,最终权重:
D
t
+
1
(
i
)
=
D
t
(
i
)
e
−
y
i
α
t
h
t
(
x
i
)
Z
t
D_{t+1}(i)=D_t(i)\frac{e^{-y_i\alpha_th_t(x_i)}}{Z_t}
Dt+1(i)=Dt(i)Zte−yiαtht(xi),其中,
Z
t
=
∑
i
D
t
(
i
)
e
−
y
i
α
t
h
t
(
x
i
)
Z_t=\sum_i D_t(i)e^{-y_i\alpha_th_t(x_i)}
Zt=∑iDt(i)e−yiαtht(xi)。
最后求解,
D
T
+
1
(
i
)
=
D
1
(
i
)
∏
t
=
1
T
e
−
y
i
α
t
h
t
(
x
i
)
Z
t
=
1
m
e
−
y
i
f
(
x
i
)
∏
t
=
1
T
Z
t
\begin{aligned} D_{T+1}(i)&=D_1(i)\prod_{t=1}^T\frac{e^{-y_i\alpha_th_t(x_i)}}{Z_t}\\ &=\frac{1}{m}\frac{e^{-y_if(x_i)}}{\prod_{t=1}^TZ_t} \end{aligned}
DT+1(i)=D1(i)t=1∏TZte−yiαtht(xi)=m1∏t=1TZte−yif(xi)
不知不觉出现了
e
−
y
i
f
(
x
i
)
e^{-y_if(x_i)}
e−yif(xi),且
e
−
y
i
f
(
x
i
)
=
m
D
T
+
1
(
i
)
∏
t
=
1
T
Z
t
e^{-y_if(x_i)}=mD_{T+1}(i)\prod_{t=1}^TZ_t
e−yif(xi)=mDT+1(i)∏t=1TZt,那么代入上面误差率的公式中,
ϵ
≤
∑
i
=
1
m
D
T
+
1
(
i
)
∏
t
=
1
T
Z
t
=
∏
t
=
1
T
Z
t
\begin{aligned} \epsilon&\leq\sum_{i=1}^mD_{T+1}(i)\prod_{t=1}^TZ_t\\ &=\prod_{t=1}^TZ_t \end{aligned}
ϵ≤i=1∑mDT+1(i)t=1∏TZt=t=1∏TZt
误差率出现了上界,仔细观察这个上界,里面的
Z
t
Z_t
Zt好像和参数
D
t
(
i
)
,
α
t
D_t(i),\alpha_t
Dt(i),αt有关耶,是不是和我们一开始的猜想一样。我们的目标是最小化误差率,可最小化
∏
\prod
∏有点困难,我们退而求其次,即求解
min
Z
t
\min Z_t
minZt。
那么我们先处理一下
Z
t
Z_t
Zt,观察
y
i
h
t
(
i
)
y_ih_t(i)
yiht(i)这项的值不是1就是-1,那么就好办了。
Z
t
=
∑
i
D
t
(
i
)
e
−
y
i
α
t
h
t
(
x
i
)
=
∑
y
i
≠
h
t
(
x
i
)
D
t
(
i
)
e
α
t
+
∑
y
i
=
h
t
(
x
i
)
D
t
(
i
)
e
−
α
t
=
e
α
t
ϵ
t
+
e
−
α
t
(
1
−
ϵ
t
)
\begin{aligned} Z_t&=\sum_i D_t(i)e^{-y_i\alpha_th_t(x_i)}\\ &=\sum_{y_i\neq h_t(x_i)}D_t(i)e^{\alpha_t}+\sum_{y_i=h_t(x_i)}D_t(i)e^{-\alpha_t}\\ &=e^{\alpha_t}\epsilon_t+e^{-\alpha_t}\left(1-\epsilon_t\right) \end{aligned}
Zt=i∑Dt(i)e−yiαtht(xi)=yi̸=ht(xi)∑Dt(i)eαt+yi=ht(xi)∑Dt(i)e−αt=eαtϵt+e−αt(1−ϵt)
那么
Z
t
Z_t
Zt对
α
t
\alpha_t
αt求导,领导数等于0,得
α
t
=
1
2
ln
1
−
ϵ
t
ϵ
t
\alpha_t=\frac{1}{2}\ln\frac{1-\epsilon_t}{\epsilon_t}
αt=21lnϵt1−ϵt。
我们这边看一下,权重更新之后对当前学习器的误差率有什么影响,那我们就要计算
ϵ
t
∗
=
∑
h
t
(
x
i
)
≠
y
i
D
t
+
1
(
i
)
\epsilon_t^*=\sum_{h_t(x_i)\neq y_i}D_{t+1}(i)
ϵt∗=∑ht(xi)̸=yiDt+1(i),
ϵ
t
∗
=
∑
h
t
(
x
i
)
≠
y
i
D
t
+
1
(
i
)
=
∑
h
t
(
x
i
)
≠
y
i
D
t
(
i
)
e
−
y
i
α
t
h
t
(
x
i
)
Z
t
=
∑
h
t
(
x
i
)
≠
y
i
D
t
(
i
)
e
α
t
∑
h
t
(
x
i
)
≠
y
i
D
t
(
i
)
e
α
t
+
∑
h
t
(
x
i
)
=
y
i
D
t
(
i
)
e
−
α
t
=
ϵ
t
e
α
t
ϵ
t
e
α
t
+
(
1
−
ϵ
t
)
e
−
α
t
,
α
t
=
1
2
ln
1
−
ϵ
t
ϵ
t
=
0.5
\begin{aligned} \epsilon_t^*&=\sum_{h_t(x_i)\neq y_i}D_{t+1}(i)\\ &=\frac{\sum_{h_t(x_i)\neq y_i}D_t(i)e^{-y_i\alpha_th_t(x_i)}}{Z_t}\\ &=\frac{\sum_{h_t(x_i)\neq y_i}D_t(i)e^{\alpha_t}}{\sum_{h_t(x_i)\neq y_i}D_t(i)e^{\alpha_t}+\sum_{h_t(x_i)=y_i}D_t(i)e^{-\alpha_t}}\\ &=\frac{\epsilon_te^{\alpha_t}}{\epsilon_te^{\alpha_t}+(1-\epsilon_t)e^{-\alpha_t}},\alpha_t=\frac{1}{2}\ln\frac{1-\epsilon_t}{\epsilon_t}\\ &=0.5 \end{aligned}
ϵt∗=ht(xi)̸=yi∑Dt+1(i)=Zt∑ht(xi)̸=yiDt(i)e−yiαtht(xi)=∑ht(xi)̸=yiDt(i)eαt+∑ht(xi)=yiDt(i)e−αt∑ht(xi)̸=yiDt(i)eαt=ϵteαt+(1−ϵt)e−αtϵteαt,αt=21lnϵt1−ϵt=0.5
结果是0.5,对于误差率来说应该是最坏的结果了(大于0.5的只要输出翻转一下就小于0.5了),那意思就是当前学习器训练完,
权
重
会
调
整
到
使
当
前
学
习
器
效
果
最
差
的
状
态
\color{#FF0000}{权重会调整到使当前学习器效果最差的状态}
权重会调整到使当前学习器效果最差的状态,然后再给下一个学习器训练,这是Adaboost一个重要的思想!
到这里,Adaboost算法里面公式的推导结束了,那接下来我们使用刚刚推导的结果看一下最终的误差率吧。
误差率上界
将
α
t
=
1
2
ln
1
−
ϵ
t
ϵ
t
\alpha_t=\frac{1}{2}\ln\frac{1-\epsilon_t}{\epsilon_t}
αt=21lnϵt1−ϵt代入
Z
t
Z_t
Zt得
Z
t
=
∑
i
D
t
(
i
)
e
−
1
2
y
i
h
t
(
x
i
)
ln
1
−
ϵ
t
ϵ
t
=
∑
i
D
t
(
i
)
[
1
−
ϵ
t
ϵ
t
Pr
(
y
i
≠
h
t
(
i
)
)
+
ϵ
t
1
−
ϵ
t
Pr
(
y
i
=
h
t
(
i
)
)
]
=
2
∑
i
D
t
(
i
)
ϵ
t
(
1
−
ϵ
t
)
=
2
ϵ
t
(
1
−
ϵ
t
)
\begin{aligned} Z_t&=\sum_iD_t(i)e^{-\frac{1}{2}y_ih_t(x_i)\ln\frac{1-\epsilon_t}{\epsilon_t}}\\ &=\sum_iD_t(i)\left[\sqrt{\frac{1-\epsilon_t}{\epsilon_t}}\Pr(y_i\neq h_t(i))+\sqrt{\frac{\epsilon_t}{1-\epsilon_t}}\Pr(y_i= h_t(i))\right]\\ &=2\sum_iD_t(i)\sqrt{\epsilon_t(1-\epsilon_t)}\\ &=2\sqrt{\epsilon_t(1-\epsilon_t)} \end{aligned}
Zt=i∑Dt(i)e−21yiht(xi)lnϵt1−ϵt=i∑Dt(i)[ϵt1−ϵtPr(yi̸=ht(i))+1−ϵtϵtPr(yi=ht(i))]=2i∑Dt(i)ϵt(1−ϵt)=2ϵt(1−ϵt)
令
ϵ
t
=
1
−
r
t
2
\epsilon_t=\frac{1-r_t}{2}
ϵt=21−rt,在上面的算法中,我们可以看到
ϵ
t
>
0.5
\epsilon_t>0.5
ϵt>0.5,所以这边的
r
t
∈
(
0
,
1
)
r_t\in(0,1)
rt∈(0,1)。
上式
2
ϵ
t
(
1
−
ϵ
t
)
=
1
−
r
t
2
,
r
t
∈
(
0
,
1
)
2\sqrt{\epsilon_t(1-\epsilon_t)}=\sqrt{1-r_t^2},r_t\in(0,1)
2ϵt(1−ϵt)=1−rt2,rt∈(0,1)
所以最终的误差率
ϵ
≤
∏
t
Z
t
=
∏
t
1
−
r
t
2
,
r
t
∈
(
0
,
1
)
\epsilon\leq\prod_tZ_t=\prod_t\sqrt{1-r_t^2},r_t\in(0,1)
ϵ≤∏tZt=∏t1−rt2,rt∈(0,1),可以看出误差率上界是
T
T
T个小于1的数相乘,明显是趋于0的。
附简单的程序:
from sklearn.datasets import make_gaussian_quantiles
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
import numpy as np
import matplotlib.pyplot as plt
X1, y1 = make_gaussian_quantiles(cov=2., n_samples=200, n_features=2, n_classes=2, random_state=1)
X2, y2 = make_gaussian_quantiles((3, 3), cov=1.5, n_samples=300, n_features=2, n_classes=2, random_state=1)
X = np.concatenate((X1, X2))
y = np.concatenate((y1, -y2+1))
plt.scatter(X[:,0], X[:,1], marker='o', c=y)
bdt = AdaBoostClassifier(DecisionTreeClassifier(
max_depth=2
, min_samples_split=20
, min_samples_leaf=5
)
, algorithm='SAMME'
, n_estimators=200
, learning_rate=1
)
bdt.fit(X, y)
bdt.score(X, y)
附初音程序
import pandas as pd
import numpy as np
from PIL import Image
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
miku = pd.read_csv(r'miku.csv')
miku = np.array(miku.values)
# print(miku.shape)
# miku_grayscale = miku[:, 2]
# miku_grayscale = miku_grayscale.reshape((500, 500))
# miku_grayscale = miku_grayscale.transpose()
# image = Image.fromarray(miku_grayscale*255)
# image.show()
miku_data = miku[:, 0:2]
miku_target = miku[:, 2]
# n_estimators参数为上文讲到的T,修改参数看效果。
clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=5), n_estimators=50)
clf.fit(miku_data, miku_target)
predict = clf.predict(miku_data)
predict = predict.reshape((500, 500))
predict = predict.transpose()
image = Image.fromarray(predict*255)
image.show()
AdaBoost补充
https://blog.csdn.net/zhisuihen6347/article/details/100582880