ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

集成学习-Task4 Boosting

2021-08-24 23:01:46  阅读:211  来源: 互联网

标签:集成 Task4 tree 分类器 train Adaboost Boosting test


1. Bagging与Boosting的联系和区别

        Bagging与Boosting都是集成学习模型,它们都需要将多个不同的模型整合到一起进行预测。

        Bagging思想的本质是:通过bootstrap的方式对全样本数据集做有放回抽样得到多个子集,在不同的子集上训练不同的弱分类器,最后通过投票的方式决定最终预测结果。这些弱分类器都倾向于过拟合并且Bagging会通过降低方差的方式减少预测误差。

        Boosting则是采取另一种思想:使用全样本数据集训练一系列弱分类器,然后将这些弱分类器组合形成一个预测性能更好的分类器。这些弱分类器都倾向于欠拟合并且Boosting会通过降低偏差的方式减少预测误差。

2. Boosting要解决的问题

        Boosting会从弱可学习算法出发,将其提升为强可学习算法。大多数的Boosting方法都是通过改变训练数据集中不同数据的概率分布来实现提升的。具体来说,Boosting在每一轮的学习中会改变数据集中不同样本的权值。并且在最后将各个弱分类器组合起来。

        对于Boosting来说,有两个问题需要解决:

        1. 如何改变数据的概率分布;

        2. 如何将各个弱分类器组合起来。

3. Adaboost——最经典的Boosting算法

3.1 Adaboost原理

        对于Adaboost而言,解决这两个问题的方法是:

        1. 上一轮分类错误的样本增加权重,分类正确的样本减少权重;

        2. 加权投票表决。表现好的分类器增加权重,表现差的分类器减少权重。

        下面我们具体介绍Adaboost算法。假设给定一个二分类数据集

T=\{(x_{1}, y_{1}), (x_{2}, y_{2}), \cdots, (x_{N}, y_{N})\}

其中x_{i}为特征空间\mathcal{X}中的特征向量,y_{i}为数据对应的标签且取值范围为{-1, +1}。记最终的分类器为G(x),则

        (1)用均匀分布对数据权重做初始化,即权重分布为

D_{1}=(w_{1,1}, w_{1,2}, \cdots, w_{1, N})

w_{1, i}=\frac{1}{N}

        (2)对于m=1,2,\cdots,M

        (2.1)使用权重分布D_{m}训练基分类器G_{m}(x)

        (2.2)计算G_{m}(x)在训练集上的分类误差

e_{m}=\sum_{i=1}^{N} 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)

        (2.3)利用分类误差计算分类器G_{m}(x)的权重

\alpha_{m}=\frac{1}{2}ln\frac{1-e_{m}}{e_{m}}

        (2.4)利用分类器权重更新训练数据的权重分布

D_{m+1}=(w_{m+1, 1}, w_{m+1, 2}, \cdots, w_{m+1, N})

w_{m+1, i}=\frac{w_{m, i}exp(-\alpha_{m}y_{i}G_{m}(x_{i}))}{\sum_{j = 1}^{N}w_{m, j}exp(-\alpha_{m}y_{j}G_{m}(x_{j}))}

        (3)构建基分类器的线性组合f(x)= \sum_{m = 1}^{M} \alpha_{m}G_{m}(x),则最终的分类器为

G(x)=sign(f(x))=sign(\sum_{m = 1}^{M} \alpha_{m}G_{m}(x))

        根据(2.3)分类误差越小,基分类器的权重越大。根据(2.4)被正确分类的样本权重会减小,而被错误分类的样本权重会增加。

3.2 在sklearn中使用Adaboost

import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt
plt.style.use("ggplot")
%matplotlib inline
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.metrics import accuracy_score
        
wine = pd.read_csv("https://archive.ics.uci.edu/ml/\
                    machine-learning-databases/wine/wine.data", \
                    header = None)
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']

print("Class labels",np.unique(wine["Class label"]))

wine = wine[wine['Class label'] != 1]
y = wine['Class label'].values
X = wine[['Alcohol', 'OD280/OD315 of diluted wines']].values

# 将分类标签变成二进制编码:
le = LabelEncoder()
y = le.fit_transform(y)

# 按照y的类别等比例抽样
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, \
                                                    random_state = 1, \
                                                    stratify = y)

# 使用单一决策树
tree = DecisionTreeClassifier(criterion = 'entropy', random_state = 1, \
                                max_depth = 1)
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))

# 使用Adaboost
ada = AdaBoostClassifier(base_estimator = tree, n_estimators = 500, \
                        learning_rate = 0.1, random_state = 1)
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))

        输出结果如下: 

Class labels [1 2 3]
Decision tree train/test accuracies 0.916/0.875
Adaboost train/test accuracies 1.000/0.917

3.3 对实例结果做进一步的分析

        我们从结果中可以发现:单层决策树似乎对训练数据欠拟合,而Adaboost模型正确地预测了训练数据的所有分类标签。同时,与单层决策树相比,Adaboost的测试性能也略有提高。我们可以通过画图的方式来解释出现这种现象的原因。

x_min = X_train[:, 0].min() - 1
x_max = X_train[:, 0].max() + 1
y_min = X_train[:, 1].min() - 1
y_max = 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(nrows = 1, ncols = 2, sharex = 'col', \
                        sharey = 'row', figsize = (12, 6))
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.tight_layout()
plt.text(0, -0.2, s = 'OD280/OD315 of diluted wines', ha = 'center', \
            va = 'center',fontsize = 12, transform = axarr[1].transAxes)
plt.show()

         我们可以发现Adaboost的决策边界比单层决策树的决策边界要复杂的多。换句话说,Adaboost试图用增加模型复杂度从而降低偏差的方式去减小总误差。但是这一过程引入了方差,可能出现过拟合,因此在训练集和测试集的性能上存在较大的差距。

        与单个分类器相比,Adaboost等Boosting方法增加了计算的复杂度,在实践中需要仔细思考是否愿意为预测性能的提升而增加计算成本。同时,Boosting无法做到现在流行的并行计算的方式,因为每一步迭代都要基于上一部的基分类器。

 3.4 由Adaboost引出的前向分步算法

        前向分步算法是比Adaboost更高级的框架。这个框架不但可以解决分类问题,还可以解决回归问题。它的算法流程可以与Adaboost的做类比。

        我们参考Adaboost,将最终的分类器表示为

f(x)= \sum_{m = 1}^{M} \beta_{m}b(x;\gamma_{m})

其中,b(x;\gamma_{m})是基分类器,\gamma_{m}为基分类器参数,\beta_{m}为基分类器权重。假设模型最终的损失函数为L(y,f(x)),则学习f(x)就等价于

\min _{\beta_{m}, \gamma_{m}} \sum_{i=1}^{N} L\left(y_{i}, \sum_{m=1}^{M} \beta_{m} b\left(x_{i} ; \gamma_{m}\right)\right)

这个最优化问题很难用一般的凸优化知识解决,因为这里有很多的\beta_{m}\gamma_{m}需要我们一次性求出。但是前向分步算法可以把这个类型的问题做分解。由于这个模型是一个加法模型,因此可以从前往后,在每一步只优化一个基分类器及其系数。具体来说,每一步只需要优化

\min_{\beta,\gamma} \sum_{i=1}^{N}L(y_{i},\beta b(x_{i};\gamma))

就可以。

        更具体来说,我们给定

T=\{(x_{1}, y_{1}), (x_{2}, y_{2}), \cdots, (x_{N}, y_{N})\}

 其中x_{i}为特征空间\mathcal{X}中的特征向量,y_{i}为数据对应的标签且取值范围为{-1, +1}。记最终的分类器为f(x),损失函数为L(y,f(x)),基分类器集合为\{b(x;\gamma)\},则

        (1)初始化f_{0}(x)=0

        (2)对m=1,2,\cdots,M

        (2.1)极小化损失函数

\beta_{m},\gamma_{m}=arg\min_{\beta,\gamma} \sum_{i=1}^{N}L(y_{i},f_{m-1}(x_{i})+\beta b(x_{i};\gamma))

 得到参数\beta_{m}\gamma_{m}

        (2.2)更新

f_{m}(x)=f_{m-1}(x)+\beta_{m}b(x;\gamma_{m})

        (3)不断重复上述过程直到得到最后的模型

f(x)=f_{M}(x)=\sum_{m=1}^{M} \beta_{m}b(x;\gamma_{m})

         这样,前向分步算法就将一次求解所有\beta_{m}\gamma_{m}的问题分解成了逐个求解的问题。

4. 从回归问题的集成学习到梯度提升决策树(GBDT)

4.1 用决策树和Boosting来解决回归问题

标签:集成,Task4,tree,分类器,train,Adaboost,Boosting,test
来源: https://blog.csdn.net/Zee_Chao/article/details/119876327

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有