44·监督学习-分类进阶

AdaBoost 算法

ensembleboosting

第44课:AdaBoost 算法

所属模块: 监督学习 - 分类
难度: 中级
标签: 集成学习, Boosting

学习目标

完成本课后,你将能够:

  1. 理解 AdaBoost 算法的核心思想及其在集成学习中的地位。
  2. 掌握 AdaBoost 通过调整样本权重和弱学习器权重来提升模型性能的机制。
  3. 使用 Python 的 Scikit-learn 库实现 AdaBoost 分类器。
  4. 了解 AdaBoost 的关键超参数及其调优思路。
  5. 将 AdaBoost 应用于实际数据集,并解释其决策过程。

核心概念

上一课我们介绍了集成学习中的两大流派:Bagging 与 Boosting。Bagging(如随机森林)通过并行构建多个独立模型并平均其结果来降低方差。而 Boosting 则采用一种“循序渐进”的策略:串行地训练一系列弱学习器,每一个新的学习器都重点关注上一个学习器犯错误的样本**。AdaBoost (Adaptive Boosting) 是 Boosting 家族中最经典、最具开创性的算法之一。

1. 核心思想:聚焦错误,逐步修正 想象你在教一个学生做数学题。你先给他一套简单的题目(弱学习器),发现他有几道做错了。于是,你标记出这些错题,并给他另一套题,这套题里错题出现的频率更高。通过反复这个过程,学生(模型)就越来越擅长做那些之前容易出错的难题。

2. 三个关键角色:

  • 样本权重: 每个训练样本都有一个权重。开始时,所有样本权重相同。在每一轮迭代中,被前一个弱学习器错误分类的样本,其权重会被增加,从而在下一轮训练中受到更多关注。
  • 弱学习器: 通常是简单的模型,例如决策树桩(Decision Stump,即只有一层分裂的决策树)或小的决策树。AdaBoost 的威力在于,它能将许多比随机猜测略好一点的“弱者”组合成一个强大的“强者”。
  • 弱学习器权重: 每个弱学习器在最终投票中的话语权不同。在训练集上表现越好(加权错误率越低)的弱学习器,其权重(alpha)越大,对最终决策的影响力也越大。

3. 权重更新公式: 这是 AdaBoost 的灵魂。假设我们已经训练好了第 t 个弱学习器 h_t

  • 样本权重更新: 对于被 h_t 正确分类的样本,其新权重 = 旧权重 * exp(-alpha_t)。对于被错误分类的样本,其新权重 = 旧权重 * exp(alpha_t)。然后,对所有样本权重进行归一化,使其总和为1。
  • 弱学习器权重 alpha_t alpha_t = 0.5 * ln((1 - error_t) / error_t),其中 error_th_t当前样本权重下的加权错误率。错误率越低,alpha_t 越大。

经过 T 轮迭代,最终的强分类器是所有弱学习器的加权和:H(x) = sign(sum(alpha_t * h_t(x)))

代码示例

下面是一个使用 Scikit-learn 实现 AdaBoost 进行分类的完整示例。

# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report

# 1. 生成模拟数据(月牙形数据集,非线性可分)
X, y = make_moons(n_samples=1000, noise=0.3, random_state=42)

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

# 3. 构建 AdaBoost 分类器
# 我们以决策树桩(最大深度为1)作为基础的弱学习器
# n_estimators 是弱学习器的数量
ada_clf = AdaBoostClassifier(
    estimator=DecisionTreeClassifier(max_depth=1), # 基础学习器
    n_estimators=50, # 学习器个数
    learning_rate=1.0, # 学习率,对alpha进行缩放
    algorithm='SAMME', # 离散AdaBoost算法
    random_state=42
)

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

# 5. 预测与评估
y_pred = ada_clf.predict(X_test)
print(f"测试集准确率: {accuracy_score(y_test, y_pred):.4f}")
print("\n分类报告:")
print(classification_report(y_test, y_pred))

# 6. 可视化决策边界 (可选)
def plot_decision_boundary(clf, X, y, ax, title):
    # 创建网格点
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
                         np.arange(y_min, y_max, 0.1))
    # 预测
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # 绘制
    ax.contourf(xx, yy, Z, alpha=0.4, cmap='coolwarm')
    ax.scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor='k', cmap='coolwarm')
    ax.set_title(title)

fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 绘制单个决策树桩的边界
stump = DecisionTreeClassifier(max_depth=1).fit(X_train, y_train)
plot_decision_boundary(stump, X_test, y_test, axes[0], '单个决策树桩')
# 绘制AdaBoost集成后的边界
plot_decision_boundary(ada_clf, X_test, y_test, axes[1], 'AdaBoost (50棵树桩)')
plt.tight_layout()
plt.show()

# 7. 查看弱学习器的权重(alpha)
# ada_clf.estimator_weights_ 就是每个弱学习器的权重列表
print(f"\n前5个弱学习器的权重(alpha): {ada_clf.estimator_weights_[:5]}")

实践练习

练习1:基础应用 使用 sklearn.datasets.load_breast_cancer 数据集,构建一个 AdaBoost 分类器(基础学习器为深度为2的决策树,数量为100个)。划分数据集(80%训练,20%测试),打印测试集准确率和分类报告。 预期输出: 准确率应明显高于单个决策树(提示:可对比测试)。

练习2:手动实现权重更新(理解原理) 假设我们有一个极其简单的3个样本数据集,以及一个刚训练好的、错误率 error = 0.3 的弱学习器。

  1. 计算该弱学习器的权重 alpha
  2. 计算被错误分类的那个样本的新权重(假设其旧权重为 w_old = 1/3)。
  3. 思考:经过本轮更新,被错误分类的样本在下一轮训练中会受到更多关注吗?为什么? 预期输出: alpha = 0.4236 w_new = 0.4776 是的,新权重大于旧权重(0.4776 > 0.3333),说明该样本在下一轮会被更关注。

练习3:超参数调优与对比 在练习1的乳腺癌数据集上,尝试调整 n_estimators(如10, 50, 200)和 learning_rate(如0.5, 1.0, 2.0)的组合,观察模型在测试集上的表现变化。哪一个参数组合表现最好?learning_raten_estimators 之间存在怎样的关系? 预期输出: 记录不同组合下的准确率。通常存在一个权衡:learning_rate 较小需要更多的 n_estimators 来达到相似效果。

常见错误

  1. 忽略数据预处理: AdaBoost 对异常值(outliers)和噪声数据比较敏感,因为算法会不断增大错误样本的权重。在应用 AdaBoost 前,应进行适当的数据清洗和标准化。
  2. 弱学习器选择不当: 如果基础学习器太强(如深度很大的决策树),AdaBoost 可能很快过拟合训练数据。通常应从非常简单的模型(如决策树桩)开始。
  3. 过度增加迭代次数: 盲目增大 n_estimators 会增加训练时间,并可能导致过拟合。应配合验证集监控性能,适时停止。
  4. 误解 learning_rate 的作用: learning_rate 缩放了弱学习器的权重 alpha,它需要与 n_estimators 配合调优。较小的学习率通常需要更多的弱学习器来拟合数据。
  5. 用于回归问题时忘记更换算法: AdaBoostRegressor 是用于回归任务的对应类,其内部使用的是不同的损失函数(如线性损失或平方损失),不要误用 AdaBoostClassifier

小结

本课我们深入探讨了 AdaBoost 算法:

  • 核心机制: 通过迭代调整样本权重(关注错误)和计算弱学习器权重(奖励强者),将多个简单的弱学习器组合成一个强大的集成模型。
  • 关键步骤: 初始化权重 -> 训练弱学习器 -> 计算其加权错误率和权重 -> 更新样本权重 -> 重复。
  • 实践应用: 使用 sklearn.ensemble.AdaBoostClassifier 可以轻松实现。基础学习器(estimator)、迭代次数(n_estimators)和学习率(learning_rate)是最重要的调优参数。
  • 优势与特点: 对模型的偏差(Bias)有显著降低,不易过拟合(相对于单个复杂模型),且能提供特征重要性的度量。
  • 后续展望: AdaBoost 的思想是梯度提升(Gradient Boosting)框架的一个特例。下一课我们将学习当前最强大的梯度提升实现之一——XGBoost,它在 AdaBoost 的基础上引入了正则化等更多工程优化。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「XGBoost 原理与实战」 以巩固所学知识。