机器学习实战教程(十三):集成学习

简介

集成学习是一种机器学习方法,它旨在通过将多个单独的学习器(称为基分类器或基学习器)的预测结果进行组合,来提高整体的预测准确率。

集成学习可以看作是一种“多个人一起合作做事”的方法。每个基分类器都是独立的学习器,它们在训练数据上进行训练并产生一个预测结果。这些基分类器可以使用不同的算法、不同的参数设置或不同的训练数据。最后,将所有基分类器的预测结果汇总起来,通过一定的组合方式(例如投票、加权投票等)得到最终的预测结果。

与单个分类器相比,集成学习可以显著提高分类器的准确率和泛化能力。这是因为集成学习可以有效地减少分类器的偏差和方差,从而避免过拟合和欠拟合问题。此外,集成学习还可以增加分类器的鲁棒性,使其对噪声和异常值具有更强的容忍性。

目前,集成学习已经被广泛应用于各种领域,例如图像识别、自然语言处理、金融风险评估等。常见的集成学习方法包括Bagging、Boosting、Stacking等。

在集成学习中,通常会涉及到几个概念,包括:

  1. 基分类器(Base Classifier):指的是单独的、独立的学习器,它们的预测结果会被组合起来生成最终的预测结果,集成学习中常用的基分类器有决策树、支持向量机、逻辑回归、朴素贝叶斯、神经网络等。不同的基分类器在不同的数据集和任务中可能会表现出不同的性能,因此在实际应用中需要根据具体情况选择合适的基分类器。。

  2. 集成分类器(Ensemble Classifier):指的是由多个基分类器组成的分类器。集成分类器可以看作是一个“元分类器”,它可以对多个基分类器的预测结果进行组合,从而得到更加准确的预测结果。

  3. Bagging(Bootstrap Aggregating):是一种基于自助采样法的集成学习方法。它通过对原始训练集进行多次有放回的采样,来产生多个训练集,并使用每个训练集产生一个基分类器。最后,将所有基分类器的预测结果进行投票或平均,得到最终的预测结果。

  4. Boosting:是一种迭代的、逐步提升基分类器性能的集成学习方法。它通过对训练集进行加权,使得基分类器更加关注那些被错误分类的样本,从而提高分类器的准确率。Boosting方法有很多种,比如AdaBoost、Gradient Boosting等。

  5. Stacking:是一种将多个基分类器的预测结果作为输入,再训练一个“元分类器”的集成学习方法。Stacking方法可以看作是一种二级学习方法,它将基分类器的预测结果作为新的特征,再进行训练,从而得到更加准确的预测结果。

这些概念是集成学习中非常基础且重要的内容,理解它们可以帮助我们更好地理解和应用集成学习算法。

集成分类方法

常用的集成分类方法有以下几种:

  1. Bagging:基于自助采样的方法,通过训练多个相互独立的基分类器,然后将它们的输出进行投票或平均。

  2. Boosting:通过逐步训练一系列弱分类器,每一轮训练都会根据前一轮分类器的错误情况来调整样本权重,使得被错误分类的样本得到更多的关注,从而提高分类器的性能。

以下是两种集成方法的集成分类器实现

  1. Random Forest(随机森林):是一种基于决策树的Bagging集成方法,通过随机选择特征和样本来生成多个决策树,然后将它们的输出进行投票。

  2. AdaBoost:是一种基于Boosting的集成方法,通过逐步训练一系列弱分类器,每一轮训练都会根据前一轮分类器的错误情况来调整样本权重,并且在训练过程中给每个分类器分配一个权重,然后将它们的输出进行加权平均。

  3. Gradient Boosting Decision Tree (GBDT):是一种基于Boosting的集成方法,通过逐步训练一系列决策树来提高分类器的性能,每个决策树都是基于前一棵树的残差来进行训练的,然后将所有决策树的输出进行加权平均。

这些集成分类器在不同的数据集和任务中可能会表现出不同的性能,因此在实际应用中需要根据具体情况选择合适的集成分类器。

Bagging

自举汇聚法(bootstrap aggregating),也称为bagging方法。Bagging对训练数据采用自举采样(boostrap sampling),即有放回地采样数据,主要思想:

  • 从原始样本集中抽取训练集。每轮从原始样本集中使用Bootstraping的方法抽取n个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中)。共进行k轮抽取,得到k个训练集。(k个训练集之间是相互独立的)
  • 每次使用一个训练集得到一个模型,k个训练集共得到k个模型。(注:这里并没有具体的分类算法或回归方法,我们可以根据具体问题采用不同的分类或回归方法,如决策树、感知器等)
  • 对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果。(所有模型的重要性相同)
    在这里插入图片描述

Boosting

Boosting是一种与Bagging很类似的技术。Boosting的思路则是采用重赋权(re-weighting)法迭代地训练基分类器,主要思想:

  • 每一轮的训练数据样本赋予一个权重,并且每一轮样本的权值分布依赖上一轮的分类结果,也就是说当前样本的权重,受分类结果的权重影响,当前分类结果的错误率越高,当前样本的权重也就越高,利用指数函数放大。
  • 基分类器之间采用序列式的线性加权方式进行组合。

在这里插入图片描述

Bagging、Boosting二者之间的区别

样本选择上:

  • Bagging:训练集是在原始集中有放回选取的,从原始集中选出的各轮训练集之间是独立的。
  • Boosting:每一轮的训练集不变,只是训练集中每个样例在分类器中的权重发生变化。而权值是根据上一轮的分类结果进行调整。

样例权重:

  • Bagging:使用均匀取样,每个样例的权重相等。
  • Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大,也就是每个样本都有一个权重,错误率越高权重越大,需要被重新训练的概率越大。

预测函数:
在集成学习中,我们通常会为每个基分类器分配一个权重,这个权重取决于该分类器在训练集上的表现。对于表现好的分类器,我们会赋予更高的权重,以使它们在投票决策中占据更重要的地位。相反,表现差的分类器会被分配较低的权重,以减少它们对最终结果的影响。

  • Bagging:所有预测函数的权重相等。
  • Boosting:每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重。

并行计算:

  • Bagging:各个预测函数可以并行生成。
  • Boosting:各个预测函数只能顺序生成,因为后一个模型参数需要前一轮模型的结果。

下面是将决策树与这些算法框架进行结合所得到的新的算法:

  • Bagging + 决策树 = 随机森林
  • AdaBoost + 决策树 = 提升树
  • Gradient Boosting + 决策树 = GBDT

随机森林

自助采样

随机森林是一种基于Bagging集成学习思想的算法,它使用多个决策树进行集成,同时通过引入随机特征选择和样本随机抽样的方法来增加模型的随机性,提高模型的泛化能力。下面举一个简单的例子来说明随机森林的计算过程。

假设我们有一个包含1000个样本的数据集,每个样本包含5个特征。我们希望使用随机森林对这个数据集进行分类。

首先,我们需要对数据集进行随机抽样,从原始数据集中有放回地随机抽取1000个样本(有放回地抽样意味着同一个样本可能会被抽取多次,比如抽取了一个样本1,记录到一个袋子中,放回到原数据集,然后又从原数据集1000个中抽一个,可能又抽到样本1,也可以能是样本100,每次都是从1000个中抽取,抽取1000次,运气好的情况下可能抽到1000个样本1,当然这几乎不可能,不要理解为从源数据集拿到一个数据就放到自助采样集,就不放回去了,自助采样集只是个样本的复制),这个新的数据集就是一个“袋子”,我们称之为一个“自助采样集”(bootstrap sample)。这个自助采样集中有一部分样本可能重复出现,另一些样本可能没有被抽取到。这个过程被称为自助采样(bootstrap)。

接下来,我们需要使用基于决策树的分类器对这个自助采样集进行训练。在训练决策树时,我们需要对每个节点上的特征进行随机选择,具体地,每次从原始特征中随机选择一定数量的特征,然后从这些特征中选择最优的特征进行划分。这个过程被称为随机特征选择(random feature selection)。

训练出第一个决策树之后,我们可以对剩余的样本进行预测,记录下每个样本的预测结果。接着,我们再次从原始数据集中有放回地随机抽取1000个样本,形成一个新的自助采样集,使用同样的方法训练第二个决策树,并记录下每个样本的预测结果。

重复这个过程,直到训练出指定数量的决策树。最终,我们可以对每个样本的预测结果进行投票,得出随机森林的最终预测结果。

需要注意的是,随机森林中的决策树通常是并行训练的,即每个决策树可以在独立的CPU核心上进行训练,从而加速模型的训练过程。另外,随机森林中的决策树可以使用一些剪枝策略来防止过拟合,比如最小样本数限制、最大深度限制等。

预测数据

注意集成学习算法,不是通过数据训练从多个模型中选择出一个模型,而是多个模型输入结果预测,通过投票或者求平均值等方法获得最终的结果。

随机森林是一种集成学习方法,它基于决策树算法进行构建。随机森林的预测数据的过程如下:

  1. 从训练集中随机有放回地抽取n个样本作为一个子集,这个子集的大小和训练集的大小相同。

  2. 针对这个子集,随机选择k个特征,其中k是一个固定的超参数,一般小于特征总数。

  3. 基于这个子集和k个特征,训练一个决策树模型。

  4. 重复1-3步骤m次,得到m个决策树模型。

  5. 对于新的数据点,将它输入到每一个决策树模型中,得到m个预测结果。

  6. 对于分类问题,使用投票的方式,将m个预测结果中得票最多的类别作为最终的预测结果。对于回归问题,使用平均值的方式,将m个预测结果进行平均,作为最终的预测结果。

需要注意的是,在随机森林中,每个决策树模型的训练都是独立的,因此可以并行地进行训练和预测,从而提高模型的效率。

鸢尾花预测

鸢尾花数据集是一组带有标签的多元数据,其中包含了三个不同品种的鸢尾花(山鸢尾、变色鸢尾、维吉尼亚鸢尾)的测量值。这些测量值(特征)包括花萼长度、花萼宽度、花瓣长度和花瓣宽度。每个样本都包含这四个测量值,共150个样本。

该数据集的目的是通过这些测量值来区分不同品种的鸢尾花。这是一个非常常见的机器学习问题,被广泛用于分类和聚类算法的基准测试。

鸢尾花数据集是机器学习领域最常用的数据集之一,它在数据可视化、模型评估、特征选择和算法比较等方面都有广泛的应用。

我们首先使用sklearn库中的load_iris函数加载了鸢尾花数据集。然后,我们使用train_test_split函数将数据集分割为训练集和测试集,比例为0.3

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

# 加载鸢尾花数据集
iris = load_iris()
# 打印特征数和数据集大小
print("Number of features: ", len(iris.feature_names))
print("Number of samples: ", len(iris.data))
print(iris.target)

输出:

Number of features:  4
Number of samples:  150
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2]

然后,我们使用train_test_split函数将数据集分割为训练集和测试集,比例为0.3

# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3,random_state=2)

直接使用决策树预测。

from sklearn.tree import DecisionTreeClassifier
# 定义决策树分类器
clf = DecisionTreeClassifier(random_state=1)

# 训练模型
clf.fit(X_train, y_train)

# 预测测试集
y_pred = clf.predict(X_test)
accuracy = clf.score(X_test, y_test)
print("Accuracy:", accuracy)

输出:Accuracy: 0.9555555555555556

RandomForestClassifier是一个基于随机森林算法实现的分类模型,它有一些重要的参数,下面我将对这些参数进行详细解释。

  1. n_estimators:表示构建随机森林时决策树的数量,默认值为100。n_estimators越大,模型的准确率和稳定性相对也会提高,但是训练时间会增加,因此需要在准确率和时间成本之间进行权衡。

  2. criterion:表示衡量分裂质量的指标,可以选择"gini"或"entropy"。默认值为"gini",意味着使用基尼系数来衡量分裂质量。而"entropy"表示使用信息增益来衡量分裂质量。一般来说,选择基尼系数比信息增益要快一些,但是在某些情况下,信息增益可能会表现得更好。

  3. max_depth:表示决策树的最大深度,默认值为None,表示不限制深度。如果将max_depth设置为较小的值,可以避免过拟合的情况发生,但是可能会影响模型的准确率。

  4. min_samples_split:表示在进行节点分裂之前,节点的最小样本数,默认值为2。如果将min_samples_split设置为较大的值,可以避免决策树在局部区域上过度拟合,但是可能会导致决策树欠拟合。

  5. min_samples_leaf:表示叶节点的最小样本数,默认值为1。如果将min_samples_leaf设置为较小的值,可以使模型更加灵活,但是可能会导致决策树过拟合。

  6. max_features:表示在确定节点分裂时,要考虑的特征数。可以输入整数、浮点数、字符串或None。如果输入整数,则表示考虑的特征数为该整数值;如果输入浮点数,则表示考虑的特征数为总特征数乘以该浮点数值;如果输入字符串"auto",则表示考虑的特征数为总特征数;如果输入字符串"sqrt",则表示考虑的特征数为总特征数的平方根;如果输入字符串"log2",则表示考虑的特征数为总特征数的以2为底的对数;如果输入None,则表示考虑的特征数为总特征数。一般来说,随机森林的表现比较稳定,因此可以将max_features设置为默认值None。

  7. random_state:表示随机种子,用于控制随机模式的生成,可以使随机模式可重复。如果将random_state设置为整数,则表示使用该整数作为随机种子;如果设置为None,则表示使用默认的随机种子。

使用随机森林


# 创建随机森林分类器,指定决策树数量为100,其他参数采用默认值
rfc = RandomForestClassifier(n_estimators=100)

# 使用训练数据集进行训练
rfc.fit(X_train, y_train)

# 使用测试数据集进行预测
y_pred = rfc.predict(X_test)

# 计算模型的准确率
accuracy = rfc.score(X_test, y_test)
print("Accuracy:", accuracy)

输出:Accuracy: 0.9777777777777777

AdaBoost

AdaBoost(Adaptive Boosting)是一种集成学习方法,其目的是将多个弱分类器组合成一个强分类器。它的核心思想是每一次训练都加强那些前一次训练中被错误分类的样本的权重,减少那些被正确分类的样本的权重。这样,在每一次训练中,模型都会更加关注前面分类效果不好的样本,从而使得整个模型能够更好地适应数据集。

算法的过程和公式

AdaBoost算法的过程和公式如下:

  1. 初始化训练数据的权重:对于有N个样本的训练集D,每个样本的权重初始化为1/N。

  2. 对于t=1,2,…T,进行以下操作:

    a. 根据当前的训练数据权重分布,使用基分类器(如决策树)进行训练。

    b. 计算基分类器的错误率(误差率):对于分类错误的样本,权重增加;对于分类正确的样本,权重减少。

    c. 计算基分类器的权重:基分类器的权重与其错误率相关,错误率越小的基分类器,其权重越大。

    d. 更新训练数据的权重:根据基分类器的权重,更新训练数据的权重分布,使得基分类器错误率大的样本权重增加,错误率小的样本权重减少。

  3. 最终的分类器是基分类器的加权和,权重为每个基分类器的权重。

AdaBoost算法的公式如下:

Step 1:初始化权重

D 1 ( i ) = 1 N , i = 1 , 2 , . . . , N D_1(i)=\frac{1}{N}, i=1,2,...,N D1(i)=N1,i=1,2,...,N

Step 2:对于t=1,2,…T,进行以下操作:

a. 训练基分类器

G t ( x ) : X → { − 1 , 1 } G_t(x):\mathcal{X}\rightarrow\{-1,1\} Gt(x):X{ 1,1}

b. 计算错误率

ϵ t = P ( G t ( x i ) ≠ y i ) = ∑ i = 1 N D t ( i ) [ G t ( x i ) ≠ y i ] \epsilon_t=P(G_t(x_i)\ne y_i)=\sum_{i=1}^N D_t(i)[G_t(x_i)\ne y_i] ϵt=P(Gt(xi)=yi)=i=1NDt(i)[Gt(xi)=yi]

c. 计算基分类器的权重

α t = 1 2 ln ⁡ 1 − ϵ t ϵ t \alpha_t=\frac{1}{2}\ln\frac{1-\epsilon_t}{\epsilon_t} αt=21lnϵt1ϵt

d. 更新权重

D t + 1 ( i ) = D t ( i ) exp ⁡ ( − α t y i G t ( x i ) ) Z t , i = 1 , 2 , . . . , N D_{t+1}(i)=\frac{D_t(i)\exp(-\alpha_ty_iG_t(x_i))}{Z_t},i=1,2,...,N Dt+1(i)=ZtDt(i)exp(αtyiGt(xi)),i=1,2,...,N
其中, Z t Z_t Zt是规范化因子,使得 D t + 1 D_{t+1} Dt+1​成为概率分布。

Step 3:最终分类器

f ( x ) = sign ⁡ ( ∑ t = 1 T α t G t ( x ) ) f(x)=\operatorname{sign}\left(\sum_{t=1}^T\alpha_tG_t(x)\right) f(x)=sign(t=1TαtGt(x))

其中, s i g n ⁡ ( x ) sign⁡(x) sign(x)是符号函数,如果x≥0,则 sign ⁡ ( x ) = 1 \operatorname{sign}(x)=1 sign(x)=1;否则, sign ⁡ ( x ) = − 1 \operatorname{sign}(x)=-1 sign(x)=1

鸢尾花预测

sklearn.ensemble模块提供了很多集成方法,AdaBoost、Bagging、随机森林等。本次使用的是AdaBoostClassifier。
让我们先看下AdaBoostClassifier这个函数,一共有5个参数:
在这里插入图片描述
参数说明如下:

  • base_estimator: 可选参数,默认为DecisionTreeClassifier。理论上可以选择任何一个分类或者回归学习器,不过需要支持样本权重。我们常用的一般是CART决策树或者神经网络MLP。默认是决策树,即AdaBoostClassifier默认使用CART分类树DecisionTreeClassifier,而AdaBoostRegressor默认使用CART回归树DecisionTreeRegressor。另外有一个要注意的点是,如果我们选择的AdaBoostClassifier算法是SAMME.R,则我们的弱分类学习器还需要支持概率预测,也就是在scikit-learn中弱分类学习器对应的预测方法除了predict还需要有predict_proba。
  • algorithm: 可选参数,默认为SAMME.R。scikit-learn实现了两种Adaboost分类算法,SAMME和SAMME.R。两者的主要区别是弱学习器权重的度量,SAMME使用对样本集分类效果作为弱学习器权重,而SAMME.R使用了对样本集分类的预测概率大小来作为弱学习器权重。由于SAMME.R使用了概率度量的连续值,迭代一般比SAMME快,因此AdaBoostClassifier的默认算法algorithm的值也是SAMME.R。我们一般使用默认的SAMME.R就够了,但是要注意的是使用了SAMME.R, 则弱分类学习器参数base_estimator必须限制使用支持概率预测的分类器。SAMME算法则没有这个限制。
  • n_estimators: 整数型,可选参数,默认为50。弱学习器的最大迭代次数,或者说最大的弱学习器的个数。一般来说n_estimators太小,容易欠拟合,n_estimators太大,又容易过拟合,一般选择一个适中的数值。默认是50。在实际调参的过程中,我们常常将n_estimators和下面介绍的参数learning_rate一起考虑。
  • learning_rate: 浮点型,可选参数,默认为1.0。每个弱学习器的权重缩减系数,取值范围为0到1,对于同样的训练集拟合效果,较小的v意味着我们需要更多的弱学习器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。所以这两个参数n_estimators和learning_rate要一起调参。一般来说,可以从一个小一点的v开始调参,默认是1。
  • random_state: 整数型,可选参数,默认为None。如果RandomState的实例,random_state是随机数生成器; 如果None,则随机数生成器是由np.random使用的RandomState实例。
#%%
from sklearn.datasets import load_iris
from sklearn.ensemble import AdaBoostClassifier
from sklearn.model_selection import train_test_split

iris = load_iris()
X, y = iris.data, iris.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

clf = AdaBoostClassifier(n_estimators=50, learning_rate=1.0, random_state=42)
clf.fit(X_train, y_train)

accuracy = clf.score(X_test, y_test)
print("Accuracy:", accuracy)

输出:Accuracy: 1.0

集成学习选择

AdaBoost和随机森林都是集成学习方法,通过组合多个弱分类器(或决策树)来构建一个强分类器。虽然它们都可以提高分类的准确率,但是在不同的数据集和场景下,它们的表现可能会有所不同。

一般来说,随机森林适合处理高维数据和噪声较多的数据集,因为它可以随机选取特征和样本来构建多个决策树,从而减少过拟合的风险。而AdaBoost则适合处理低维数据和复杂的分类问题,因为它可以通过调整权重和重采样来训练多个弱分类器,并将它们组合起来得到一个更强的分类器。

因此,在处理复杂的低维数据集时,AdaBoost通常能够表现出更好的分类准确率,而在处理高维数据集时,随机森林可能更适合。但是,这只是一般情况,在具体应用中,需要根据数据集的特点和需求来选择适合的算法。

猜你喜欢

转载自blog.csdn.net/liaomin416100569/article/details/130501843