4.2 模型集成方法深入


文档摘要

4.2 模型集成方法深入 Scikit-learn 高级主题:模型集成方法深入详解与实践 4.2 模型集成方法深入 模型集成方法是机器学习中一种强大的技术,它通过组合多个弱学习器来创建一个强大的模型。这种方法的核心思想是“集思广益”,即多个模型的集体智慧通常优于任何一个单独的模型。在 Scikit-learn 中,模型集成方法得到了广泛的支持,提供了多种算法和工具,可以帮助我们构建高效且鲁棒的预测模型。 本文将深入探讨 Scikit-learn 中主要的模型集成方法,包括 Bagging、Boosting、Stacking 和 Voting,并结合实际代码示例,详细讲解其原理、应用和参数调优。 4.2.

4.2 模型集成方法深入

Scikit-learn 高级主题:模型集成方法深入详解与实践

4.2 模型集成方法深入

模型集成方法是机器学习中一种强大的技术,它通过组合多个弱学习器来创建一个强大的模型。这种方法的核心思想是“集思广益”,即多个模型的集体智慧通常优于任何一个单独的模型。在 Scikit-learn 中,模型集成方法得到了广泛的支持,提供了多种算法和工具,可以帮助我们构建高效且鲁棒的预测模型。

本文将深入探讨 Scikit-learn 中主要的模型集成方法,包括 Bagging、Boosting、Stacking 和 Voting,并结合实际代码示例,详细讲解其原理、应用和参数调优。

4.2.1 Bagging (Bootstrap Aggregating)

原理详解:

Bagging (Bootstrap Aggregating,自助抽样集成) 是一种并行集成方法。其核心思想是通过自助抽样 (Bootstrap Sampling) 的方法,从原始训练集中有放回地抽取多个子集,然后基于每个子集训练一个基学习器。最后,对于分类问题,通常采用投票法 (Voting) 决定最终预测结果;对于回归问题,则采用平均法 (Averaging) 决定最终预测结果。

Bagging 的关键在于 自助抽样基学习器的独立性。自助抽样保证了每个基学习器训练数据的随机性和差异性,而基学习器的独立性则确保了集成模型的泛化能力。Bagging 主要关注于降低模型的方差 (Variance)。

Scikit-learn 实现:

Scikit-learn 提供了 BaggingClassifierBaggingRegressor 类来实现 Bagging 方法。这两个类的主要参数包括:

  • estimator: 基学习器,可以是任何 Scikit-learn 的分类器或回归器 (例如 DecisionTreeClassifier, DecisionTreeRegressor, KNeighborsClassifier 等)。

  • n_estimators: 基学习器的数量,即集成模型中包含多少个基学习器。

  • max_samples: 每个基学习器训练时抽取的样本数量或比例。可以是整数 (样本数) 或浮点数 (样本比例)。

  • max_features: 每个基学习器训练时抽取的特征数量或比例。可以是整数 (特征数) 或浮点数 (特征比例)。

  • bootstrap: 是否进行自助抽样。默认为 True

  • bootstrap_features: 是否对特征进行自助抽样。默认为 False

  • random_state: 随机种子,用于控制抽样的随机性,保证结果的可复现性。

代码实践:

我们以分类任务和回归任务为例,演示 BaggingClassifierBaggingRegressor 的使用。

分类任务示例 (使用 BaggingClassifier):

import numpy as np from sklearn.model_selection import train_test_split from sklearn.ensemble import BaggingClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score # 加载 Iris 数据集 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) # 初始化 BaggingClassifier,基学习器为决策树 bagging_clf = BaggingClassifier( estimator=DecisionTreeClassifier(), # 基学习器 n_estimators=100, # 基学习器数量 max_samples=0.8, # 每个基学习器使用 80% 的样本 max_features=0.8, # 每个基学习器使用 80% 的特征 bootstrap=True, # 启用自助抽样 bootstrap_features=False, # 不对特征进行自助抽样 random_state=42 ) # 训练模型 bagging_clf.fit(X_train, y_train) # 预测 y_pred = bagging_clf.predict(X_test) # 评估模型 accuracy = accuracy_score(y_test, y_pred) print(f"BaggingClassifier Accuracy: {accuracy:.4f}")

回归任务示例 (使用 BaggingRegressor):

from sklearn.ensemble import BaggingRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.datasets import load_boston from sklearn.metrics import mean_squared_error, r2_score # 加载 Boston 房价数据集 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.3, random_state=42) # 初始化 BaggingRegressor,基学习器为决策树 bagging_reg = BaggingRegressor( estimator=DecisionTreeRegressor(), # 基学习器 n_estimators=100, # 基学习器数量 max_samples=0.8, # 每个基学习器使用 80% 的样本 max_features=0.8, # 每个基学习器使用 80% 的特征 bootstrap=True, # 启用自助抽样 bootstrap_features=False, # 不对特征进行自助抽样 random_state=42 ) # 训练模型 bagging_reg.fit(X_train, y_train) # 预测 y_pred = bagging_reg.predict(X_test) # 评估模型 mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"BaggingRegressor MSE: {mse:.4f}") print(f"BaggingRegressor R^2: {r2:.4f}")

参数调优:

  • n_estimators (基学习器数量): 增加 n_estimators 通常可以提升模型的性能,但计算成本也会增加。需要通过交叉验证等方法找到合适的平衡点。

  • max_samplesmax_features (抽样比例): 调整这两个参数可以控制基学习器的多样性。较小的抽样比例会增加基学习器的差异性,但也可能导致单个基学习器的性能下降。

  • bootstrapbootstrap_features (自助抽样): 通常建议启用自助抽样以增加模型的随机性和泛化能力。

  • estimator (基学习器): Bagging 可以使用各种基学习器。通常,决策树是常用的基学习器,因为它具有较高的灵活性和易于理解的特点。也可以尝试其他模型,例如 KNN 或线性模型。

优缺点:

  • 优点:

    • 降低方差,提高模型的稳定性和泛化能力。

    • 可以并行训练,提高训练效率。

    • 对噪声数据和异常值相对鲁棒。

    • 易于实现和使用。

  • 缺点:

    • 对于偏差 (Bias) 较高的基学习器,Bagging 的效果可能有限。

    • 集成模型的解释性相对较差。

4.2.2 Boosting (提升方法)

原理详解:

Boosting (提升方法) 是一种串行集成方法。与 Bagging 不同,Boosting 的基学习器之间存在依赖关系。其核心思想是通过迭代的方式训练一系列基学习器,每个基学习器都尝试纠正前一个基学习器的错误。Boosting 通过 加权样本调整权重 的方式,使得后续的基学习器更加关注之前模型预测错误的样本,从而逐步提升模型的性能。Boosting 主要关注于降低模型的偏差 (Bias)。

Boosting 的代表性算法包括 AdaBoost (Adaptive Boosting) 和 Gradient Boosting (梯度提升)。

4.2.2.1 AdaBoost (自适应提升)

原理详解:

AdaBoost (Adaptive Boosting,自适应提升) 是一种经典的 Boosting 算法。其核心思想是:

  1. 初始化样本权重: 开始时,所有训练样本的权重相等。

  2. 迭代训练基学习器: 在每一轮迭代中,基于带有权重的训练样本训练一个基学习器。

  3. 计算基学习器权重: 根据基学习器在训练集上的错误率,计算该基学习器的权重。错误率越低,权重越高。

  4. 更新样本权重: 根据基学习器的预测结果,更新样本的权重。对于被正确分类的样本,降低其权重;对于被错误分类的样本,提高其权重。

  5. 集成模型: 将所有基学习器进行加权组合,得到最终的集成模型。预测时,根据基学习器的权重进行加权投票 (分类) 或加权平均 (回归)。

AdaBoost 的“自适应性”体现在样本权重的调整上,使得后续的基学习器能够更加关注之前模型预测错误的样本,从而逐步提升模型的性能。

Scikit-learn 实现:

Scikit-learn 提供了 AdaBoostClassifierAdaBoostRegressor 类来实现 AdaBoost 算法。这两个类的主要参数包括:

  • estimator: 基学习器,通常使用弱学习器,例如深度较浅的决策树 (通常是决策树桩,即深度为 1 的决策树)。

  • n_estimators: 基学习器的数量,即迭代次数。

  • learning_rate: 学习率,用于控制每个基学习器的权重缩减幅度,防止过拟合。较小的学习率通常需要更多的基学习器。

  • algorithm: AdaBoost 算法的变体,可选 'SAMME' (用于多分类) 和 'SAMME.R' (基于概率估计,通常效果更好)。

  • random_state: 随机种子。

代码实践:

分类任务示例 (使用 AdaBoostClassifier):

from sklearn.ensemble import AdaBoostClassifier from sklearn.tree import DecisionTreeClassifier # ... (加载 Iris 数据集,与 Bagging 示例相同) ... # 初始化 AdaBoostClassifier,基学习器为决策树桩 adaboost_clf = AdaBoostClassifier( estimator=DecisionTreeClassifier(max_depth=1), # 基学习器为决策树桩 n_estimators=50, # 基学习器数量 learning_rate=1.0, # 学习率 algorithm='SAMME.R', # 使用 SAMME.R 算法 random_state=42 ) # 训练模型 adaboost_clf.fit(X_train, y_train) # 预测和评估 (与 Bagging 示例相同) y_pred = adaboost_clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"AdaBoostClassifier Accuracy: {accuracy:.4f}")

回归任务示例 (使用 AdaBoostRegressor):

from sklearn.ensemble import AdaBoostRegressor from sklearn.tree import DecisionTreeRegressor # ... (加载 Boston 房价数据集,与 Bagging 示例相同) ... # 初始化 AdaBoostRegressor,基学习器为决策树桩 adaboost_reg = AdaBoostRegressor( estimator=DecisionTreeRegressor(max_depth=3), # 基学习器为决策树 n_estimators=50, # 基学习器数量 learning_rate=0.1, # 学习率 random_state=42 ) # 训练模型 adaboost_reg.fit(X_train, y_train) # 预测和评估 (与 Bagging 示例相同) y_pred = adaboost_reg.predict(X_test) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"AdaBoostRegressor MSE: {mse:.4f}") print(f"AdaBoostRegressor R^2: {r2:.4f}")

参数调优:

  • n_estimators (基学习器数量): 与 Bagging 类似,增加 n_estimators 可以提升性能,但计算成本也会增加。需要通过交叉验证等方法找到合适的平衡点。

  • learning_rate (学习率): 学习率控制了每个基学习器的权重缩减幅度。较小的学习率可以提高模型的鲁棒性,但也可能需要更多的基学习器。通常需要与 n_estimators 联合调优。

  • estimator (基学习器): AdaBoost 通常使用弱学习器,例如决策树桩。选择合适的基学习器和其复杂度 (例如决策树的深度) 也很重要。

优缺点:

  • 优点:

    • 降低偏差,提高模型的精度。

    • 对异常值不敏感。

    • 实现简单,易于理解。

  • 缺点:

    • 对噪声数据敏感,容易受到噪声的干扰。

    • 对弱学习器的选择较为敏感,如果弱学习器太弱,可能导致性能不佳。

    • Boosting 算法是串行的,训练时间相对较长。

4.2.2.2 Gradient Boosting (梯度提升)

原理详解:

Gradient Boosting (梯度提升) 是另一种强大的 Boosting 算法。它与 AdaBoost 的主要区别在于,Gradient Boosting 通过 梯度下降 的方法来优化模型。Gradient Boosting 的核心思想是:

  1. 初始化模型: 通常用一个常数模型初始化,例如平均值 (回归) 或对数几率 (分类)。

  2. 迭代训练基学习器: 在每一轮迭代中,计算当前模型预测值与真实值之间的残差 (负梯度)。然后,训练一个新的基学习器来拟合这个残差。

  3. 更新模型: 将新的基学习器添加到集成模型中,并乘以一个学习率进行缩放。

  4. 重复迭代: 重复步骤 2 和 3,直到达到预定的迭代次数或满足停止条件。

Gradient Boosting 的关键在于 负梯度拟合。每一轮迭代都尝试拟合当前模型的残差,从而逐步减小损失函数,提升模型的性能。Gradient Boosting 可以使用各种损失函数,例如平方误差 (回归)、对数损失 (分类) 等,因此具有很强的灵活性。

Scikit-learn 实现:

Scikit-learn 提供了 GradientBoostingClassifierGradientBoostingRegressor 类来实现 Gradient Boosting 算法。这两个类的主要参数包括:

  • n_estimators: 基学习器的数量 (迭代次数)。

  • learning_rate: 学习率。

  • max_depth: 基学习器 (通常是决策树) 的最大深度,控制模型的复杂度。

  • min_samples_split: 内部节点再划分所需最小样本数。

  • min_samples_leaf: 叶节点最小样本数。

  • subsample: 子采样比例,用于随机梯度提升,可以降低方差,防止过拟合。

  • max_features: 特征采样比例,用于随机特征子空间,可以增加模型的随机性。

  • loss: 损失函数,例如 'ls' (最小二乘,回归), 'deviance' (逻辑回归,分类), 'exponential' (AdaBoost 损失,分类) 等。

  • random_state: 随机种子。

代码实践:

分类任务示例 (使用 GradientBoostingClassifier):

from sklearn.ensemble import GradientBoostingClassifier # ... (加载 Iris 数据集,与 Bagging 示例相同) ... # 初始化 GradientBoostingClassifier gb_clf = GradientBoostingClassifier( n_estimators=100, # 基学习器数量 learning_rate=0.1, # 学习率 max_depth=3, # 决策树最大深度 subsample=0.8, # 子采样比例 random_state=42 ) # 训练模型 gb_clf.fit(X_train, y_train) # 预测和评估 (与 Bagging 示例相同) y_pred = gb_clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"GradientBoostingClassifier Accuracy: {accuracy:.4f}")

回归任务示例 (使用 GradientBoostingRegressor):

from sklearn.ensemble import GradientBoostingRegressor # ... (加载 Boston 房价数据集,与 Bagging 示例相同) ... # 初始化 GradientBoostingRegressor gb_reg = GradientBoostingRegressor( n_estimators=100, # 基学习器数量 learning_rate=0.1, # 学习率 max_depth=3, # 决策树最大深度 subsample=0.8, # 子采样比例 random_state=42 ) # 训练模型 gb_reg.fit(X_train, y_train) # 预测和评估 (与 Bagging 示例相同) y_pred = gb_reg.predict(X_test) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"GradientBoostingRegressor MSE: {mse:.4f}") print(f"GradientBoostingRegressor R^2: {r2:.4f}")

参数调优:

  • n_estimatorslearning_rate (基学习器数量和学习率): 这两个参数通常需要联合调优。较小的学习率通常需要更多的基学习器才能达到相同的性能。

  • max_depth (决策树最大深度): 控制模型的复杂度。较小的 max_depth 可以降低模型的方差,防止过拟合,但可能降低模型的精度。

  • subsample (子采样比例): 控制随机梯度提升的程度。较小的 subsample 可以降低方差,但可能增加偏差。

  • min_samples_splitmin_samples_leaf (节点划分和叶节点样本数): 用于控制决策树的剪枝,防止过拟合。

  • max_features (特征采样比例): 控制特征子空间的随机性,可以增加模型的泛化能力。

优缺点:

  • 优点:

    • 精度高,通常优于 AdaBoost 和 Bagging。

    • 灵活性强,可以使用各种损失函数和基学习器。

    • 可以处理各种类型的数据,包括数值型和类别型特征。

    • 对缺失值和异常值有一定的鲁棒性。

  • 缺点:

    • 训练时间较长,尤其是当数据量较大时。

    • 参数较多,调优相对复杂。

    • 容易过拟合,需要仔细调参和使用正则化技术 (例如子采样、剪枝)。

    • 模型解释性相对较差。

4.2.3 Random Forest (随机森林)

原理详解:

Random Forest (随机森林) 是一种基于决策树的 Bagging 集成方法。它在 Bagging 的基础上,进一步引入了 随机特征选择。Random Forest 的核心思想是:

  1. 自助抽样: 从原始训练集中有放回地抽取多个子集。

  2. 随机特征选择: 在每个决策树的节点划分时,随机选择一部分特征进行候选特征集,然后从候选特征集中选择最优特征进行划分。

  3. 构建决策树: 基于每个子集和随机选择的特征,构建决策树。

  4. 集成模型: 将所有决策树集成起来,对于分类问题,采用投票法;对于回归问题,采用平均法。

Random Forest 的 “随机性” 体现在两个方面: 样本抽样的随机性 (Bagging) 和 特征选择的随机性 (随机特征子空间)。这双重随机性使得 Random Forest 集成模型的泛化能力更强,且对过拟合的抵抗能力更强。Random Forest 主要关注于降低模型的方差,同时在一定程度上也降低了偏差。

Scikit-learn 实现:

Scikit-learn 提供了 RandomForestClassifierRandomForestRegressor 类来实现 Random Forest 算法。这两个类的主要参数包括:

  • n_estimators: 决策树的数量。

  • max_depth: 决策树的最大深度。

  • min_samples_split: 内部节点再划分所需最小样本数。

  • min_samples_leaf: 叶节点最小样本数。

  • max_features: 每个决策树节点划分时考虑的最大特征数。可以是 'auto', 'sqrt', 'log2', 整数或浮点数。'auto' 等价于 'sqrt' (分类) 或所有特征 (回归)。

  • bootstrap: 是否进行自助抽样。默认为 True

  • random_state: 随机种子。

代码实践:

分类任务示例 (使用 RandomForestClassifier):

from sklearn.ensemble import RandomForestClassifier # ... (加载 Iris 数据集,与 Bagging 示例相同) ... # 初始化 RandomForestClassifier rf_clf = RandomForestClassifier( n_estimators=100, # 决策树数量 max_depth=None, # 决策树最大深度 (不限制) max_features='sqrt', # 每个节点划分时考虑 sqrt(n_features) 个特征 bootstrap=True, # 启用自助抽样 random_state=42 ) # 训练模型 rf_clf.fit(X_train, y_train) # 预测和评估 (与 Bagging 示例相同) y_pred = rf_clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"RandomForestClassifier Accuracy: {accuracy:.4f}")

回归任务示例 (使用 RandomForestRegressor):

from sklearn.ensemble import RandomForestRegressor # ... (加载 Boston 房价数据集,与 Bagging 示例相同) ... # 初始化 RandomForestRegressor rf_reg = RandomForestRegressor( n_estimators=100, # 决策树数量 max_depth=None, # 决策树最大深度 (不限制) max_features='sqrt', # 每个节点划分时考虑 sqrt(n_features) 个特征 bootstrap=True, # 启用自助抽样 random_state=42 ) # 训练模型 rf_reg.fit(X_train, y_train) # 预测和评估 (与 Bagging 示例相同) y_pred = rf_reg.predict(X_test) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"RandomForestRegressor MSE: {mse:.4f}") print(f"RandomForestRegressor R^2: {r2:.4f}")

参数调优:

  • n_estimators (决策树数量): 与 Bagging 和 Boosting 类似,增加 n_estimators 可以提升性能,但计算成本也会增加。

  • max_depth (决策树最大深度): 控制模型的复杂度。限制 max_depth 可以防止过拟合,但可能降低模型的精度。

  • max_features (最大特征数): 控制特征选择的随机性。较小的 max_features 可以增加模型的随机性和泛化能力,但也可能降低单个决策树的性能。通常 'sqrt' 或 'log2' 是不错的选择。

  • min_samples_splitmin_samples_leaf (节点划分和叶节点样本数): 用于控制决策树的剪枝,防止过拟合。

  • bootstrap (自助抽样): 通常建议启用自助抽样。

优缺点:

  • 优点:

    • 精度高,通常优于单个决策树和 Bagging。

    • 泛化能力强,对过拟合的抵抗能力强。

    • 对高维数据和大数据集表现良好。

    • 可以并行训练,训练效率较高。

    • 可以评估特征的重要性 (feature importance)。

    • 对缺失值和异常值有一定的鲁棒性。

  • 缺点:

    • 模型解释性相对较差,不如单个决策树直观。

    • 对于某些特定类型的数据集 (例如低维数据集),可能不如 Gradient Boosting 等算法表现好。

4.2.4 Voting and Stacking (投票和堆叠)

原理详解:

Voting (投票) 和 Stacking (堆叠) 是两种更灵活的集成方法,它们不依赖于特定的基学习器类型,而是通过组合多个不同类型的模型来提高预测性能。

4.2.4.1 Voting (投票)

原理详解:

Voting (投票) 方法是最简单直接的集成方法之一。它将多个不同模型的预测结果进行组合,根据投票规则 (例如多数投票或加权投票) 决定最终的预测结果。

Voting 分为两种类型:

  • Hard Voting (硬投票): 对于分类问题,每个模型预测一个类别标签,最终结果由所有模型预测结果中出现次数最多的类别标签决定 (多数投票)。

  • Soft Voting (软投票): 对于分类问题,每个模型预测一个概率向量 (每个类别的概率),最终结果由所有模型预测概率向量的平均值或加权平均值决定,然后选择概率最高的类别标签。Soft Voting 通常比 Hard Voting 效果更好,因为它考虑了模型预测的置信度信息。

Scikit-learn 实现:

Scikit-learn 提供了 VotingClassifierVotingRegressor 类来实现 Voting 方法。这两个类的主要参数包括:

  • estimators: 一个列表,包含多个模型的名称和模型实例的元组,例如 [('lr', LogisticRegression()), ('rf', RandomForestClassifier()), ('svc', SVC(probability=True))]

  • voting: 投票类型,可选 'hard' (硬投票) 或 'soft' (软投票)。默认为 'hard'。对于 Soft Voting,基学习器需要支持概率预测 (例如 predict_proba 方法)。

  • weights: 每个模型的权重,用于加权投票。默认为 None (等权重)。

代码实践:

分类任务示例 (使用 VotingClassifier):

from sklearn.ensemble import VotingClassifier from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC # ... (加载 Iris 数据集,与 Bagging 示例相同) ... # 初始化多个不同的分类器 clf1 = LogisticRegression(random_state=42) clf2 = DecisionTreeClassifier(random_state=42) clf3 = SVC(probability=True, random_state=42) # SVC 需要 probability=True 才能使用 Soft Voting # 初始化 VotingClassifier voting_clf = VotingClassifier( estimators=[('lr', clf1), ('dt', clf2), ('svc', clf3)], # 模型列表 voting='soft', # 使用 Soft Voting weights=[1, 1, 2] # 模型权重 (SVC 权重更高) ) # 训练模型 voting_clf.fit(X_train, y_train) # 预测和评估 (与 Bagging 示例相同) y_pred = voting_clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print(f"VotingClassifier Accuracy: {accuracy:.4f}")

回归任务示例 (使用 VotingRegressor):


发布者: 作者: 转发
评论区 (0)
U