集成学习器的形式:
(sign(x)为符号函数,x>0输出1,x<0输出-1)
(为个体学习器,
表示该学习器的重要性)
Adaboost算法分析:
该算法其实是一个简单的弱分类算法提升过程,这个过程通过不断的训练,可以提高对数据的分类能 Adaboost
力。整个过程如下所示:
1. 先通过对N个训练样本的学习得到第一个弱分类器;
2. 将分错的样本和其他的新数据一起构成一个新的N个的训练样本,通过对这个样本的学习得到第二个弱分类器 ;
3. 将1和2都分错了的样本加上其他的新样本构成另一个新的N个的训练样本,通过对这个样本的学习得到第三个弱分类器;
4. 最终经过提升的强分类器 。即某个数据被分为哪一类要通过 , ……的多数表决。
下面直接通过例子去理解AdaBoost算法。(例子与解法来源于李航的《统计学习方法》)
例子:
假设个体学习器由x(输入)和y(输出)产生,其阈值v(判定正反例的分界线)使该分类器在训练数据集上分类误差率最低。(y=1为正例,y=-1为反例)
序号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
X | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
y | 1 | 1 | 1 | -1 | -1 | -1 | 1 | 1 | 1 | -1 |
第一个个体学习器:
第一个学习器,先认为每个x的权重一样,即 (i=1-10)。
D1:
X | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
w1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 | 0.1 |
y | 1 | 1 | 1 | -1 | -1 | -1 | 1 | 1 | 1 | -1 |
(a)对于n=1(即第一个学习器),在权值分布为D1(10个数据,每个数据的权值皆初始化为0.1)的训练数据上,经过计算可得
- 阈值v取2.5时误差率为0.3(x < 2.5时取1,x > 2.5时取-1,则6 7 8分错,误差率为0.3),
- 阈值v取5.5时误差率最低为0.4(x < 5.5时取1,x > 5.5时取-1,则3 4 5 6 7 8皆分错,误差率0.6大于0.5,不可取。故令x > 5.5时取1,x < 5.5时取-1,则0 1 2 9分错,误差率为0.4),
- 阈值v取8.5时误差率为0.3(x < 8.5时取1,x > 8.5时取-1,则3 4 5分错,误差率为0.3)。
因此选择2.5与8.5为阈值错误率均为0.3,故可取任意一个,根据代码取2.5为阈值。
此时分类器为
通过代码绘制出树:
import numpy as np
from sklearn.ensemble import AdaBoostClassifier
from sklearn import tree
X=np.arange(10).reshape(-1,1)
y=np.array([1,1,1,-1,-1,-1,1,1,1,-1])
ada=AdaBoostClassifier(n_estimators=3,algorithm='SAMME')
ada.fit(X,y)
plt.figure(figsize=(9,6))
_=tree.plot_tree(ada[0])
y_=ada[0].predict(X) #查看第一棵树的预测值
print(y_)
print(y)
>>> [ 1, 1, 1, -1, -1, -1, -1, -1, -1, -1]
>>> [ 1, 1, 1, -1, -1, -1, 1, 1, 1, -1]
(b)可以看到将6,7,8预测错误,此时误差e1=0.3,根据e1求:
, 则
。
(c)更新训练数据的权值分布
即此处为:,其中y为真实值
为预测值,w为权重。通过代码计算求得:
#更新的权重
w2=0.1*np.e**(-a1*y*y_)
w2
>>> [0.06546857, 0.06546857, 0.06546857, 0.06546857, 0.06546857, 0.06546857, 0.15274505, 0.15274505, 0.15274505, 0.06546857]
w2.sum()
>>> 0.9165151400883117
此处,和应该为1,则将权重重新分布,使其和为1。
w2=w2/w2.sum()
w2=np.round(w2,5)
w2
>>> [0.07143, 0.07143, 0.07143, 0.07143, 0.07143, 0.07143, 0.16666,0.16666, 0.16666, 0.07143]
D2:
X | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
w2 | 0.07143 | 0.07143 | 0.07143 | 0.07143 | 0.07143 | 0.07143 | 0.16666 | 0.16666 | 0.16666 | 0.07143 |
y | 1 | 1 | 1 | -1 | -1 | -1 | 1 | 1 | 1 | -1 |
可以看到x=6,7,8的数据的权重变大,而其他数据的权重降低这是希望能把之前经常分类错误的数据能在下一个个体学习器分类正确(经常分类错误会出现权重不断变大)。(权重是用来计算误差的,为了降低误差,选择阈值时会倾向把权重大的分类正确)此时 :
第二个个体学习器:
D2:
X | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
w2 | 0.07143 | 0.07143 | 0.07143 | 0.07143 | 0.07143 | 0.07143 | 0.16666 | 0.16666 | 0.16666 | 0.07143 |
y | 1 | 1 | 1 | -1 | -1 | -1 | 1 | 1 | 1 | -1 |
(a)在权值分布为D2的训练数据上,阈值取8.5时分类误差率最低,其中3,4,5被分错,错分为正例(即将-1分为1),误差e2为:0.07143*3=0.2143(3,4,5权重之和)。
此时分类器为:
同理画出树:
根据e2与公式:
根据,求出w3:
w3=w2*np.e**(-a2*y*y_1)
w3=w3/w3.sum()
w3=np.round(w3,4)
w3
>>> [0.0455, 0.0455, 0.0455, 0.1666, 0.1666, 0.1666, 0.1061, 0.1061,0.1061, 0.0455]
与D2对比,可以看到x=3,4,5的数据的权重变大了,而其他权重降低了。
此时
即此时:
第三个个体学习器:
D3:
X | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
w3 | 0.0455 | 0.0455 | 0.0455 | 0.1666 | 0.1666 | 0.1666 | 0.1061 | 0.1061 | 0.1061 | 0.0455 |
y | 1 | 1 | 1 | -1 | -1 | -1 | 1 | 1 | 1 | -1 |
在权值分布为D3的训练数据上,阈值取5.5时分类误差率最低,为e3=0.0455*4=0.1820,x=0,1,2,9被分类错误。
个体学习器为:
则更新训练数据的权值分布:
w4=w3*np.e**(-a3*y*y_2)
w4=np.round(w4/w4.sum(),4)
w4
>>> [0.125 , 0.125 , 0.125 , 0.1018, 0.1018, 0.1018, 0.0649, 0.0649, 0.0649, 0.125 ]
D4:
x | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
w4 | 0.125 | 0.125 | 0.125 | 0.1018 | 0.1018 | 0.1018 | 0.0649 | 0.0649 | 0.0649 | 0.125 |
y | 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)
y_predict
>>> [ 0.3218, 0.3218, 0.3218, -0.5254, -0.5254, -0.5254, 0.9774, 0.9774, 0.9774, -0.3218]
np.sign(y_predict)
>>> [ 1., 1., 1., -1., -1., -1., 1., 1., 1., -1.]
由此看出输出与y一致。