Boosting 和 AdaBoost
1. Boosting
Boosting 体现了提升思想,每一个训练器重点关注前一个训练器不足的地方进行训练,通过加权投票的方式,得出预测结果。
Bagging 与 Boosting
区别一:数据方面
- Bagging:有放回采样
- Boosting:全部数据集, 重点关注前一个弱学习器不足
区别二:投票方面
- Bagging:平权投票
- Boosting:加权投票
区别三:学习顺序
- Bagging的学习是并行的,每个学习器没有依赖关系
- Boosting学习是串行,学习有先后顺序
1.1 算法机制
Boosting是一组可将弱学习器升为强学习器算法。这类算法的工作机制类似:
1.先从初始训练集训练出一个基学习器。
2.在根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续得到最大的关注。
- 前一个模型训练正确的样本,样本权重减少
- 前一个模型训练错误的样本,样本权重增加,这样后续的模型就可以更加容易的学习到之前错误的样本,提高模型的能力。
3.然后基于调整后的样本分布来训练下一个基学习器;
4.如此重复进行,直至基学习器数目达到实现指定的值T为止。
5.再将这T个基学习器进行加权结合得到集成学习器。
简而言之:每新加入一个弱学习器,整体能力就会得到提升
Boosting算法的著名代表就是Adaboost算法。
因此,对于Boosting算法,存在两个问题:
-
在每一轮中如何调整训练集,使训练的弱分类器得以进行;(调整样本权值)
-
如何将各个弱分类器联合起来形成强分类器。 (调整模型权值)
1.2 Boosting的概念强化
提升Boosting是一个机器学习技术,可以用于回归和分类问题,它每一步产生一个弱预测模型(如决策树)并加权累加到总模型中;如果每一步的弱预测模型生成都是依据损失函数的梯度方向,则称之为梯度提升(GradientBoosting)。
梯度提升算法首先给定一个目标损失函数,它的定义域是所有可行的弱函数集合(基函数);提升算法通过迭代的选择一个负梯度方向上的基函数来逐渐逼近局部极小值。这种在函数域的梯度提升观点对机器学习有很大影响。
提升的理论意义:如果一个问题存在弱分类器,则可以通过提升的办法得到强分类器。
1.3 Boosting实现过程
如下过程演示:
- 每训练一轮模型,都会对训练样本的权重进行调整,从而调整样本分布。
2. AdaBoost
AdaBoost (Adaptive Boosting, 自适应提升)是 Boosting 算法的一种实现,是一种用于分类问题的算法,它用弱分类器的线性组合来构造强分类器。弱分类器的性能比随机猜测强就行,即可构造出一个非常准确的强分类器。其特点是:训练时,样本具有权重,并且在训练过程中动态调整。被分错的样本的样本会加大权重,算法更加关注难分的样本。
2.1 AdaBoost简介
AdaBoost自适应提升学习算法和Boosting考虑的点一样
Adaboost自适应在于:“关注”被错分的样本,“器重”性能好的弱分类器:(观察下图)
(1)不同的训练集—>调整样本权重
(2)“关注”—>增加错分样本权重
(3)“器重”—>好的分类器权重大
(4) 样本权重间接影响分类器权重
AdaBoost算法的两个核心步骤:
权值调整: AdaBoost算法提高那些被前一轮基分类器错误分类样本的权值,而降低那些被正确分类样本的权值。从而使得那些没有得到正确分类的样本,由于权值的加大而受到后一轮基分类器的更大关注。
基分类器组合: AdaBoost采用加权多数表决的方法。
-
分类误差率较小的弱分类器的权值大,在表决中起较大作用。
-
分类误差率较大的弱分类器的权值小,在表决中起较小作用。
2.2 AdaBoost特点
AdaBoost把多个不同的弱分类算法,用一种非随机的方式组合起来,表现出惊人的性能。
1,可以使用各种方法构建子分类器,Adaboost算法提供的是框架;
2,子分类器容易构造;
3,速度快,且基本不用调参数;
4,泛化错误率低。
2.3 AdaBoost步骤
Adaboost迭代算法有3步:
1.初始化训练数据的权值分布:假设有N个样本,每个样本赋予相同权值1/N。
2.训练弱分类器:本轮训练中,若某样本分错,则提高它的权值,相反分类正确的样本被降低权值。然后,权值更新过的全体样本被用于训练下一个分类器,使得下一个分类器更关注权重大的难分样本。多次迭代,训练多个弱分类器。
3.加权组合弱分类器:加大分类误差率小的弱分类器的权重,使其在最终表决中起较大作用,而降低分类误差率大的弱分类器的权重,使其在最终表决中起较小作用。
2.4 AdaBoost算法推导
AdaBoost 模型公式中
- α 为模型的权重
- m 为弱学习器数量
- hi(x) 表示弱学习器
- H(x) 输出结果大于 0 则归为正类,小于 0 则归为负类。
AdaBoost 模型权重公式:
α
t
\alpha_t
αt是模型的权重系数
ϵ
t
\epsilon_t
ϵt是第t个若学习的错误率
- 错误率越高,权重越小
- 错误率越低,权重越大
AdaBoost 样本权重更新公式:
- Zt 为归一化值(所有样本权重的总和)
- Dt(x) 为样本权重
- αt 为模型权重。
3. AdaBoost 构建过程
下面为训练数数据,假设弱分类器由 x 产生,其阈值 v 使该分类器在训练数据集上的分类误差率最低,试用 Adaboost 算法学习一个强分类器。
3.1 构建第一个弱学习器
-
初始化工作:初始化 10 个样本的权重,每个样本的权重为:0.1(1/N)
-
构建第一个基学习器:
-
寻找最优分裂点(寻找错误率最低的点,是一个回归任务)
- 对特征值 x 进行排序,确定分裂点为:0.5、1.5、2.5、3.5、4.5、5.5、6.5、7.5、8.5
- 当以 0.5 为分裂点时,有 5 个样本分类错误
- 当以 1.5 为分裂点时,有 4 个样本分类错误
- 当以 2.5 为分裂点时,有 3 个样本分类错误
- 当以 3.5 为分裂点时,有 4 个样本分类错误
- 当以 4.5 为分裂点时,有 5 个样本分类错误
- 当以 5.5 为分裂点时,有 4 个样本分类错误
- 当以 6.5 为分裂点时,有 5 个样本分类错误
- 当以 7.5 为分裂点时,有 4 个样本分类错误
- 当以 8.5 为分裂点时,有 3 个样本分类错误
- 最终,选择以 2.5 作为分裂点,计算得出基学习器错误率为:3/10=0.3
-
计算模型权重:
1/2 * np.log((1-0.3)/0.3)=0.4236
-
更新样本权重:
- 分类正确样本为:1、2、3、4、5、6、10 共 7 个,其计算公式为:e-αt,则正确样本权重变化系数为:e-0.4236 = 0.6547
- 分类错误样本为:7、8、9 共 3 个,其计算公式为:eαt,则错误样本权重变化系数为:e0.4236 = 1.5275
- 样本 1、2、3、4、5、6、10 权重值为:
0.06547
- 样本 7、8、9 的样本权重值为:
0.15275
- 归一化 Zt 值为:
0.06547 * 7 + 0.15275 * 3 = 0.9165
- 样本 1、2、3、4、5、6、10 最终权重值为:
0.07143
- 样本 7、8、9 的样本权重值为:
0.1667
-
此时得到:
-
3.2 构建第二个弱学习器
-
寻找最优分裂点:
-
对特征值 x 进行排序,确定分裂点为:0.5、1.5、2.5、3.5、4.5、5.5、6.5、7.5、8.5
-
当以 0.5 为分裂点时,有 5 个样本分类错误,错误率为:0.07143 * 5 = 0.35715
-
当以 1.5 为分裂点时,有 4 个样本分类错误,错误率为:0.07143 * 1 + 0.16667 * 3 = 0.57144
-
当以 2.5 为分裂点时,有 3 个样本分类错误,错误率为:0.16667 * 3 = 0.57144
。。。 。。。
-
当以 8.5 为分裂点时,有 3 个样本分类错误,错误率为:0.07143 * 3 = 0.21429
-
最终,选择以 8.5 作为分裂点,计算得出基学习器错误率为:0.21429
-
-
计算模型权重:
1/2 * np.log((1-0.21429)/0.21429)=0.64963
-
分类正确的样本:1、2、3、7、8、9、10,其权重调整系数为:0.5222
-
分类错误的样本:4、5、6,其权重调整系数为:1.9148
-
分类正确样本权重值:
- 样本 1、2、3、9 为:0.0373
- 样本 6、7、8 为:0.087
-
分类错误样本权重值:0.1368
-
归一化 Zt 值为:
0.0373 * 4 + 0.087 * 3 + 0.1368 * 3 = 0.8206
-
最终权重:
- 样本 1、2、3、9 为 :0.0455
- 样本 6、7、8 为:0.1060
- 样本 3、4、5 为:0.1667
-
此时得到:
3.3 构建第三个弱学习器
错误率:0.1820,模型权重:0.7514
3.4 强学习器
4. AdaBoost实战葡萄酒数据
4.1导入数据
# 获取数据
import pandas as pd
df_wine = pd.read_csv('data/wine.data')
# 修改列名
df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols',
'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue', 'OD280/OD315 of diluted wines',
'Proline']
# 去掉一类(1,2,3)
df_wine = df_wine[df_wine['Class label'] != 1]
# 获取特征值和目标值
X = df_wine[['Alcohol', 'Hue']].values
y = df_wine['Class label'].values
4.2 切分数据
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
# 类别转化 (2,3)=>(0,1)
le = LabelEncoder()
y = le.fit_transform(y)
# 划分训练集和测试集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.4,random_state=1)
4.3 在500棵单层决策树上训练AdaBoost
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
# 机器学习(决策树和AdaBoost)
tree = DecisionTreeClassifier(criterion='entropy',max_depth=1,random_state=0)
ada= AdaBoostClassifier(base_estimator=tree,n_estimators=500,learning_rate=0.1,random_state=0)
4.4 AdaBoost分类器性能评估
from sklearn.metrics import accuracy_score
# 决策树和AdaBoost分类器性能评估
# 决策树性能评估
tree = tree.fit(X_train,y_train)
y_train_pred = tree.predict(X_train)
y_test_pred = tree.predict(X_test)
tree_train = accuracy_score(y_train,y_train_pred)
tree_test = accuracy_score(y_test,y_test_pred)
print('Decision tree train/test accuracies %.3f/%.3f' % (tree_train,tree_test))
# Decision tree train/test accuracies 0.845/0.854
# AdaBoost性能评估
ada = ada.fit(X_train,y_train)
y_train_pred = ada.predict(X_train)
y_test_pred = ada.predict(X_test)
ada_train = accuracy_score(y_train,y_train_pred)
ada_test = accuracy_score(y_test,y_test_pred)
print('Adaboost train/test accuracies %.3f/%.3f' % (ada_train,ada_test))
# Adaboost train/test accuracies 1/0.875
总结:AdaBosst预测准确了所有的训练集类标,与单层决策树相比,它在测试机上表现稍微好一些。单决策树对于训练数据过拟合的程度更加严重一些。总之,我们可以发现Adaboost分类器能够些许提高分类器性能,并且与bagging分类器的准确率接近.
4.5 绘制决策区域形状(复制演示)
import numpy as np
import matplotlib.pyplot as plt
x_min,x_max = X_train[:,0].min() - 1,X_train[:,0].max() + 1
y_min,y_max = X_train[:,1].min() - 1,X_train[:,1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min,x_max,0.1),np.arange(y_min,y_max,0.1))
f,axarr = plt.subplots(1,2,sharex='col',sharey='row',figsize=(8,3))
for idx,clf,tt in zip([0,1],[tree,ada],['Decision Tree', 'AdaBoost']):
clf.fit(X_train,y_train)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
axarr[idx].contourf(xx,yy,Z,alpha = 0.3)
axarr[idx].scatter(X_train[y_train==0,0],X_train[y_train==0,1],c='blue',marker='^')
axarr[idx].scatter(X_train[y_train==1,0],X_train[y_train==1,1],c='red',marker='o')
axarr[idx].set_title(tt)
axarr[0].set_ylabel('Alcohol', fontsize=12)
plt.text(10.2,-1.2,s='Hue',ha='center',va='center',fontsize = 12)
plt.tight_layout()
总结:通过观察区域,我们可以看到AdaBoost的决策区域比单层的决策区域更加复杂。
4.6 总结
集成技术与单独的分类器性能比较,集成学习提高了复杂度,但在实践中,需要衡量是否愿意为适度提高预测性能付出更多的计算成本。
5. 小结
- Boosting 体现了提升思想,每一个训练器重点关注前一个训练器不足的地方进行训练,通过加权投票的方式,得出预测结果
- AdaBoost 是 boosting 家族算法中的一员,其主要通过改变样本权重,来训练多个弱学习器,最后通过加权求和的方式得出预测结果