集成学习--boosting

1. 导论

通过前面的课程,我们学习了一些简单而实用的分类和回归模型,同时也探讨了如何使用集成学习家族的bagging思想去优化最终的模型。bagging 思想的实质是:通过boostrap的方式对全样本进行抽样得到的抽样子集,对不同的子集使用同一种模型进行拟合,然后投票得到最终的预测。同时我们也知道bagging主要通过降低方差的方式减少预测误差。而boosting与bagging的思想截然不同,boosting方法是使用同一组数据集进行反复学习,得到一系列简单模型,然后组合这些模型构成一个预测性能十分强大的机器学习模型。显然boosting思想提高最终的预测效果是通过不断减少偏差的形式。

2. Boosting方法的基本思路

先介绍两个例子:
第一个例子:不知道大家有没有做过错题本,我们将每次测验的错的题目记录在错题本上,不停的翻阅,直到我们完全掌握(也就是能够在考试中能够举一反三)。
第二个例子:对于一个复杂任务来说,将多个专家的判断进行适当的综合所作出的判断,要比其中任何一个专家单独判断要好。实际上这是一种“三个臭皮匠顶个诸葛亮的道理”。
这两个例子都说明Boosting的道理,也就是不错地重复学习达到最终的要求。

3. Adaboost算法

Adaboost的基本原理

对于Adaboost来说,解决上述的两个问题的方式是:

1. 提高那些被前一轮分类器错误分类的样本的权重,而降低那些被正确分类的样本的权重。这样一来,那些在上一轮分类器中没有得到正确分类的样本,由于其权重的增大而在后一轮的训练中“备受关注”。

2. 各个弱分类器的组合是通过采取加权多数表决的方式,具体来说,加大分类错误率低的弱分类器的权重,因为这些分类器能更好地完成分类任务,而减小分类错误率较大的弱分类器的权重,使其在表决中起较小的作用。

下面,我们使用sklearn对Adaboost算法进行建模:

本次案例我们使用一份UCI的机器学习库里的开源数据集:葡萄酒数据集。

# 引入数据科学相关工具包:
import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt
plt.style.use("ggplot")
%matplotlib inline
import seaborn as sns
# 加载训练数据:         
wine = pd.read_csv("wine.txt",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.head()

集成学习--boosting

 

 

# 数据预处理
# 仅仅考虑2,3类葡萄酒,去除1类
wine = wine[wine[Class label] != 1]
y = wine[Class label].values
X = wine[[Alcohol,OD280/OD315 of diluted wines]].values

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


# 按8:2分割训练集和测试集
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=1,stratify=y)  # stratify参数代表了按照y的类别等比例抽样
# 使用单一决策树建模
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier(criterion=entropy,random_state=1,max_depth=1)
from sklearn.metrics import accuracy_score
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))

集成学习--boosting

 

 

# 使用sklearn实现Adaboost(基分类器为决策树)
‘‘‘
AdaBoostClassifier相关参数:
base_estimator:基本分类器,默认为DecisionTreeClassifier(max_depth=1)
n_estimators:终止迭代的次数
learning_rate:学习率
algorithm:训练的相关算法,{‘SAMME‘,‘SAMME.R‘},默认=‘SAMME.R‘
random_state:随机种子
‘‘‘
from sklearn.ensemble import AdaBoostClassifier
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))

集成学习--boosting

 

 结果分析:单层决策树似乎对训练数据欠拟合,而Adaboost模型正确地预测了训练数据的所有分类标签,而且与单层决策树相比,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()

集成学习--boosting

 

 

从上面的决策边界图可以看到:Adaboost模型的决策边界比单层决策树的决策边界要复杂的多。也就是说,Adaboost试图用增加模型复杂度而降低偏差的方式去减少总误差,但是过程中引入了方差,可能出现国拟合,因此在训练集和测试集之间的性能存在较大的差距,这就简单地回答的刚刚问题。值的注意的是:与单个分类器相比,Adaboost等Boosting模型增加了计算的复杂度,在实践中需要仔细思考是否愿意为预测性能的相对改善而增加计算成本,而且Boosting方式无法做到现在流行的并行计算的方式进行训练,因为每一步迭代都要基于上一部的基本分类器。

4. 前向分步算法

(1) 加法模型:

集成学习--boosting

 

 (2) 前向分步算法:

集成学习--boosting

 

 (3) 前向分步算法与Adaboost的关系:

Adaboost算法是前向分步算法的特例,Adaboost算法是由基本分类器组成的加法模型,损失函数为指数损失函数。

5. 梯度提升决策树(GBDT)

(1) 基于残差学习的提升树算法:

前面我们一直学习的都是分类树,并没有涉及到回归的例子,接下来要学习一下如何使用加法模型+前向分步算法的框架实现回归问题。在使用加法模型+前向分步算法的框架解决问题之前,我们需要首先确定框架内使用的基函数是什么,在这里我们使用决策树分类器。树算法最重要是寻找最佳的划分点,分类树用纯度来判断最佳划分点使用信息增益(ID3算法),信息增益比(C4.5算法),基尼系数(CART分类树)。但是在回归树中的样本标签是连续数值,可划分点包含了所有特征的所有可取的值。所以再使用熵之类的指标不再合适,取而代之的是平方误差,它能很好的评判拟合程度。模仿分类错误率,我们用每个样本的残差表示每次使用基函数预测时没有解决的那部分问题。

所以这种依靠加法模型+前向分步算法的框架解决回归问题的算法,叫提升树算法。那么,这个算法还是否有提升的空间呢?

(2) 梯度提升决策树算法(GBDT):

提升树利用加法模型和前向分步算法实现学习的过程,当损失函数为平方损失和指数损失时,每一步优化是相当简单的,也就是我们前面探讨的提升树算法和Adaboost算法。但是对于一般的损失函数而言,往往每一步的优化不是那么容易。

集成学习--boosting

 

 

6. XGBoost算法

XGBoost本质上还是一个GBDT,但是力争把速度和效率发挥到极致,所以叫X (Extreme) GBoosted,包括前面说过,两者都是boosting方法。XGBoost是一个优化的分布式梯度增强库,旨在实现高效,灵活和便携。 它在Gradient Boosting框架下实现机器学习算法。 XGBoost提供了并行树提升(也称为GBDT,GBM)。

Xgboost以CART决策树为子模型,通过Gradient Tree Boosting实现多棵CART树的集成学习,得到最终模型。

 

集成学习--boosting

上一篇:Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决


下一篇:yarn 安装vue后 命令不起作用