一、原理的描述
Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。其算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。使用adaboost分类器可以排除一些不必要的训练数据特徵,并将关键放在关键的训练数据上面。
- 三个臭皮匠,赛过诸葛亮
- 参考文章一
- 参考文章二
- 1.用大量的病例 == X == 样本让这些新手 == model依次学习,每个大夫 == model == 算法自己琢磨怎样诊断,学习结束后统计一下每个人在这些病例上的诊断准确率
2.训练时,前面的大夫误诊的病例,后面的大夫要重点学习研究 == 样本权重加大 == w,所谓查缺补漏
3.训练结束之后,给每个大夫打分,如果一个大夫对病例学习的误诊率越低,也就是说在这些学习的病例集上诊断的准确率越高,这名大夫在后面诊断病人时的话语权就越大 == 权重大 == 偏大 - 诊断过程
- 一个病人之后,8个大夫一起诊断,然后投票。如果一个大夫之前在学习时的诊断准确率为p,误差率e = 1-p,他在投票时的话语权是:
- [图片上传失败...(image-81730-1586219732552)]
- 赵大夫的结果 == 模型预测值
- Adabooting概述
- AdaBoost算法是一种集成学习(ensemble learning)方法。集成学习是机器学习中的一类方法,它对多个机器学习模型进行组合形成一个精度更高的模型就是强学习器,参与组合的模型称为弱学习器(weak learner)。在预测时使用这些弱学习器模型联合起来进行预测;训练时需要用训练样本集依次训练出这些弱学习器。典型的集成学习算法是随机森林和boosting算法,而AdaBoost算法是boosting算法的一种实现版本。
- ,其中是第t个模型的权重,第t个弱学习器的预测
- 分类是判定规则:
- sgn(F(x))表示F(x) 大于0结果正的,如果F(x)小于0,结果就是负的(算法原理基于二分类)
- 算法梳理:
- 训练弱学习器,计算误差率e,可以计算准确率p ,p + e = 1
- 弱学习器的权重
- 没有进行归一化
- 归一化
- Adaboosting中的A是adaptive的意思,所以AdaBoosting表示自适应增强算法
二、主要解决的问题
(1) 二分类,多类单标签问题、多类多标签问题、大类单标签问题
(2)回归问题
三、整体的流程:
- 先通过对N个训练样本的学习得到第一个弱分类器 ;
- 将 分错的样本和其他的新数据一起构成一个新的N个的训练样本,通过对这个样本的学习得到第二个弱分类器 ;
- 将 和 都分错了的样本加上其他的新样本构成另一个新的N个的训练样本,通过对这个样本的学习得到第三个弱分类器 ;
- 最终经过提升的强分类器 。即某个数据被分为哪一类要通过 , ……的多数表决。
注意:每一次都会更新样本的权重(数据的划分正确,降低该样本的权重,数据划分错误就增大它的权重)---》计算该弱分类器的误差率--》更新公式---》再根据公式更新下一轮的样本的权重。
通过以上的操作----经过T次的循环。就得到了最终想要的强分类器。
具体的公式及详细说明如下:
每次迭代都是选择相同的模型,上面的ht(x)表示的是弱学习器,前面的αt表示的是该弱学习器的权重。
多个弱学习器经过多次的迭代,最终得到的就是强学习器H(x)。
其中:sign代表的是符号函数
其最终返回的是那种分类
四、adaboosting简单的算法案例
```python
from sklearn.ensemble import AdaBoostClassifier
import numpy as np
from sklearn import tree
生成数据
X = np.arange(10).reshape(-1,1)
y = np.array([1,1,1,-1,-1,-1,1,1,1,-1])
y
array([ 1, 1, 1, -1, -1, -1, 1, 1, 1, -1])
声明算法,进行训练
# {'SAMME', 'SAMME.R'}
ada = AdaBoostClassifier(algorithm='SAMME',n_estimators=3)
ada.fit(X,y)
AdaBoostClassifier(algorithm='SAMME', base_estimator=None, learning_rate=1.0,
n_estimators=3, random_state=None)
第一棵树划分
y# 4个1 ----> 比例0.4,6个-1 ----> 比例 0.6 gini = 0.4*(1-0.4) + 0.6*(1-0.6) = 0.48
array([ 1, 1, 1, -1, -1, -1, 1, 1, 1, -1])
_ = tree.plot_tree(ada[0])
ada[0].predict(X)#第一棵树的预测值,怎么预测呢?
array([ 1, 1, 1, -1, -1, -1, -1, -1, -1, -1])
第一棵树,手动计算,划分
# 样本的初始权重,还没有开始进行训练,所以,所有样本权重一样?
w1 = np.full(shape = 10,fill_value=0.1)
w1
array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
X # 样本中10个数据,划分,0到1之间(threshold阈值0.5)划分;1到2之间(1.5)划分……
# X <= threshold 类别1 阳性 说明不好
# X > threshold 类别-1 阴性 说明健康
array([[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]])
# numpy中的最基本逻辑运算
# 数据分析的三剑客:numpy、pandas、matplotlib
c = y != y1#算数计算的时候,False = 0,True = 1
print(c)
print(c.astype(np.int8))
# 之前讲分类算法,模型评估,使用准确率
# accuracy = (y == y_).mean()
[False True True False False False True True True False]
[0 1 1 0 0 0 1 1 1 0]
# 如果阈值0.5,构建树,结果:
y1 = np.array([1,-1,-1,-1,-1,-1,-1,-1,-1,-1]) #预测结果
e1 = ((y != y1)*d1).sum()#误差
print('方式一',e1)
e1 = (y != y1).mean()
print('方式二',e1)
# 如果阈值1.5,构建树,结果:
y2 = np.array([1,1,-1,-1,-1,-1,-1,-1,-1,-1])
e2 = ((y != y2)*d1).sum()
print('方式一',e2)
e2 = (y != y2).mean()
print('方式二',e2)
方式一 0.5
方式二 0.5
方式一 0.4
方式二 0.4
# 第一颗树划分时,阈值选择了2.5?
# 决策树的裂分,有一个标准!
# for 循环目的:找到分类条件:2.5或者8.5
thresholds = np.arange(0.5,10)
for i,t in enumerate(thresholds,start = 1):#enumerate,获取索引,默认从0开始,
# y_是弱分类器,预测值
y_ = np.array([1]*i + [-1]*(10-i))
# y_ = np.zeros(shape = 10)
# y_[(X <=t).reshape(-1)] = 1
# y_[(X > t).ravel()] = -1
print(t,((y !=y_)*w1).sum())
0.5 0.5
1.5 0.4
2.5 0.30000000000000004
3.5 0.4
4.5 0.5
5.5 0.6
6.5 0.5
7.5 0.4
8.5 0.30000000000000004
9.5 0.4
根据输出的结果,结论,阈值是2.5或者8.5,误差最小的:0.3
选择2.5或者8.5作为裂分条件,代码中一般选择,前面的索引
# 计算第一个弱学习器的权重,相当于大夫的话语权
e1 = 0.3
a1 = 1/2*np.log((1 -e1)/e1 )
print('计算第一个弱学习器的权重:',a1)
计算第一个弱学习器的权重: 0.42364893019360184
更新样本的权重
# 在w1的基础上,进行更新 w1 = [0.1,0.1,0.1……]
y_ = np.array([1]*3 + [-1]*(10-3))
w2 = w1*np.exp(-y*y_*a1)
w2 = w2/w2.sum()
print(w2)
[0.07142857 0.07142857 0.07142857 0.07142857 0.07142857 0.07142857
0.16666667 0.16666667 0.16666667 0.07142857]
第二棵树划分
_ = tree.plot_tree(ada[1])#样本权重,发生变化了
手动计算,第二棵树的划分
第二棵树,根据第一棵树的返回结果,进行,学习
第一棵树,更新了样本的权重!w2
thresholds = np.arange(0.5,10)
for i,t in enumerate(thresholds,start = 1):#enumerate,获取索引,默认从0开始,
# y_是弱分类器,预测值
y_ = np.array([1]*i + [-1]*(10-i))
# y_ = np.zeros(shape = 10)
# y_[(X <=t).reshape(-1)] = 1
# y_[(X > t).ravel()] = -1
print(t,((y !=y_)*w2).sum())
0.5 0.6428571428571428
1.5 0.5714285714285714
2.5 0.5
3.5 0.5714285714285714
4.5 0.6428571428571428
5.5 0.7142857142857142
6.5 0.5476190476190476
7.5 0.38095238095238093
8.5 0.21428571428571425
9.5 0.28571428571428564
# 阈值,如果是8.5,那么左边9个数,右边是1个数,计算误差率
y_ = np.array([1]*9 + [-1]*(10-9))#预测值
display(y,y_)
e2 = ((y != y_)*w2).sum()
print('第二棵树的误差率:',e2)
print('样本的权重是:',w2.round(4))
#计算第二棵树的权重
a2 =np.round( 1/2*np.log((1 - e2)/e2),4)
print('第二棵树,权重是:',a2)
array([ 1, 1, 1, -1, -1, -1, 1, 1, 1, -1])
array([ 1, 1, 1, 1, 1, 1, 1, 1, 1, -1])
第二棵树的误差率: 0.21428571428571425
样本的权重是: [0.0714 0.0714 0.0714 0.0714 0.0714 0.0714 0.1667 0.1667 0.1667 0.0714]
第二棵树,权重是: 0.6496
更新第二棵树的样本的权值分布,根据第一棵树的结果w2进行更新
y_ = np.array([1]*9 + [-1]*(10-9))#预测值
w3 = w2*np.exp(-y*y_*a2)
w3 = w3/w3.sum()
print('第二棵树,更新样本权重,更新样本分布:',w3)
第二棵树,更新样本权重,更新样本分布: [0.04545643 0.04545643 0.04545643 0.16665975 0.16665975 0.16665975
0.10606501 0.10606501 0.10606501 0.04545643]
第三棵树划分
_ = tree.plot_tree(ada[2])
thresholds = np.arange(0.5,10)
for i,t in enumerate(thresholds,start = 1):#enumerate,获取索引,默认从0开始,
# y_是弱分类器,预测值
y_ = np.array([1]*i + [-1]*(10-i))
# y_ = np.zeros(shape = 10)
# y_[(X <=t).reshape(-1)] = 1
# y_[(X > t).ravel()] = -1
print(t,((y !=y_)*w3).sum())#误差率 + 准确率 = 1
0.5 0.40910788311754365
1.5 0.36365145166003876
2.5 0.318195020202534
3.5 0.4848547715250161
4.5 0.6515145228474983
5.5 0.8181742741699806
6.5 0.7121092674358026
7.5 0.6060442607016245
8.5 0.4999792539674466
9.5 0.5454356854249515
e3 = 0.1820
# 计算第三棵树的权重
y_ = np.array([-1]*6 + [1]*(10-6))
a3 = 1/2*np.log((1 - e3)/e3)
print('第三棵树的权重是:',a3)
# 更新第三棵树的,样本权值分布,权重
w4 = w3*np.exp(-y*y_*a3)
w4 = w4/w4.sum()
print('第三棵树,更新样本权重:',w4.round(3))
第三棵树的权重是: 0.7514278247629759
第三棵树,更新样本权重: [0.125 0.125 0.125 0.102 0.102 0.102 0.065 0.065 0.065 0.125]
集成算法
print(a1,a2,a3)
0.42364893019360184 0.6496 0.7514278247629759
# 第一棵树ft(x)
y1 = np.array([1]*3 + [-1]*(10-3))
# 第二棵树的预测值
y2 = np.array([1]*9 + [-1]*(10-9))#预测值
# 第三棵树,预测值
y3 = np.array([-1]*6 + [1]*(10-6))
F = a1*y1 + a2*y2 + a3*y3
# 将多个弱分类器,整合,变成了强分类器F(X)
F
array([ 0.32182111, 0.32182111, 0.32182111, -0.52547675, -0.52547675,
-0.52547675, 0.97737889, 0.97737889, 0.97737889, -0.32182111])
# 上面的result使我们手动计算的。
result = [-1 if i <0 else 1 for i in F]
result
[1, 1, 1, -1, -1, -1, 1, 1, 1, -1]
# 这个模型预测的返回值
ada.predict(X)
array([ 1, 1, 1, -1, -1, -1, 1, 1, 1, -1])
# 类别 0,1,2目标值有3个类别
y = np.array([1,1,2,0])
# 二进制编码,3个数的二进制,刚好可以表示,3个类别,one-hot:独热编码
y_ = np.array([[0,1,0],
[0,1,0],
[0,0,1],
[1,0,0]])
********
**以上部分内容参考自博客**[https://blog.csdn.net/ben_ben_niao/article/details/47277035](https://blog.csdn.net/ben_ben_niao/article/details/47277035)