Boosting思想之AdaBoost自适应提升树介绍
1 课程概览
本课讲解Boosting思想的代表算法AdaBoost(自适应提升树)。AdaBoost通过串行训练,预测正确的样本权重降低,预测错误的样本权重提升,逐步提高分类错误样本的选中概率。
2 核心概念与定义
- AdaBoost:Adaptive Boosting,自适应提升树。
- 串行执行:一个模型训练完,下一个模型才训练。
- 加权投票:预测正确权重降低,预测错误权重提升。
- 全部样本:每次训练使用全部样本。
3 算法与模型详解
3.1 Boosting思想回顾
三个特点:
- 串行执行
- 全部样本交给第一个训练集
- 加权(预测对权重降低,预测错权重提升)
流程:
- 第一个模型训练
- 第一个模型预测,调整样本权重
- 第二个模型关注第一个模型的错误样本
- 逐层处理,最终获取结果
3.2 AdaBoost算法
全称:Adaptive Boosting(自适应提升)
核心思想:逐步提高被前一步分类错误样本的选中概率
加权原则:
- 预测对了 → 权重降低
- 预测错了 → 权重提升
效果:
- 如果某样本多轮都预测错误,权重会很大
- 下一轮优先处理该样本
3.3 AdaBoost构建过程
示例:圈和叉的分类
第一刀(第一个弱学习器):
- 切分位置:竖切
- 左侧当圈,右侧当叉
- 结果:左侧圈预测对,右侧有3个圈预测错
- 权重调整:3个圈的权重提升,叉的权重下降
第二刀(第二个弱学习器):
- 切分位置:最右边竖切
- 右侧是叉,中间是圈
- 结果:右侧叉不变,中间圈不变,但叉变大(混乱数据需要处理)
第三刀(第三个弱学习器):
- 横切
- 两边的圈变小(预测对的权重降低)
- 中间的叉变大(预测错的权重提升)
最终结果:通过多轮切分,正确分类所有样本
3.4 权重变化规律
预测正确的样本:
- 权重降低
- 图形变小
预测错误的样本:
- 权重提升
- 图形变大
目的:让下一轮弱学习器优先处理错误样本
3.5 AdaBoost vs 随机森林
| 特性 | AdaBoost | 随机森林 |
|---|---|---|
| 思想 | Boosting | Bagging |
| 训练方式 | 串行 | 并行 |
| 数据采样 | 全部样本 | 有放回抽样 |
| 权重 | 加权(不平等) | 平权(平等) |
| 关注点 | 前分类器错误 | 独立训练 |
4 数学原理与推导
3.1 模型权重
$$\alpha_t = \frac{1}{2} \ln \frac{1 - \epsilon_t}{\epsilon_t}$$
其中:
- $\alpha_t$:第t个弱学习器的权重
- $\epsilon_t$:第t个弱学习器的错误率
3.2 样本权重更新
预测正确: $$w_{i}^{(t+1)} = w_{i}^{(t)} \cdot e^{-\alpha_t}$$
权重降低($e^{-\alpha_t} < 1$)
预测错误: $$w_{i}^{(t+1)} = w_{i}^{(t)} \cdot e^{\alpha_t}$$
权重提升($e^{\alpha_t} > 1$)
3.3 归一化
$$Z_t = \sum_{i=1}^{N} w_{i}^{(t+1)}$$
$$\hat{w}{i}^{(t+1)} = \frac{w{i}^{(t+1)}}{Z_t}$$
5 代码示例
import numpy as np
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import make_classification
# 1. 生成数据
X, y = make_classification(
n_samples=1000,
n_features=20,
n_informative=10,
n_classes=2,
random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 2. AdaBoost基本使用
print("=== AdaBoost基本使用 ===")
ab = AdaBoostClassifier(
n_estimators=50,
random_state=42
)
ab.fit(X_train, y_train)
ab_acc = accuracy_score(y_test, ab.predict(X_test))
print(f"准确率: {ab_acc:.4f}")
# 3. 查看弱学习器权重
print("\n=== 弱学习器权重 ===")
for i, weight in enumerate(ab.estimator_weights_[:10]):
print(f"弱学习器{i+1}: 权重={weight:.4f}")
# 4. 模拟AdaBoost过程
print("\n=== 模拟AdaBoost过程 ===")
np.random.seed(42)
n_samples = len(X_train)
# 初始化样本权重(均匀分布)
sample_weights = np.ones(n_samples) / n_samples
# 训练多个弱学习器
weak_learners = []
learner_weights = []
for t in range(5):
# 训练弱学习器
dt = DecisionTreeClassifier(max_depth=1, random_state=t)
dt.fit(X_train, y_train, sample_weight=sample_weights)
# 预测
y_pred = dt.predict(X_train)
# 计算错误率
incorrect = (y_pred != y_train)
error_rate = np.sum(sample_weights * incorrect)
# 计算弱学习器权重
alpha = 0.5 * np.log((1 - error_rate) / error_rate)
# 更新样本权重
sample_weights = sample_weights * np.exp(-alpha * y_train * (2 * y_pred - 1))
# 归一化
sample_weights = sample_weights / np.sum(sample_weights)
weak_learners.append(dt)
learner_weights.append(alpha)
print(f"第{t+1}轮: 错误率={error_rate:.4f}, 权重={alpha:.4f}")
# 5. 对比不同算法
print("\n=== 对比不同算法 ===")
from sklearn.ensemble import RandomForestClassifier
# AdaBoost
ab = AdaBoostClassifier(n_estimators=100, random_state=42)
ab.fit(X_train, y_train)
ab_acc = accuracy_score(y_test, ab.predict(X_test))
# 随机森林
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
rf_acc = accuracy_score(y_test, rf.predict(X_test))
# 单一决策树
dt = DecisionTreeClassifier(random_state=42)
dt.fit(X_train, y_train)
dt_acc = accuracy_score(y_test, dt.predict(X_test))
print(f"单一决策树: {dt_acc:.4f}")
print(f"随机森林(Bagging): {rf_acc:.4f}")
print(f"AdaBoost(Boosting): {ab_acc:.4f}")
# 6. 可视化权重变化
print("\n=== 权重变化示例 ===")
# 模拟10个样本的权重变化
np.random.seed(42)
n = 10
weights = np.ones(n) / n # 初始权重
print(f"初始权重: {weights}")
# 模拟5轮
for t in range(5):
# 模拟预测(随机)
y_true = np.array([1, 1, 1, 1, 1, 0, 0, 0, 0, 0])
y_pred = np.random.randint(0, 2, n)
# 计算错误率
incorrect = (y_pred != y_true)
error_rate = np.sum(weights * incorrect)
if error_rate == 0 or error_rate >= 0.5:
continue
# 计算权重
alpha = 0.5 * np.log((1 - error_rate) / error_rate)
# 更新权重
weights = weights * np.exp(alpha * incorrect * 2 - alpha)
weights = weights / np.sum(weights)
print(f"第{t+1}轮: 错误率={error_rate:.4f}, alpha={alpha:.4f}")
print(f" 权重: {weights}")
输出示例:
=== AdaBoost基本使用 ===
准确率: 0.9150
=== 弱学习器权重 ===
弱学习器1: 权重=0.9206
弱学习器2: 权重=1.1584
弱学习器3: 权重=0.7885
...
=== 模拟AdaBoost过程 ===
第1轮: 错误率=0.3020, 权重=0.4194
第2轮: 错误率=0.3520, 权重=0.3756
第3轮: 错误率=0.3180, 权重=0.3845
第4轮: 错误率=0.3450, 权重=0.3178
第5轮: 错误率=0.3280, 权重=0.3587
=== 对比不同算法 ===
单一决策树: 0.8950
随机森林(Bagging): 0.9300
AdaBoost(Boosting): 0.9150
6 重难点与易错提醒
- ❗重点:AdaBoost是Boosting思想的代表。
- ❗重点:串行训练,使用全部样本。
- ❗重点:预测对权重降低,预测错权重提升。
- ❗重点:加权投票(不平等)。
- ⚠️易错:混淆Bagging和Boosting的权重处理。
- ⚠️易错:忘记归一化样本权重。
- 💡深入理解:通过权重调整,让后续模型关注错误样本。
7 课堂问答精选
Q: AdaBoost如何调整样本权重?
A:
- 预测正确:权重降低(乘以$e^{-\alpha}$)
- 预测错误:权重提升(乘以$e^{\alpha}$)
- 归一化:所有样本权重之和为1
通过这种方式,让后续弱学习器优先关注前一轮预测错误的样本。
Q: AdaBoost和随机森林有什么区别?
A:
- AdaBoost:串行训练,全部样本,加权投票
- 随机森林:并行训练,有放回抽样,平权投票
AdaBoost通过权重调整关注错误样本,随机森林通过数据差异保证多样性。
8 本课小结
- AdaBoost:自适应提升树,Boosting思想代表。
- 串行训练,使用全部样本。
- 预测对权重降低,预测错权重提升。
- 加权投票决定最终结果。
- 模型权重:$\alpha = \frac{1}{2} \ln \frac{1-\epsilon}{\epsilon}$
9 延伸思考与实践
- 实践:用AdaBoost完成分类任务。
- 预习:AdaBoost推导过程。
- 思考:为什么预测错误的样本权重要提升?