集成学习:从 Bagging 到 XGBoost

摘要 :前面学的每个算法都有各自的优缺点------线性回归简单但只能拟合线性关系,决策树可解释但容易过拟合,SVM 效果好但调参复杂。集成学习的思路是:不纠结于找"最好的单一算法",而是把多个"弱"模型组合起来,得到一个"强"模型。这就是"三个臭皮匠,顶个诸葛亮"的机器学习版本。这篇文章系统介绍三种集成策略:Bagging(并行)、Boosting(串行)、Stacking(混合),以及它们的代表算法。


一、为什么要集成?

"三个臭皮匠"的数学依据

假设有 5 个独立的分类器,每个的准确率都是 60%。如果让它们投票:

复制代码
投票决定:至少 3 个分类器说"是"才算"是"

每个分类器正确的概率:p = 0.6
至少 3 个正确的概率:P(≥3) = 0.683

5 个 60% 的分类器投票 → 68.3% 的准确率!比单个高了 8 个百分点。

如果增加到 101 个 60% 的分类器:
  P(≥51) ≈ 0.972 → 97.2% 的准确率!

这就是集成学习的数学基础------当个体独立且优于随机时,组合能大幅提升性能。

偏差-方差分解

理解集成学习需要先理解模型误差的两个来源:

误差来源 含义 类比
偏差(Bias) 模型的系统性偏离------预测值的中心是否在真实值附近 射箭时,箭都偏离靶心同一个方向
方差(Variance) 模型的波动程度------换不同数据训练,结果变化大不大 射箭时,箭散落分布在一大片区域
复制代码
低偏差 + 低方差 = 理想(准确且稳定)    ⭐
低偏差 + 高方差 = 过拟合(准但波动大)   → Bagging 解决
高偏差 + 低方差 = 欠拟合(稳定但不准)   → Boosting 解决
高偏差 + 高方差 = 最差(又不准又不稳)   ❌

两种集成策略

复制代码
集成学习的两个基本策略:

Bagging(并行):
  训练多个独立模型 → 平均它们的预测
  → 降低方差(保持偏差不变)
  → 适合容易过拟合的模型(如决策树)

Boosting(串行):
  逐个训练模型,每个模型修正前一个的错误
  → 降低偏差(同时控制方差)
  → 适合容易欠拟合的模型(如浅层决策树)

二、Bagging:并行集成

Bootstrap Aggregating

Bagging = Bootstrap + Aggregating(自助采样 + 聚合)。

Bootstrap 采样 :从原始数据集中有放回地抽取 N 个样本,得到一个新的训练集。这样重复 M 次,得到 M 个不同的训练集。

复制代码
原始数据集 [1, 2, 3, 4, 5]

Bootstrap 采样 1: [1, 2, 2, 3, 5]  ← 有重复
Bootstrap 采样 2: [1, 3, 4, 4, 5]
Bootstrap 采样 3: [2, 2, 3, 4, 5]
...共 M 次

聚合(Aggregating):

  • 分类:M 个模型投票(少数服从多数)

  • 回归:M 个模型的平均值

    from sklearn.ensemble import BaggingClassifier
    from sklearn.tree import DecisionTreeClassifier

    Bagging + 决策树 = 随机森林的雏形

    bagging = BaggingClassifier(
    estimator=DecisionTreeClassifier(), # 基学习器
    n_estimators=100, # 训练 100 棵树
    max_samples=1.0, # 每棵树使用 100% 的样本(有放回)
    bootstrap=True, # 有放回采样
    n_jobs=-1 # 并行训练
    )
    bagging.fit(X_train, y_train)

随机森林(Random Forest)

随机森林 = Bagging + 决策树 + 特征随机性。

Bagging 只在样本上做随机采样,随机森林增加了一个关键步骤:在每个分裂点,只考虑随机选取的一部分特征。

复制代码
传统 Bagging 决策树:
  每个分裂点从所有特征中选择最佳分裂特征
  → 树的多样性有限(强特征总被选在最前面)

随机森林:
  每个分裂点只考虑随机选取的 √n 或 n/3 个特征
  → 树的多样性更大
  → 集成效果更强

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(
    n_estimators=100,           # 树的数量
    max_depth=10,               # 每棵树的最大深度
    min_samples_leaf=2,         # 叶子最小样本数
    max_features='sqrt',        # 每棵树考虑的特征数:√n
    random_state=42,
    n_jobs=-1
)
rf.fit(X_train, y_train)

为什么特征随机性有效?

复制代码
如果不加特征随机性:
  所有树的根节点几乎都是同一个最强特征
  → 所有树高度相似 → 平均后提升有限

加了特征随机性:
  每棵树从不同的角度"看"数据
  → 树的多样性大 → 不同树犯错方向不同 → 投票抵消错误

OOB 评估:不需要单独的验证集

Bootstrap 采样中,每个样本大约有 37% 的概率不被抽到 (当 N 很大时)。这些没被抽到的样本叫做 OOB(Out-Of-Bag)样本。

复制代码
# 随机森林自动计算 OOB 分数
rf = RandomForestClassifier(
    n_estimators=100,
    oob_score=True,              # 使用 OOB 评估
    random_state=42
)
rf.fit(X_train, y_train)
print(f"OOB 准确率: {rf.oob_score_:.3f}") 
print(f"测试集准确率: {rf.score(X_test, y_test):.3f}")
# OOB 分数 ≈ 测试准确率,不需要额外的验证集!

三、Boosting:串行集成

与 Bagging 的并行不同,Boosting 是串行 的------每一棵新树都在纠正前一棵树的错误。

3.1 AdaBoost(Adaptive Boosting)

1995 年提出的第一个实用 Boosting 算法,核心思想:增加错误分类样本的权重。

复制代码
第一步:用等权重训练第一棵弱分类器
第二步:找出被分错的样本,提高它们的权重
第三步:用更新权重后的数据训练第二棵分类器
第四步:重复,直到达到指定数量的分类器

最终:所有分类器加权投票(准确率高的分类器权重大)

from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier

ada = AdaBoostClassifier(
    estimator=DecisionTreeClassifier(max_depth=1),  # "树桩"------只有一层的决策树
    n_estimators=200,
    learning_rate=1.0,
    random_state=42
)
ada.fit(X_train, y_train)

3.2 梯度提升(Gradient Boosting)

梯度提升是 AdaBoost 的泛化和改进。核心思想:每一棵新树拟合的是前面所有树的"残差"。

复制代码
梯度提升的直观理解:

第 1 棵树:拟合原始目标 y
  → 预测值 ŷ₁,残差 r₁ = y - ŷ₁
  
第 2 棵树:拟合残差 r₁
  → 预测值 ŷ₂,残差 r₂ = r₁ - ŷ₂
  
第 3 棵树:拟合残差 r₂
  ...

最终预测:ŷ = ŷ₁ + ŷ₂ + ŷ₃ + ... + ŷₘ

每一棵树都在"补窟窿"------弥补之前所有树的不足。

from sklearn.ensemble import GradientBoostingClassifier

gb = GradientBoostingClassifier(
    n_estimators=100,
    max_depth=3,              # 每棵树较浅(一般 3-5)
    learning_rate=0.1,        # 学习率(每棵树的贡献)
    subsample=0.8,            # 每棵树只用 80% 的样本
    random_state=42
)
gb.fit(X_train, y_train)

学习率(learning_rate)的作用:

复制代码
学习率控制每棵树的"贡献大小":

learning_rate=1.0(没有收缩):
  每棵树全力拟合残差 → 容易过拟合

learning_rate=0.1(收缩):
  每棵树只贡献一小部分 → 需要更多树,但泛化更好

一般策略:learning_rate 小(0.01~0.1)+ n_estimators 大(200~2000)

3.3 XGBoost:梯度提升的工程化巅峰

XGBoost(eXtreme Gradient Boosting)是梯度提升的工程优化版本,2014 年由陈天奇提出。它在几个关键点上做了改进:

改进 效果
二阶导数近似 比一阶梯度的收敛更快、更精确
内置正则化 在损失函数中加入树的复杂度惩罚
列采样 借鉴随机森林的特征随机性
并行化 在特征维度上并行(虽然树是串行的)
稀疏感知 自动处理缺失值
缓存优化 高效的缓存访问模式
复制代码
import xgboost as xgb

# XGBoost 分类器
xgb_model = xgb.XGBClassifier(
    n_estimators=200,
    max_depth=5,
    learning_rate=0.1,
    subsample=0.8,
    colsample_bytree=0.8,     # 每棵树使用的特征比例
    reg_alpha=0.1,            # L1 正则化
    reg_lambda=1.0,           # L2 正则化
    random_state=42,
    n_jobs=-1
)
xgb_model.fit(X_train, y_train)

# 特征重要性
importance = xgb_model.feature_importances_

# XGBoost 的特征重要性有三种计算方式:
# 'weight': 特征被用来分裂的次数
# 'gain':   特征带来的平均信息增益
# 'cover':  特征覆盖的样本数
xgb.plot_importance(xgb_model, importance_type='gain')

XGBoost vs 普通梯度提升:

复制代码
普通梯度提升:    每棵树用所有特征 → 容易过拟合
XGBoost:         列采样 + 正则化 → 泛化更强

普通梯度提升:    一阶导数近似 → 收敛较慢
XGBoost:         二阶导数近似 → 收敛更快、更准

普通梯度提升:    无法并行 → 训练慢
XGBoost:         特征并行 + 缓存优化 → 训练快 10 倍

3.4 LightGBM 与 CatBoost

算法 年份 核心创新 优势场景
XGBoost 2014 二阶导数 + 正则化 + 并行 结构化数据的通用王者
LightGBM 2017 基于直方图的决策树算法 + GOSS 海量数据、高维特征
CatBoost 2017 有序提升 + 自动处理类别特征 含大量类别特征的数据
复制代码
import lightgbm as lgb
# LightGBM 在数据量大时比 XGBoost 快几倍
lgb_model = lgb.LGBMClassifier(
    n_estimators=200,
    max_depth=5,
    learning_rate=0.1,
    num_leaves=31,            # LightGBM 特有的参数
    subsample=0.8,
    colsample_bytree=0.8,
    random_state=42
)

四、Bagging vs Boosting 对比

对比维度 Bagging / 随机森林 Boosting / XGBoost
训练方式 并行(同时训练) 串行(逐个训练)
主要目标 降低方差(防止过拟合) 降低偏差(提升准确性)
基学习器 强学习器(可不剪枝) 弱学习器(浅树)
对噪声敏感度 不敏感(平均抵消噪声) 敏感(会拟合噪声)
训练速度 快(可并行) 慢(必须串行)
代表性算法 随机森林 XGBoost / LightGBM
调参难度 低(2-3 个关键参数) 高(更多参数需配合)

选型指南

复制代码
数据量大且有噪声 → 随机森林(鲁棒、并行、不易过拟合)
追求极致准确率 → XGBoost / LightGBM(串行修正,更强)
数据含大量类别特征 → CatBoost(原生支持)
需要快速原型 → 随机森林(默认参数表现就不错)

五、Stacking:混合集成

Stacking 不是用同一种模型做集成,而是混合不同类型的模型。

复制代码
第一层(基学习器):
  模型 1(逻辑回归) → 输出概率 P₁
  模型 2(SVM)      → 输出概率 P₂
  模型 3(随机森林)  → 输出概率 P₃
  模型 4(XGBoost)  → 输出概率 P₄

第二层(元学习器):
  输入 [P₁, P₂, P₃, P₄] → 逻辑回归 → 最终预测

from sklearn.ensemble import StackingClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
import xgboost as xgb

stacking = StackingClassifier(
    estimators=[
        ('lr', LogisticRegression(max_iter=1000)),
        ('svm', SVC(kernel='rbf', probability=True)),
        ('rf', RandomForestClassifier(n_estimators=100)),
        ('xgb', xgb.XGBClassifier(n_estimators=100)),
    ],
    final_estimator=LogisticRegression(),  # 元学习器
    cv=5,                                    # 交叉验证防止过拟合
    stack_method='predict_proba'             # 使用概率作为元特征
)

stacking.fit(X_train, y_train)
print(f"Stacking 准确率: {stacking.score(X_test, y_test):.3f}")
# Stacking 通常比单个模型高 1-3%,但计算成本也高几倍

六、完整实战:多种集成方法对比

复制代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.ensemble import (RandomForestClassifier, 
                              GradientBoostingClassifier,
                              AdaBoostClassifier,
                              StackingClassifier)
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
import xgboost as xgb
import time

# ===== 1. 生成数据 =====
X, y = make_classification(
    n_samples=2000, n_features=20, n_informative=15,
    n_redundant=3, random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# ===== 2. 定义模型 =====
models = {
    '单棵决策树': DecisionTreeClassifier(max_depth=5, random_state=42),
    '随机森林': RandomForestClassifier(n_estimators=200, max_depth=10, random_state=42, n_jobs=-1),
    'AdaBoost': AdaBoostClassifier(n_estimators=200, random_state=42),
    '梯度提升': GradientBoostingClassifier(n_estimators=200, max_depth=3, learning_rate=0.1, random_state=42),
    'XGBoost': xgb.XGBClassifier(n_estimators=200, max_depth=3, learning_rate=0.1, random_state=42, n_jobs=-1),
    'Stacking': StackingClassifier(
        estimators=[
            ('rf', RandomForestClassifier(n_estimators=100, random_state=42)),
            ('xgb', xgb.XGBClassifier(n_estimators=100, random_state=42)),
            ('svm', SVC(kernel='rbf', probability=True, random_state=42)),
        ],
        final_estimator=LogisticRegression(),
        cv=3
    ),
}

# ===== 3. 训练与评估 =====
results = []
for name, model in models.items():
    start = time.time()
    model.fit(X_train, y_train)
    train_time = time.time() - start
    
    train_acc = accuracy_score(y_train, model.predict(X_train))
    test_acc = accuracy_score(y_test, model.predict(X_test))
    
    # 交叉验证(XGBoost 和 Stacking 较慢,跳过 cv)
    if 'Stacking' not in name and 'XGBoost' not in name:
        cv_scores = cross_val_score(model, X_train, y_train, cv=3)
        cv_mean = cv_scores.mean()
    else:
        cv_mean = test_acc  # 近似值
    
    results.append({
        '模型': name,
        '训练准确率': f"{train_acc:.3f}",
        '测试准确率': f"{test_acc:.3f}",
        '训练时间(秒)': f"{train_time:.2f}"
    })

results_df = pd.DataFrame(results)
print(results_df.to_string(index=False))

输出示例:

复制代码
        模型    训练准确率   测试准确率   训练时间(秒)
   单棵决策树      0.942      0.888        0.02
     随机森林      1.000      0.938        1.85
     AdaBoost      0.956      0.915        0.45
     梯度提升      0.982      0.930        2.10
      XGBoost      0.988      0.938        0.55
     Stacking      0.976      0.945        4.80

结果解读:

复制代码
单棵决策树(88.8%):最差,但速度快、可解释
随机森林(93.8%):决策树的显著提升 ✅
AdaBoost(91.5%):比单棵树好,但不如 RF 和 Boosting
梯度提升(93.0%):和 RF 接近
XGBoost(93.8%):与 RF 持平,训练更快 ✅
Stacking(94.5%):通常最优,但最慢

数据量对集成方法的影响

复制代码
小数据(<1000):随机森林 > XGBoost(RF 在小数据上更稳定)
中数据(1000-1万):XGBoost > 随机森林(GB 的串行修正优势体现)
大数据(>1万):LightGBM > XGBoost > 随机森林(速度差异明显)
超大数据(>10万):LightGBM 或神经网络(XGBoost 也变慢了)

七、集成学习的调参指南

随机森林

复制代码
# 优先调这三个参数
rf = RandomForestClassifier(
    n_estimators=500,          # 越多越好,但边际递减(先固定 100-500)
    max_depth=None,            # 不限制深度(靠随机性防止过拟合)
    min_samples_leaf=1,        # 保持较小(默认为 1)
    max_features='sqrt',       # 关键参数:sqrt(n) 或 log2(n)
)
# 随机森林默认参数通常表现就不错

XGBoost

复制代码
xgb_model = xgb.XGBClassifier(
    # 核心参数
    n_estimators=500,          # 树的数量(与 learning_rate 配合)
    learning_rate=0.05,        # 学习率(越小需要越多树)
    max_depth=5,               # 树的深度(通常 3-8)
    
    # 正则化
    reg_alpha=0.1,             # L1 正则化
    reg_lambda=1.0,            # L2 正则化
    
    # 采样
    subsample=0.8,             # 行采样(每棵树用 80% 样本)
    colsample_bytree=0.8,      # 列采样(每棵树用 80% 特征)
    
    # 停止条件
    early_stopping_rounds=20,  # 验证集 20 轮不提升就停止
)

XGBoost 调参顺序:

复制代码
第一步:固定 learning_rate=0.1,调 max_depth 和 min_child_weight
第二步:调 subsample 和 colsample_bytree(防过拟合)
第三步:调 reg_alpha 和 reg_lambda(正则化)
第四步:降低 learning_rate(0.01~0.05),增加 n_estimators

八、集成学习在 2026 年的地位

任务类型 2026 年推荐方案
结构化数据分类/回归 ✅ XGBoost / LightGBM------仍然是最强选择
中小规模数据 ✅ 随机森林------稳健、不易过拟合
包含大量类别特征 ✅ CatBoost------原生支持类别特征
图像/音频/文本 ❌ 已被深度学习取代
超高精度需求(比赛) ✅ Stacking------多个模型融合
可解释性要求高 ⚠️ 随机森林(特征重要性)或单棵决策树

一个事实:在 Kaggle 竞赛中,XGBoost / LightGBM 是结构化数据任务上使用最频繁、表现最稳定的算法之一。即使到了 2026 年,深度学习在结构化数据上仍然没有全面超越梯度提升树。


九、总结

概念 一句话理解
Bagging 并行训练多个模型,平均它们的预测------降低方差
随机森林 Bagging + 决策树 + 特征随机性------简单、稳定、强大
Boosting 串行训练,每棵树修正前一个的错误------降低偏差
XGBoost Boosting 的工程化巅峰------二阶导数 + 正则化 + 并行
Stacking 混合不同类型模型------集成的集成
三大参数 n_estimators(多少个)、learning_rate(每步多大)、max_depth(多深)

集成学习的核心思想链条:

复制代码
单棵决策树(不稳定、易过拟合)
    ↓ Bagging(并行平均)
随机森林(稳定、泛化好)
    ↓ Boosting(串行修正)
XGBoost / LightGBM(精准、高效)
    ↓ Stacking(混合)
多个模型的融合(集成的极限)

下一篇文章:无监督学习------当数据没有标签时,如何发现隐藏的结构?

相关推荐
宸津-代码粉碎机4 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
做萤石二次开发的哈哈5 小时前
视频解码器怎么对接?解码上墙、电视墙开窗与场景切换的ISAPI接入实战
人工智能·物联网·监控·视频编解码·大屏端·萤石开放平台·蓝海aiot一站式工作台
Leo.yuan5 小时前
2026年本地化Data Agent优质厂商盘点:哪些产品更适合企业生产环境
大数据·数据库·人工智能
长谷深风1116 小时前
Tool与Skill:AI能力设计的分水岭
java·人工智能·ai·大模型·aiagent
科技观察哨6 小时前
六足平台选型与纳米定位系统集成:HEB-640六自由度位移台在半导体光刻对准中的参数边界与国产替代评估
前端·人工智能
云上先途6 小时前
任务智能体可以自动完成哪些类型工作,是不是只能做简单重复操作?
大数据·人工智能
明志数科6 小时前
具身智能数据供给的分层:分布式采集与入厂采集的工程边界分析
人工智能·机器学习·机器人
像风一样自由20206 小时前
41.用FastAPI搭建一个RAG后端需要哪些接口
人工智能·大模型·fastapi·rag·智能体
小蒋观天下6 小时前
两轮车检测AI摄像头——2026行业竞争格局、商业模式与核心痛点
大数据·人工智能·安全·计算机视觉·ai大模型
RisunJan6 小时前
【这就是AI】AI每日资讯简报 - 2026-09-28(周一)
大数据·人工智能