【机器学习之集成学习算法-01】| 基于重抽样自举法的集成学习方法:Bagging袋装法和Random Forests随机森林算法原理及PM2.5浓度回归预测实例分析

🎩 欢迎来到技术探索的奇幻世界👨‍💻

📜 个人主页@一伦明悦-CSDN博客

✍🏻 作者简介: C++软件开发、Python机器学习爱好者

🗣️ 互动与支持:💬评论      👍🏻点赞      📂收藏     👀关注+

如果文章有所帮助,欢迎留下您宝贵的评论,点赞加收藏支持我,点击关注,一起进步!


目录

前言            

正文 

01-集成学习简介          

02-重抽样自举法简介          

 03-Bagging袋装法简介          

04-Random Forests随机森林算法          

05-基于Bagging方法和RF算法对PM2.5浓度回归预测          

总结 


前言            

        集成学习是一种机器学习技术,其核心思想是通过结合多个基本模型的预测结果来提高整体性能。常见的集成学习方法包括bagging、boosting和stacking

        Bagging(袋装法)通过随机采样训练数据集生成多个基学习器,然后将它们的预测结果进行平均或投票;

        Boosting(提升)则是通过迭代训练基学习器,每一轮都调整数据分布,使得前一轮中被错误分类的样本在下一轮中得到更多关注;

        而Stacking(堆叠)则是将多个基学习器的预测结果作为新的特征输入到元学习器中进行最终的预测。

        这些方法可以应用于各种机器学习任务,如分类、回归和聚类,以提高模型的泛化能力和预测性能。

正文 

01-集成学习简介          

        集成学习是一种机器学习方法,旨在通过组合多个模型的预测结果来提高整体性能。它主要解决了两个问题:高方差和弱模型构建到强模型的转变。集成学习的基本思路是:建模阶段,基于一组独立的训练集,分别建立与之对应的一组回归或分类预测模型。这里的每个预测模型称为基础学习器(Base Learner)。预测阶段,基础学习器将分别给出各自的预测结果。对各预测结果进行平均或投票,确定最终的预测结果。一方面,集成学习可以解决预测模型的高方差。另一方面,集成学习可将一组弱模型联合起来使其成为一个强模型。          

        解决高方差问题高方差是指模型对训练数据的变化敏感,表现为在不同训练集上表现差异较大。集成学习通过组合多个模型,如随机森林或梯度提升树,可以降低模型的方差。这是因为集成学习会在不同的子集上训练多个模型,然后将它们的预测结果进行平均或投票,从而减少单个模型的不稳定性。

        集成学习能够解决高方差问题,其基本理论依据来源于统计学。统计学指出,对来自同一总体、方差等于 2的N个独立的随机样本观测Z _ { 1 } , Z _ { 2 } , \cdots , Z _ { N },其均值Z的方差等于\sigma ^ { 2 } / N,即一组样本观测平均值的方差仅是原方差的1/N,样本观测个数N越大,方差越小。
借鉴该思想,集成学习认为,若能够基于来自同一总体的B个独立的训练集S _ { b } ( b = 1 , 2 , \cdots , B ),建立B个基础学习器,从而得到对X _ { 0 }的方差等于的B个回归预测值\hat { f } ^ { ( 1 ) } ( X _ { 0 } ) , \hat { f } ^ { ( 2 ) } ( X _ { 0 } ) , \cdots , \hat { f } ^ { ( B ) } ( X _ { 0 } ),则B个回归预测值的平均值\hat { f } _ { a v g } ( X _ { 0 } ) = \frac { 1 } { B } \sum _ { i = 1 } ^ { B } \hat { f } ^ { ( i ) } ( X _ { 0 } ),其方差将降低到\sigma ^ { 2 } / B。需特别指出的是,这里的B个预测模型是彼此独立的。
        当然,实际中人们无法获得这B个独立的训练集S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B ),通常会采用某种策略模拟生成B个独立的训练集,并由此建立B个独立的基础学习器,得到对X _ { 0 }的B个回归预测值\hat { f } ^ { * ( 1 ) } ( X _ { 0 } ) , \hat { f } ^ { * ( 2 ) } ( X _ { 0 } ) , \cdots , \hat { f } ^ { * ( B ) } ( X _ { 0 } )X _ { 0 }的最终回归预测结果为\hat { f } _ { a v g } ^ { * } ( X _ { 0 } ) = \frac { 1 } { B } \sum _ { i = 1 } ^ { B } \hat { f } ^ { * } ( i ) ( X _ { 0 } )
        同理,对分类预测问题,最终的分类预测结果是B个分类预测值的“投票”结果,一般为其中的众数类。
        模拟生成B个独立训练集的常见策略是重抽样自举法(Bootstrap)。基于重抽样自举法的常见集成学习法有袋装(Bagging)法和随机森林(Random Forests)。
        集成学习聚焦解决高方差问题,但不关注可能带来的模型过拟合。因此,评价袋装法和随机森林的预测性能时,应尤其关注测试误差。

        从弱模型到强模型的构建:弱模型是指准确率略高于随机猜测的模型,而强模型则是指准确率较高且具有更强泛化能力的模型。集成学习通过结合多个弱模型,例如通过Bagging(自助采样)或Boosting(迭代改进)方法,可以逐步提升模型的性能。在Bagging中,每个模型都在随机子集上训练,然后将它们的预测结果组合起来。在Boosting中,每个模型都尝试纠正前一个模型的错误,从而逐步提高整体性能。

        复杂模型导致高方差以及模型过拟合。为解决这个问题,集成学习的另一种策略是将一组弱模型组成一个“联合委员会”,并最终成为强模型。弱模型一般指比随机猜测的误差略低的模型。
零模型(Zero Model)就是一种典型的弱模型,它是一种只关注输出变量取值本身而不考虑输入变量的模型。例如,零模型对PM2.5浓度的回归预测值,等于训练集中 PM2.5的均值,并不考虑SO2、CO等对PM2.5有重要影响的其他输入变量的取值。再例如,零模型对空气质量等级的分类预测值,等于训练集中空气质量等级的众数类,不考虑 PM2.5、PM10 等对空气质量等级有重要影响的其他输入变量的取值。

        比零模型略好的弱模型考虑了输入变量,但因模型过于简单等原因,训练误差较高且不会出现模型过拟合。借鉴“三个臭皮匠顶上一个诸葛亮”的朴素思想,集成学习认为,若将多个弱模型集成起来,让它们联合预测,将会得到理想的预测效果。

        从弱模型到强模型的常见集成学习法有提升(Boosting)法和梯度提升树等。需特别指出的是,这里的B个弱模型具有顺序(Sequential)相关性。

        总之,集成学习通过组合多个模型的预测结果,有效地解决了高方差问题,并且能够从弱模型构建到强模型,从而提高了机器学习模型的性能和泛化能力。

02-重抽样自举法简介          

        重抽样自举法是模拟生成B个独立训练集的常见策略。基于重抽样自举法的常见的集成学习法有:袋装法和随机森林。
        重抽样自举法,也称0.632自举法。对样本量为N的数据集S,重抽样自举法的基本做法是:对S做有放回的随机抽样,共进行B次,分别得到B个样本容量均为N的随机样本S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B ),称S _ { b } ^ { * }为一个自举样本,B为自举次数。
        对每个样本观测X _ { i },一次被抽中进入S _ { b } ^ { * }的概率为\frac { 1 } { N },未被抽中的概率为1 - \frac { 1 } { N }。当N较大时,N次均未被抽中的概率为( 1 - \frac { 1 } { N } ) ^ { N } \approx \frac { 1 } { e } = 0 . 3 6 8(e是自然对数的基数2.7183)。这意味着整体上有1 - 3 6 . 8 \% = 6 3 . 2 \%的样本观测可以作为自举样本,这也就是重抽样自举法被称为0.632 自举法的原因。
        重抽样自举法在统计学中的最常见应用是估计统计量的标准误(Standard errors)。例如,在没有任何理论假定下,估计线性回归模型中回归系数估计值\hat { \beta } _ { i } ( i = 0 , 1 , \cdots , p )的标准误。具体做法是:首先,基于B个自举样本S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B )分别建立B个回归模型,得到回归系数\beta _ { i }的B个估计值\hat { \beta } _ { i } ^ { * } ( b ) ( b = 1 , 2 , \cdots , B );然后,计算\hat { \beta } _ { i } ^ { * } ( b )的标准差 ( \overline { \beta } _ { i } ^ { * } = \frac { 1 } { B } \sum _ { b = 1 } ^ { B } \hat { \beta } _ { i } ^ { * } ( b ) )作为\hat { \beta } _ { i } ( i = 0 , 1 , \cdots , p )标准差的估计称为标准误,并由此得到回归系数真值的置信区间。
        在机器学习中,重抽样自举法用于模拟生成前述的独立训练集。B个自举样本S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B) 对应B个独立的训练集,后续将被应用于袋装法和随机森林中。

        重抽样自举法(Bootstrap)是一种用于估计统计量的方法,通过从原始数据集中有放回地抽取样本来构建多个新数据集,然后对每个新数据集应用统计方法,最终对结果进行汇总。以下是一个简单的Python代码示例,演示了如何使用Bootstrap方法对数据进行重抽样,并计算均值的置信区间:

        这段代码首先生成了一个包含100个样本的正态分布示例数据,然后定义了一个bootstrap函数,它使用Bootstrap方法从原始数据中重抽样,并计算每个重抽样样本的均值。接着进行了1000次Bootstrap重抽样,计算了样本均值的置信区间,并用直方图可视化了Bootstrap重抽样分布及置信区间。

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']  #解决中文显示乱码问题
plt.rcParams['axes.unicode_minus']=False
# 生成示例数据
np.random.seed(42)
data = np.random.normal(loc=10, scale=2, size=100)

# Bootstrap函数
def bootstrap(data, num_samples):
    sample_means = []
    for _ in range(num_samples):
        sample = np.random.choice(data, size=len(data), replace=True)
        sample_means.append(np.mean(sample))
    return sample_means

# 进行Bootstrap重抽样
bootstrap_means = bootstrap(data, 1000)

# 计算置信区间
confidence_interval = np.percentile(bootstrap_means, [2.5, 97.5])
print("95% Confidence Interval:", confidence_interval)

# 可视化结果
plt.hist(bootstrap_means, bins=30, alpha=0.7, color='b')
plt.axvline(confidence_interval[0], color='r', linestyle='--')
plt.axvline(confidence_interval[1], color='r', linestyle='--')
plt.xlabel('Bootstrap 示例均值')
plt.ylabel('频率')
plt.title('Bootstrap 重采样分布')
plt.savefig("../4.png", dpi=500)
plt.show()

        实例运行结果如下图所示:

 03-Bagging袋装法简介          

        袋装法的英文 Bagging,是 Bootstrap Aggregating 的缩略词。袋装法是一种基于重抽样自举法的常见集成学习策略,在单个学习器具有高方差和低偏差的情况下非常有效。
        袋装法涉及基于B个自举样本S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B )的建模、预测和模型评估,以及输入变量重要性度量等方面。
        袋装法的建模:
        基于B个自举样本S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B)建模的核心是训练B个基础学习器。通常基础学习器是训练误差较低的、相对复杂的模型。回归预测中可以是一般线性模型,K-近邻以及回归树等等。分类预测中可以是Logistic 回归模型、贝叶斯分类器、K-近邻以及分类树等。本章仅特指回归树和分类树。
        袋装法的预测:
        回归预测中,基于B个自举样本S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B )建立回归树,得到X _ { 0 }的B个回归预测值\hat { T } ^ { * } ( b ) ( X _ { 0 } ) , ( b = 1 , 2 , \cdots , B ),其中, \hat { T } ^ { * } ( b )表示第b棵回归树。计算\hat { T } ^ { * } ( b ) ( X _ { 0 } )的均值,得到X _ { 0 }的袋装预测值:
                                                 \hat { f } _ { b a g } ^ { * } ( X _ { 0 } ) = \frac { 1 } { B } \sum _ { b = 1 } ^ { B } { T } ^ { * ( b ) } ( X _ { 0 } )                      
        K分类预测中,基于B个自举样本S _ { b } ^ { * } ( b = 1 , 2 , \cdots , B )建立分类树,得到X _ { 0 }的B个分类预测值\hat { G } ^ { * } ( X _ { 0 } ) = \arg \max \tilde { r } ^ { * } ( b ) ( X _ { 0 } ) , ( k = 1 , 2 , \cdots , K ; b = 1 , 2 , \cdots , B)。计算预测X _ { 0 }属第k类的分类树的占比
\hat { f } _ { b a g } ^ { * } ( X _ { 0 } ) = ( P _ { 1 } ( X _ { 0 } ) , P _ { 2 } ( X _ { 0 } ) , \cdots , P _ { K } ( X _ { 0 } ) ),得到X _ { 0 }的袋装预测值
        即得票数最高的类。需说明的是,二分类预测中通常对预测值等于1和0的B个概率值进行平均,袋装预测值为概率均值最大的类。袋装法工作原理示意图如图所示。


        上图中,基于B个自举样本建立B棵分类回归树,并共同对4个样本观测进行分类预测。投票结果表明,其中3个样本观测应预测为实心类。
        无论是回归预测中求均值,还是分类预测中的投票,本质上都是对基础学习器预测结果,而随自举样本随机性差异而变化的平滑,则是消除随机性影响后的结果。理论上,经平均或投票所得的预测结果是真值的无偏估计。由此计算所得的测试误差也是泛化误差真值的无偏估计。

        袋装法测试误差的估计:
        计算基于袋装法的测试误差时,应特别注意测试误差基于“袋外观测”(OOB)计算的特征。这里,基础学习器\hat { T } ^ { * } ( b )的OOB是未出现在 内的样本观测。计算分类预测的测试误差时,应对每个样本观测X _ { i } ( i = 1 , 2 , \cdots , N ),得到其作为OOB时基础学习器所给出的预测结果。即若X _ { i } ( i = 1 , 2 , \cdots , N)在建模过程中有q ( q < B )次作为OOB观测,则只有q个基础学习器提供预测值,最终预测结果是这个q值的均值或投票。在此基础上计算的误差才是具有OOB 特征的测试误差。
        袋装法中的输入变量重要性度量:
        对于单棵决策树,越接近根节点的输入变量(作为分组变量)其重要性越高。袋装法度量输入变量重要性需基于多棵树计算。一般度量方法是:每个输入变量作为最佳分组变量,都会使输出变量的异质性下降。计算B棵树异质性下降的总和。总和最大值对应的输入变量重要性最高,总和最小值对应的输入变量重要性最低。

        Bagging通过在原始数据集上使用Bootstrap方法构建多个子集,并在每个子集上训练一个基学习器,然后将它们的预测结果进行平均或投票来提高整体性能。以下是一个简单的Python代码示例,演示了如何使用Bagging方法进行集成学习,并通过随机森林进行分类分析:

        这段代码首先加载了鸢尾花数据集,然后将数据集划分为训练集和测试集。接着定义了一个决策树作为基学习器,并使用BaggingClassifier来构建一个Bagging分类器。然后训练了Bagging分类器,并在测试集上进行了预测。最后计算了分类器的准确率,并在二维特征空间可视化了Bagging分类器的决策边界。

from sklearn.datasets import load_iris
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np

# 加载示例数据集
iris = load_iris()
X, y = iris.data[:, :2], iris.target  # 只选取前两个特征便于可视化

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 定义基学习器
base_classifier = DecisionTreeClassifier()

# 定义Bagging分类器
bagging_classifier = BaggingClassifier(base_classifier, n_estimators=10, random_state=42)

# 训练Bagging分类器
bagging_classifier.fit(X_train, y_train)

# 在测试集上进行预测
y_pred = bagging_classifier.predict(X_test)

# 计算准确率
accuracy = np.mean(y_pred == y_test)
print("Accuracy:", accuracy)

# 可视化决策边界
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))

Z = bagging_classifier.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, s=20, edgecolor='k')
plt.xlabel('萼片长度')
plt.ylabel('萼片宽度')
plt.title('装袋分类器决策边界')
plt.savefig("../4.png", dpi=500)
plt.show()

        实例运行结果如下图所示:

04-Random Forests随机森林算法          

        随机森林也是一种基于重抽样自举法的集成学习方法。顾名思义,随机森林是用随机方式建立包含多棵决策树的森林。其中每棵树都是一个基础学习器,“整片”森林对应着集成学习。
        与袋装法类似的是,随机森林中的多棵树将共同参与预测。不同的是,随机森林通过随机,努力使每棵树的“外观”因彼此“看上去不相同”而不相关。
        袋装法可降低预测方差的基本理论是:来自同一总体的、方差等于的B个预测值\sigma ^ { 2 }{ { \sim } T ^ { * } ( b ) } ( X _ { 0 } ),因彼此独立使得其均值\hat { f } _ { b a g } ^ { * } ( X _ { 0 } )的方差降至\sigma ^ { 2 } / B。事实上,这种“独立”往往很难保证,因为袋装法中树之间的差异很小,导致预测结果有很高的一致性。此时,若预测值两两相关系数均等于ρ,则方差等于\rho \sigma ^ { 2 } + \frac { 1 - \rho } { B } \sigma ^ { 2 \Theta }
        可见,随着B的增加第二项趋于0,仅剩下第一项。此时方差的降低取决于相关系数ρ(σ2确定)的大小。若相关系数p较大,方差也会较高。随机森林通过减少预测值的相关性,换言之,通过降低树间的相似性(高相似的决策树必然给出高相关的预测值)的策略来降低方差。
        降低树间相似性的基本策略是采用多样性增强。所谓多样性增强,就是在机器学习过程中增加随机性扰动,包括对训练数据增加随机性扰动,对输入变量增加随机性扰动以及对算法参数增加随机性扰动等。
        随机森林涉及如何实现多样性增强,以及输入变量重要性度量等方面。
        随机森林的实现:
        随机森林采用多样性增强策略,通过对训练数据以及输入变量增加随机性扰动以降低树间的相似性。其中,重抽样自举是实现对训练数据增加随机性扰动的最直接的方法。对输入变量增加随机性扰动的具体实现策略是:决策树建立过程中的当前“最佳”分组变量,是来自输入变量的一个随机子集,中的变量。于是分组变量具有了随机性。多样性增强策略可以使多棵树“看上去不相同”。
        具体讲,需进行b = 1 , 2 , \cdots , B次如下迭代,得到包括B棵树的随机森林。
        第一步,对样本量等于N的数据集进行重抽样自举,得到自举样本S _ { b } ^ { * }
        第二步,基于自举样本S _ { b } ^ { * }建立回归树或分类树\hat { T } ^ { * } ( b )。决策树从根节点开始按如下方式不断生长,直到满足树的预剪枝参数为止:
        1) 个输入变量中随机选择m个输入变量构成输入变量的一个随机子集。通常,


m = [ \sqrt { p } ]或者m = [ \log _ { 2 } p ]。[]表示取整。
        2)从 \Theta _ { b }中确定当前“最佳”分组变量,分组并生成两个子节点。
        第三步,输出包括B棵树\{ \tilde { T } ^ { * } ( b ) \} ^ { B }的随机森林。
        第四步,预测。回归预测结果为\hat { f } _ { r f } ^ { * } ( X _ { 0 } ) = \frac { 1 } { B } \sum _ { b = 1 } ^ { B } \tilde { T } ^ { * } ( b ) ( X _ { 0 } );分类预测结果为得票数最高的类。
        随机森林的评价也需计算基于OOB的测试误差。
        随机森林中的输入变量重要性度量:
        随机森林通过添加随机化噪声的方式度量输入变量的重要性。基本思路是:若某输入变量对输出变量预测有重要作用,那么在模型OOB的该输入变量上添加随机噪声,将显著影响模型OOB的计算结果。首先,对\hat { T } ^ { * } ( b ) ( b = 1 , 2 , \cdots , B )计算基于OOB的测试误差,记为e ( \hat { T } ^ { * } ( b ) )。然后,为测度第j个输入变量对输出变量的重要性,进行如下计算:
        1)随机打乱\hat { T } ^ { * } ( b)的OOB在第j个输入变量上的取值顺序,重新计算\hat { T } ^ { * } ( b )的基于OOB的误差,记为e ^ { j } ( \hat { I } ^ { * } ( b ))
        2)计算第j个输入变量添加噪声前后{ { \sim } 1 } ^ { * } ( b )的OOB 误差的变化: C _ { T ^ { \prime } \cdot ( b ) } ^ { j } = e ^ { j } ( \tilde { T } ^ { * } ( b ) )-e ( \hat { T } ^ { * } ( b ) )
        重复上述步骤B次,得到B个C _ { T ^ { \prime } ( b ) } ^ { j } , ( b = 1 , 2 , \cdots , B )。计算均值\frac { 1 } { B } \sum _ { b = 1 } ^ { B } c _ { \tilde { I } _ { m } ^ { j } } v ^ { \prime },它是第j个输入变量添加噪声后所导致的随机森林总的OOB误差变化,变化值越大,第j个输入变量越重要。

        随机森林(Random Forest)是一种基于集成学习的机器学习算法,它通过构建多个决策树并结合它们的预测结果来提高整体性能。随机森林通过引入随机性来提升模型的泛化能力,其中包括随机选择特征子集、随机选择样本和树的生长等。以下是一个使用随机森林进行回归预测的Python示例代码,并可视化分析预测结果:

        这段代码加载了波士顿房价数据集,并将其划分为训练集和测试集。然后定义了一个随机森林回归模型,并训练了该模型。接着在测试集上进行了房价预测,并通过散点图可视化了预测结果。散点图中每个点的横坐标代表真实房价,纵坐标代表模型预测的房价,越接近对角线表示预测结果越准确。

from sklearn.datasets import load_boston
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np

# 加载波士顿房价数据集
boston = load_boston()
X, y = boston.data, boston.target

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 定义随机森林回归模型
rf_regressor = RandomForestRegressor(n_estimators=100, random_state=42)

# 训练随机森林回归模型
rf_regressor.fit(X_train, y_train)

# 在测试集上进行预测
y_pred = rf_regressor.predict(X_test)

# 可视化预测结果
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred, color='blue', alpha=0.7)  # 透明度调整
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=2)
plt.xlabel('真实值', fontsize=12)  # 调整字体大小
plt.ylabel('预测值', fontsize=12)
plt.title('随机森林回归结果', fontsize=14)  # 调整标题大小
plt.xticks(fontsize=10)  # 调整刻度字体大小
plt.yticks(fontsize=10)
plt.grid(True)  # 添加网格线
plt.tight_layout()  # 调整布局,防止重叠
plt.savefig("../4.png", dpi=500)
plt.show()

        实例运行结果如下图所示:

05-基于Bagging方法和RF算法对PM2.5浓度回归预测          

        本小节将基于空气质量监测数据,分别采用集成学习对PM2.5浓度进行回归预测,从而说明集成学习方法的优秀预测性能和不同方法的特点。本节应用集成学习的方法,再次对案例进行剖析,以说明袋装法和随机森林对降低方差的作用。

      (1)袋装法和随机森林对降低方差的作用
        决策树具有“天然”高方差的特点。集成学习中的袋装法和随机森林,能够很好地克服这个问题。本节将首先直观展现决策树高方差的特点;然后,分别采用袋装法和随机森林,建立PM2.5浓度的回归预测模型,计算OOB误差和预测方差;最后,将计算结果可视化。
        a、建立PM2.5浓度的回归预测,对比不同模型的预测方差
        以下基于10-折交叉验证法,分别建立PM2.5 浓度预测的一般线性回归模型,以及树深度等于3的回归树模型。计算两个模型对新样本观测X0多个预测结果的均值和方差,并绘制可视化图形。        

        这里基于空气质量监测数据,采用二元线性回归模型和树深度等于3的决策树,建立对PM2.5浓度的预测模型,并对比线性模型和回归树的方差。 1、采用10-折交叉验证法,分别构建回归模型和决策树各10个。 2、分别基于回归模型和决策树各10个预测模型,预测输入变量取均值X0时的PM2.5浓度。 3、分别计算回归模型和决策树各10个预测值直方图,并计算方差。结果表明决策树具有高方差的特点。
        1)读入空气质量监测数据。数据预处理。确定输入变量(SO2、CO)和输出变量(PM2.5)。确定待预测的新样本观测X _ { 0 }
        2)指定建立用于预测PM2.5的树深度等于3的回归树和一般线性回归模型。

        3)采用10折交叉验证,依次基于10个存在随机性差异的训练集,分别建立一般线性回归模型和回归树,并给出对X _ { 0 } 的各10个预测结果。
        4)分别绘制一般线性模型和回归树预测结果的箱线图。所得图形如下图所示。图形显示,回归树的箱体高度明显高于线性模型,决策树的方差明显大于线性模型。事实上,树深度越大的决策树,其高方差的特征越突出。

#本章需导入的模块
import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings(action = 'ignore')
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']  #解决中文显示乱码问题
plt.rcParams['axes.unicode_minus']=False
from sklearn.model_selection import train_test_split,KFold,cross_val_score
from sklearn import tree
import sklearn.linear_model as LM
from sklearn import ensemble
from sklearn.datasets import make_classification,make_circles,make_regression
from sklearn.metrics import zero_one_loss,r2_score,mean_squared_error
import xgboost as xgb


data=pd.read_excel('北京市空气质量数据.xlsx')
data=data.replace(0,np.NaN)
data=data.dropna()
data=data.loc[(data['PM2.5']<=200) & (data['SO2']<=20)]
X=data[['SO2','CO']]
Y=data['PM2.5']
X0=np.array(X.mean()).reshape(1,-1)

modelDTC = tree.DecisionTreeRegressor(max_depth=3,random_state=123)
modelLR=LM.LinearRegression()
model1,model2=[],[]    
kf = KFold(n_splits=10,shuffle=True,random_state=123)
for train_index, test_index in kf.split(X):  
    Ntrain=len(train_index)
    XKtrain=X.iloc[train_index]
    YKtrain=Y.iloc[train_index]      
    modelLR.fit(XKtrain,YKtrain)
    modelDTC.fit(XKtrain,YKtrain)
    model1.append(float(modelLR.predict(X0)))
    model2.append(float(modelDTC.predict(X0)))

plt.boxplot(x=model1,sym='rd',patch_artist=True,boxprops={'color':'blue','facecolor':'pink'},
            labels ={"线性模型\n方差=%.3f"%np.var(model1)},showfliers=False) 
plt.boxplot(x=model2,sym='rd',positions=[2],patch_artist=True,boxprops={'color':'blue','facecolor':'pink'},
            labels ={"回归树\n方差=%.3f"%np.var(model2)},showfliers=False) 
plt.title("线性模型和回归树的方差对比")
plt.savefig("../4.png", dpi=500)

        实例运行结果如下图所示:

        b、采用袋装法和随机森林法,建立PM2.5浓度的回归预测
        采用袋装法和随机森林预测PM2.5 浓度。计算 OOB 误差,并保存不同迭代次数下X _ { 0}的预测结果。具体代码如下所示。

        1)计算前述单棵回归树的10折交叉验证下的测试误差。
        2)创建4个列表,分别存储不同迭代次数下,袋装法和随机森林对X _ { 0 }的预测结果和OOB误差。
        3)指定迭代10次、11次·····199次,共190个迭代方案。在每个迭代方案下,均依次采用袋装法和随机森林,计算OOB误差,得到对X _ { 0 }的预测结果。
        c、袋装法和随机森林法预测效果的可视化
        对上述模型的计算结果进行可视化,比对单棵回归树以及不同集成学习算法的特点。具体代码如下所示。

        1)绘制单棵回归树10折交叉验证下的测试误差均值线。
        2)绘制不同迭代次数下袋装法的OOB测试误差曲线并显示对X _ { 0 }的预测方差,如图所示。图形显示随着迭代次数增加,袋装法回归树的测试误差“断崖”式下降并低于单棵回归树,泛化能力优于单棵回归树。同时,袋装法回归树(Bagging 回归树)的方差显著小于图中单棵回归树的方差,对减少方差有较好的作用。
        3)绘制不同迭代次数下袋装法和随机森林的OOB测试误差曲线,并显示对X。的预测方差。
        4)绘制随机森林中变量重要性的条形图,并标出重要性得分。变量重要性的信息存储在.feature_importances_属性中。所得图形如图所示。图形显示,两种集成学习的误差在大约50次迭代后基本保持水平不变,但随机森林的测试误差大于袋装法。两种集成学习策略对降低方差都有较好的作用。

#本章需导入的模块
import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings(action = 'ignore')
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']  #解决中文显示乱码问题
plt.rcParams['axes.unicode_minus']=False
from sklearn.model_selection import train_test_split,KFold,cross_val_score
from sklearn import tree
import sklearn.linear_model as LM
from sklearn import ensemble
from sklearn.datasets import make_classification,make_circles,make_regression
from sklearn.metrics import zero_one_loss,r2_score,mean_squared_error
import xgboost as xgb

dtrErr=1-cross_val_score(modelDTC,X,Y,cv=10,scoring='r2')
BagY0=[]
bagErr=[]
rfErr=[]
rfY0=[]
for b in np.arange(10,200):
    Bag=ensemble.BaggingRegressor(base_estimator=modelDTC,n_estimators=b,oob_score=True,random_state=123,bootstrap=True)
    Bag.fit(X,Y)
    bagErr.append(1-Bag.oob_score_)
    BagY0.append(float(Bag.predict(X0)))
    RF=ensemble.RandomForestRegressor(n_estimators=b,oob_score=True,random_state=123,bootstrap=True)
    RF.fit(X,Y)      
    rfErr.append(1-RF.oob_score_)     
    rfY0.append(float(RF.predict(X0)))


plt.axhline(y=dtrErr.mean(),linestyle='--',label='回归树')
plt.plot(np.arange(10,200),bagErr,linestyle='-',label='Bagging回归树(方差=%.3f)'%np.var(BagY0))
plt.title("回归树和Bagging回归树")
plt.xlabel("树的棵树B")
plt.ylabel("测试误差")
plt.legend()
plt.show()

fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(12,4))
axes[0].plot(np.arange(10,200),bagErr,linestyle='-',label='Bagging回归树(方差=%.3f)'%np.var(BagY0))
axes[0].plot(np.arange(10,200),rfErr,linestyle='--',label='随机森林(方差=%.3f)'%np.var(rfY0))
axes[0].set_title("Bagging回归树和随机森林")
axes[0].set_xlabel("树的棵树B")
axes[0].set_ylabel("测试误差")
axes[0].legend()
axes[1].barh(y=(1,2),width=RF.feature_importances_,tick_label=X.columns)
axes[1].set_title("输入变量的重要性")
for x,y in enumerate(RF.feature_importances_):    
    axes[1].text(y+0.01,x+1,'%s' %round(y,3),ha='center')

        示例运行结果如下图所示:

      (2)袋装法和随机森林对降低预测误差的作用
        调整预测模型。为充分发挥随机森林,可引入输入变量多样性增强的优势,增加输入变量(输入变量包括SO2、CO、NO2、O3),重新建立PM2.5浓度的回归预测模型。
       a、利用旁置法和5-折交叉验证法,确定单棵回归树的最佳树深度参数
增加输入变量,重新建立单棵回归树。利用旁置法和5-折交叉验证法,确定单棵回归树的最佳树深度参数。代码如下所示。

        1)确定输入变量。确定新样本观测X _ { 0 }。将数据集划分为训练集和测试集。创建用来存储训练误差和测试误差的列表。
        2)建立不同树深度的回归树,计算其训练误差、基于旁置法的测试误差和5折交叉验证。

        3)绘制回归树的训练误差、基于旁置法的测试误差和5折交叉验证的测试误差随树深度增加的变化折线图,如图所示。

#本章需导入的模块
import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings(action = 'ignore')
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']  #解决中文显示乱码问题
plt.rcParams['axes.unicode_minus']=False
from sklearn.model_selection import train_test_split,KFold,cross_val_score
from sklearn import tree
import sklearn.linear_model as LM
from sklearn import ensemble
from sklearn.datasets import make_classification,make_circles,make_regression
from sklearn.metrics import zero_one_loss,r2_score,mean_squared_error
import xgboost as xgb


X=data[['SO2','CO','NO2','O3']]
X0=np.array(X.mean()).reshape(1,-1)
X_train, X_test, Y_train, Y_test = train_test_split(X,Y,train_size=0.70, random_state=123)
trainErr=[]
testErr=[]
CVErr=[]
K=np.arange(2,15)
for k in K:
    modelDTC = tree.DecisionTreeRegressor(max_depth=k,random_state=123)
    modelDTC.fit(X_train,Y_train)
    trainErr.append(1-modelDTC.score(X_train,Y_train))
    testErr.append(1-modelDTC.score(X_test,Y_test))
    Err=1-cross_val_score(modelDTC,X,Y,cv=5,scoring='r2')   
    CVErr.append(Err.mean())    

fig = plt.figure(figsize=(15,6))
ax1 = fig.add_subplot(121) 
ax1.grid(True, linestyle='-.')
ax1.plot(K,trainErr,label="训练误差",marker='o',linestyle='-')
ax1.plot(K,testErr,label="旁置法测试误差",marker='o',linestyle='-.')
ax1.plot(K,CVErr,label="5-折交叉验证误差",marker='o',linestyle='--')
ax1.set_xlabel("树深度")
ax1.set_ylabel("误差(1-R方)")
ax1.set_title('树深度和误差')
ax1.legend()

        实例运行结果如下图所示: 


        为进一步说明袋装策略决策树和随机森林的预测效果优于单棵决策树,首先增加输入变量个数,增加单棵决策树的树深度,计算旁置法和5-折交叉验证的测试误差。 2、依据测试误差最低为原则,确定单棵决策树的树深度等于5。代码如下:

        为对比袋装策略决策树、随机森林、单棵决策树的预测效果,计算迭代次数在10至200之间时,袋装策略回归树和随机森林的基于OOB的测试误差,以及对X0的预测误差。此外,计算单棵决策树的10-折交叉验证测试误差。

        绘制上述计算结果的相关图形。可见,增加了输入变量个数后,随机森林的测试误差低于袋装策略下的测试误差。可见,随机森林给输入变量增加的随机性扰动,有效降低了测试误差,发挥了随机森林算法的优势。此外,CO对预测PM2.5浓度有最为重要的影响。

#本章需导入的模块
import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings(action = 'ignore')
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']  #解决中文显示乱码问题
plt.rcParams['axes.unicode_minus']=False
from sklearn.model_selection import train_test_split,KFold,cross_val_score
from sklearn import tree
import sklearn.linear_model as LM
from sklearn import ensemble
from sklearn.datasets import make_classification,make_circles,make_regression
from sklearn.metrics import zero_one_loss,r2_score,mean_squared_error
import xgboost as xgb

modelDTC = tree.DecisionTreeRegressor(max_depth=5,random_state=123)
dtrErr=1-cross_val_score(modelDTC,X,Y,cv=10,scoring='r2')
BagY0=[]
bagErr=[]
rfErr=[]
rfY0=[]
for b in np.arange(10,200):
    Bag=ensemble.BaggingRegressor(base_estimator=modelDTC,n_estimators=b,oob_score=True,random_state=123,bootstrap=True)
    Bag.fit(X,Y)
    bagErr.append(1-Bag.oob_score_)
    BagY0.append(float(Bag.predict(X0)))
    RF=ensemble.RandomForestRegressor(n_estimators=b,oob_score=True,random_state=123,bootstrap=True,max_features="sqrt")
    RF.fit(X,Y)      
    rfErr.append(1-RF.oob_score_)     
    rfY0.append(float(RF.predict(X0)))


fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(12,4))
axes[0].axhline(y=dtrErr.mean(),linestyle='-.',label='回归树')
axes[0].plot(np.arange(10,200),bagErr,linestyle='-',label='Bagging回归树(方差=%.3f)'%np.var(BagY0))
axes[0].plot(np.arange(10,200),rfErr,linestyle='--',label='随机森林(方差=%.3f)'%np.var(rfY0))
axes[0].set_title("回归树、Bagging回归树和随机森林")
axes[0].set_xlabel("树的棵树B")
axes[0].set_ylabel("测试误差")
axes[0].legend()

axes[1].barh(y=(1,2,3,4),width=RF.feature_importances_,tick_label=X.columns)
axes[1].set_title("输入变量的重要性")
for x,y in enumerate(RF.feature_importances_):    
    axes[1].text(y+0.01,x+1,'%s' %round(y,3),ha='center')

        示例运行结果如下图所示:

总结 

       集成学习是一种将多个模型组合在一起以提高预测性能的机器学习方法。其中,Bagging 方法和随机森林算法都是基于集成学习思想的流行算法之一。以下是它们的简要总结:

        Bagging 方法(Bootstrap Aggregating):

        Bagging 方法是一种并行式的集成学习方法,通过对训练数据集进行有放回的随机抽样(自助采样),生成多个子数据集。

        每个子数据集用于训练一个基学习器,如决策树、SVM 等。这些基学习器相对独立,可以并行训练。

        预测时,Bagging 方法通过将每个基学习器的预测结果进行平均或投票来获得最终集成模型的预测结果。

        Bagging 方法能够减少过拟合,提高模型的稳定性和泛化能力。

        随机森林(Random Forest):

        随机森林是基于 Bagging 方法的一种改进算法,使用多个决策树来构建集成模型。

        在随机森林中,每棵决策树的训练集也是通过随机抽样得到的,但不同的是,每次分裂节点时都会随机选择一个特征子集进行分裂,而非使用全部特征。

        随机森林通过引入随机性,增加了各个基学习器之间的差异性,提高了模型的多样性和泛化能力。

        随机森林在处理高维数据、大数据集和具有噪声特征的数据上表现优秀,且对参数的选择相对不敏感。

        综上所述:

        Bagging 方法和随机森林都是基于集成学习思想的算法,通过组合多个基学习器来提高模型性能。

        Bagging 方法是一种集成多个相互独立的基学习器的方法,而随机森林在 Bagging 的基础上引入了特征随机选择,进一步增加了模型的多样性和鲁棒性。

        随机森林通常对于高维数据集和具有噪声特征的数据有很好的表现,并且易于实现和调节。

        通过利用 Bagging 方法和随机森林算法,我们可以构建更稳健、高性能的机器学习模型,并在实际问题中取得较好的预测效果。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一伦明悦

感谢,您的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值