本文源自微信公众号【Python编程和深度学习】原文链接:[机器学习系列(六)Adaboost](https://mp.weixin.qq.com/s?__biz=MzUxNTY1MjMxNQ==&mid=2247484534&idx=1&sn=6c2a2bfd20b20fe21b5982c241e45d70&chksm=f9b22bc2cec5a2d4626d3b6acfa616347be9863b8fcbadf53761b58bd7eee96168e5ebda325b&token=1098865241&lang=zh_CN#rd),欢迎扫码关注鸭!

前面我们已经介绍了几种不同的分类器,每种分类器都各有优缺点,我们可以借助集成学习的方法将不同的分类器组合起来,将多个弱可学习分类器集成组合成一个强可学习分类器。
集成方法有几种形式:
1) **不同算法**的集成
2) 相同算法的**不同设置**的集成
3) **不同分类器**处理**不同数据集部分**的集成
集成方法主要包括Bagging和Boosting两种方法。
# 目录
[一、Bagging方法:](#1)<br>
[二、Boosting方法:](#2)<br>
[三、Bagging和Boosting的区别](#3)<br>
[四、AdaBoost基本原理介绍](#4)<br>
[五、AdaBoost优点和缺点](#5)<br>
[六、Python代码](#6)<br>
<div id="1"></div>
##一、Bagging方法:
自举汇聚法(bootstap aggregating),通过对训练数据进行**有放回的采样**(自举采样bootstap sampling),弱学习器之间没有依赖关系。
算法步骤:
1) 在训练数据集中采用自举采样方法提取n个训练样本,经过k次提取之后得到k个训练集,每个训练集中有n个样本,由于是有放回的采样,所以有的样本会被多次取到,有的样本可能从来没有被取到;
2) K个训练集经过弱学习器得到k个学习模型;
3) 对k个模型的预测结果采用投票的方式得到最终的分类结果,如果是回归模型,可以取平均值或加权平均值。
Bagging方法最流行的是**随机森林**(random forest),是由Bagging方法和决策树结合。
<div id="2"></div>
##二、Boosting方法:
Boosting方法的思想是采用**重赋权**(re-weighting)法迭代地训练弱学习器。
算法步骤:
1) 首先给每个样本赋予一个初始权重值1/m,m为样本数量;
2) 开始训练第一个弱学习器,根据该弱学习器的错误率更新权重,给错误率高的训练样本的权重值变高,在下一次学习中得到更多重视;
3) 依次训练之后多每个弱学习器,并不断迭代更新权重;
4) 对最终的k个弱学习器结果进行整合。
Boosting方法最流行的是**Adaboost**。
<div id="3"></div>
##三、Bagging和Boosting的区别
1)样本选择:
Bagging:每次训练的数据集是有放回选取的,它们之间是相互独立的。
Boosting:每次训练的的数据集不变,但每个样例在学习器中的权重发生变化。而权值是根据上一轮的学习结果进行更新。
2)样本权重:
Bagging:使用均匀取样,每个样本的权重相同。
Boosting:每个样本的权重不同,根据错误率不断调整样本的权值,错误率越高则权重越大。
3)预测结果权重:
Bagging:所有预测结果的权重相等。
Boosting:每个弱学习器都有不同的权重,对于分类误差小的分类器会有更大的权重。
4)计算方式:
Bagging:各个学习器可以并行生成,互不影响。
Boosting:各个学习器只能顺序生成,因为后一个模型参数需要基于前一轮模型的结果进行调整。
<div id="4"></div>
##四、AdaBoost基本原理介绍
AdaBoost(Adaptive boosting)是基于Boosting思想的迭代算法,输入样本为
$$
\chi=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right), \ldots,\left(x_{n}, y_{n}\right)\right\}
$$
详细的算法描述如下:
1.初始化所有训练数据的权重分布:
$$
D_{1}=\left(w_{11}, \ldots, w_{1 i}, \ldots, w_{1 N}\right), \quad w_{1 i}=1 / N, \quad i=1,2, \ldots, N
$$
2.迭代训练弱学习器,并不断更新权重,第m个弱学习器的样本权重为$ {D}_m$,输出值为{-1,1},计算弱分类器在训练集上的分类错误率,值越小其在最终分类器的作用越大。
* 2.1$$
e_{m}=P\left(G_{m}\left(x_{i}\right) \neq y_{i}\right)=\sum_{i=1}^{N} w_{m i}I\left(G_{m}\left(x_{i}\right) \neq y_{i}\right)
$$
$I\left(G_{m}\left(x_{i}\right) \neq y_{i}\right)
$的取值为0时表示分类正确,取值为1表示分类错误。
* 2.2计算弱学习器的权重系数,当错误率降低的时候权重系数会增大,错误率越小,对最终的预测影响就越大。
$$
\alpha_{m}=\frac{1}{2} \ln \frac{1-e_{m}}{e_{m}}
$$
* 2.3更新训练数据集的样本权重
$$
\begin{array}{c}
D_{m+1}=\left(w_{m+1,1}, w_{m+1,2} \cdots w_{m+1, i} \cdots, w_{m+1, N}\right), \\
w_{m+1, i}=\frac{w_{m i}}{Z_{m}} \exp \left(-\alpha_{m} y_{i} G_{m}\left(x_{i}\right)\right), i=1,2, \cdots, N \\
Z_{m}=\sum_{i=1}^{N} w_{m i} \exp \left(-\alpha_{m} y_{i} G_{m}\left(x_{i}\right)\right)
\end{array}
$$
式中,${Z}_m$是规范化因子,将${w}_{m i}$的值规范化到0-1之间,使得$\sum_{i=1}^{N} w_{m i}=1$
。对于二分类算法,弱分类器${G}_m(x)$的输出值为{-1,1},类别标签${y}_i$的取值为{-1,1},如果样本被正确分类,$y_{i} G_{m}(x)>0,\quad w_{m+1, i}$取值较小,相反如果样本分类错误,$y_{i} G_{m}(x)<0, \quad w_{m+1, i}$取值较大,则权重变高,在之后的训练过程中会得到更多的重视。
3.多个弱学习器的结合
Adaboost对于弱学习器的结合策略是加权平均,
$$
f(x)=\sum_{m=1}^{M} \alpha_{m} G_{m}(x)
$$
那么最终的分类器为:
$$
G(x)=\operatorname{sign}(f(x))=\operatorname{sign}\left(\sum_{m=1}^{M} \alpha_{m} G_{m}(x)\right)
$$
<div id="5"></div>
##五、AdaBoost优点和缺点
**优点**
(1)算法集成了众多机器学习算法构建的弱分类器,不容易发生过拟合;
(2)相对于bagging算法和Random Forest算法,AdaBoost充分考虑的每个分类器的权重,可以取得较高的准确性;
(3)AdaBoost的训练参数很少,不需要调节太多的参数。
**缺点**
(1)由于AdaBoost是集成学习方法,其迭代次数基于弱分类器数目,因此迭代次数难以设定,可以使用交叉验证来进行确定;
(2)由于需要迭代所有分类器,因此训练比较耗时;
(3)对异常样本噪声敏感,异常样本在迭代中可能会获得较高的权重,影响最终的强学习器的预测准确性,同时数据正负样本不均衡也会导致实际准确性下降。
Adaboost分类器结构:

<div id="6"></div>
##六、Python代码
一个简单实例,来自飘涯
```python
#-*- conding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.ensemble import AdaBoostClassifier#adaboost引入方法
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_gaussian_quantiles#造数据
## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
## 创建数据
X1, y1 = make_gaussian_quantiles(cov=2.,
n_samples=200, n_features=2,
n_classes=2, random_state=1)#创建符合高斯分布的数据集
X2, y2 = make_gaussian_quantiles(mean=(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))
plot_step = 0.02
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, plot_step),
np.arange(y_min, y_max, plot_step))
#构建adaboost模型
bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1),
algorithm="SAMME.R",#可以不写
n_estimators=200)
#数据量大的时候,可以增加内部分类器的树深度,也可以不限制树深
#max_depth树深,数据量大的时候,一般范围在10——100之间
#数据量小的时候,一般可以设置树深度较小,或者n_estimators较小
#n_estimators 迭代次数或者最大弱分类器数:200次
#base_estimator:DecisionTreeClassifier 选择弱分类器,默认为CART树
#algorithm:SAMME 和SAMME.R 。运算规则,后者是优化算法,以概率调整权重,迭代速度快,
#需要能计算概率的分类器支持
#learning_rate:0<v<=1,默认为1,正则项 衰减指数
#loss:linear、‘square’exponential’。误差计算公式:一般用linear足够
bdt.fit(X, y)
#预测
Z = bdt.predict(np.c_[xx.ravel(), yy.ravel()])
#设置维度
Z = Z.reshape(xx.shape)
## 画图
plot_colors = "br"
class_names = "AB"
plt.figure(figsize=(10, 5), facecolor='w')
#局部子图
plt.subplot(121)
plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Paired)
for i, n, c in zip(range(2), class_names, plot_colors):
idx = np.where(y == i)
plt.scatter(X[idx, 0], X[idx, 1],
c=c, cmap=plt.cm.Paired,
label=u"类别%s" % n)
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.legend(loc='upper right')
plt.xlabel('x')
plt.ylabel('y')
plt.title(u'AdaBoost分类结果,正确率为:%.2f%%' % (bdt.score(X, y) * 100))
#获取决策函数的数值
twoclass_output = bdt.decision_function(X)
#获取范围
plot_range = (twoclass_output.min(), twoclass_output.max())
plt.subplot(122)
for i, n, c in zip(range(2), class_names, plot_colors):
#直方图
plt.hist(twoclass_output[y == i],
bins=20,
range=plot_range,
facecolor=c,
label=u'类别 %s' % n,
alpha=.5)
x1, x2, y1, y2 = plt.axis()
plt.axis((x1, x2, y1, y2 * 1.2))
plt.legend(loc='upper right')
plt.ylabel(u'样本数')
plt.xlabel(u'决策函数值')
plt.title(u'AdaBoost的决策值')
plt.tight_layout()
plt.subplots_adjust(wspace=0.35)
plt.show()
```
结果如下:

参考:
李航,《统计学习方法》 第八章
https://blog.csdn.net/qq_24519677/java/article/details/81910112
https://www.jianshu.com/p/b86a0863fe45