集成学习之Bagging和Boosting思想介绍
1 课程概览
本课详细讲解集成学习的两种核心思想:Bagging(自助法,并行训练,投票决策)和Boosting(串行训练,针对短板加强,加权投票)。对比两者的数据采样、训练方式和决策机制。
2 核心概念与定义
- Bagging:自助法,有放回抽样,并行训练,投票评选。
- Boosting:串行训练,关注前分类器不足,加权投票。
- 有放回抽样:抽取后放回,多个弱学习器数据既有交集又有差异。
- 投票评选:多个弱学习器每人一票,多数表决。
3 算法与模型详解
3.1 Bagging思想
核心:自助法(Bootstrap)
流程:
- 从1000条数据中有放回抽取700条
- 抽完放回,供下一个弱学习器抽取
- 多个弱学习器数据既有交集又有差异
- 并行训练
- 多数表决作为最终预测结果
三个关键点:
- 有放回的抽样:抽完放回,保证交集和差异
- 投票评选:多个弱学习器每人一票,多数表决
- 并行训练:多个弱学习器同时训练
为什么要有放回:
- 无放回:抽500条后没数据了
- 有放回:保证多个弱学习器数据既有交集又有差异
3.2 Bagging示例
分类任务:
- 3个弱学习器分别画分界线
- 模型1:左圈右方
- 模型2:左圈右方
- 模型3:上圈下方
- 投票结果:模型1和模型2相同,投票决定最终结果
投票决策:
- 2个模型投A方向,1个模型投B方向
- 最终结果:A方向(多数)
3.3 Boosting思想
核心:关注前分类器的不足
流程:
- 训练集给到第一个弱学习器
- 第一个弱学习器训练,存在不足
- 第二个弱学习器重点关注前一个的不足
- 第三个弱学习器继续针对不足训练
- 最终由最后一个弱学习器输出结果
- 加权投票
特点:
- 串行训练(一个接一个)
- 全量数据(不是有放回抽样)
- 关注前分类器不足
- 加权投票
3.4 Bagging vs Boosting
| 特性 | Bagging | Boosting |
|---|---|---|
| 数据采样 | 有放回抽样 | 全量数据 |
| 训练方式 | 并行 | 串行 |
| 关注点 | 独立训练 | 前分类器不足 |
| 决策方式 | 投票评选 | 加权投票 |
| 权重 | 平等 | 不平等 |
3.5 Boosting的加权投票
与Bagging投票的区别:
- Bagging:每人一票(平等)
- Boosting:权重不同(如长老1票,宗主2票)
示例:
- 弱学习器1:权重0.3
- 弱学习器2:权重0.5
- 弱学习器3:权重0.2
- 加权求和决定最终结果
3.6 两种思想的代表算法
Bagging:
- 随机森林(Random Forest)
Boosting:
- AdaBoost
- GBDT
- XGBoost
- LightGBM
4 代码示例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
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. Bagging思想 - 随机森林
print("=== Bagging - 随机森林 ===")
rf = RandomForestClassifier(
n_estimators=100, # 100个弱学习器
random_state=42
)
rf.fit(X_train, y_train)
rf_acc = accuracy_score(y_test, rf.predict(X_test))
print(f"准确率: {rf_acc:.4f}")
# 3. Boosting思想 - AdaBoost
print("\n=== Boosting - 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))
print(f"准确率: {ab_acc:.4f}")
# 4. 模拟Bagging有放回抽样
print("\n=== 模拟Bagging有放回抽样 ===")
np.random.seed(42)
data_size = 1000
sample_size = 700
# 3个弱学习器各自抽样
samples = []
for i in range(3):
sample = np.random.choice(data_size, sample_size, replace=True)
samples.append(sample)
print(f"弱学习器{i+1}: 抽取{sample_size}条,唯一值{len(set(sample))}个")
# 计算交集和差异
intersection_12 = len(set(samples[0]) & set(samples[1]))
intersection_13 = len(set(samples[0]) & set(samples[2]))
intersection_23 = len(set(samples[1]) & set(samples[2]))
print(f"\n弱学习器1和2的交集: {intersection_12}")
print(f"弱学习器1和3的交集: {intersection_13}")
print(f"弱学习器2和3的交集: {intersection_23}")
print("既有交集又有差异,投票才有意义")
# 5. 模拟Bagging投票决策
print("\n=== 模拟Bagging投票决策 ===")
# 训练3个弱学习器
weak_learners = []
for i in range(3):
dt = DecisionTreeClassifier(max_depth=3, random_state=i)
# 有放回抽样
sample_idx = np.random.choice(len(X_train), len(X_train), replace=True)
dt.fit(X_train[sample_idx], y_train[sample_idx])
weak_learners.append(dt)
# 各弱学习器预测
predictions = np.array([learner.predict(X_test) for learner in weak_learners])
print(f"3个弱学习器的预测形状: {predictions.shape}")
# 投票(多数表决)
from scipy.stats import mode
final_pred = mode(predictions, axis=0)[0].ravel()
vote_acc = accuracy_score(y_test, final_pred)
print(f"投票决策准确率: {vote_acc:.4f}")
# 6. 模拟Boosting串行训练
print("\n=== 模拟Boosting串行训练 ===")
# AdaBoost的串行过程
ab = AdaBoostClassifier(n_estimators=5, random_state=42)
ab.fit(X_train, y_train)
# 查看各弱学习器的权重
print("各弱学习器权重:")
for i, weight in enumerate(ab.estimator_weights_):
print(f" 弱学习器{i+1}: 权重={weight:.4f}")
# 7. 可视化Bagging vs Boosting
fig, axes = plt.subplots(1, 2, figsize=(15, 6))
# Bagging流程图
axes[0].set_title('Bagging思想(并行)', fontsize=14)
axes[0].axis('off')
bagging_text = """
数据集(1000条)
↓ 有放回抽样
┌───┬───┬───┐
↓ ↓ ↓
弱学习器1 弱学习器2 弱学习器3
(并行训练)
↓ ↓ ↓
预测1 预测2 预测3
↓ ↓ ↓
投票评选
↓
最终结果
"""
axes[0].text(0.1, 0.5, bagging_text, fontsize=12, verticalalignment='center')
# Boosting流程图
axes[1].set_title('Boosting思想(串行)', fontsize=14)
axes[1].axis('off')
boosting_text = """
数据集(全量)
↓
弱学习器1 → 不足
↓
弱学习器2(针对不足)
↓ 不足
弱学习器3(针对不足)
↓
加权投票
↓
最终结果
"""
axes[1].text(0.1, 0.5, boosting_text, fontsize=12, verticalalignment='center')
plt.tight_layout()
plt.show()
# 8. 对比总结
print("\n=== 对比总结 ===")
print(f"Bagging(随机森林): {rf_acc:.4f}")
print(f"Boosting(AdaBoost): {ab_acc:.4f}")
print("\nBagging: 有放回抽样,并行训练,投票评选")
print("Boosting: 全量数据,串行训练,加权投票")
输出示例:
=== Bagging - 随机森林 ===
准确率: 0.9300
=== Boosting - AdaBoost ===
准确率: 0.9150
=== 模拟Bagging有放回抽样 ===
弱学习器1: 抽取700条,唯一值512个
弱学习器2: 抽取700条,唯一值511个
弱学习器3: 抽取700条,唯一值513个
弱学习器1和2的交集: 385
弱学习器1和3的交集: 387
弱学习器2和3的交集: 386
既有交集又有差异,投票才有意义
=== 模拟Bagging投票决策 ===
3个弱学习器的预测形状: (3, 200)
投票决策准确率: 0.8900
=== 模拟Boosting串行训练 ===
各弱学习器权重:
弱学习器1: 权重=0.9206
弱学习器2: 权重=1.1584
弱学习器3: 权重=0.7885
弱学习器4: 权重=1.1584
弱学习器5: 权重=0.9206
=== 对比总结 ===
Bagging(随机森林): 0.9300
Boosting(AdaBoost): 0.9150
Bagging: 有放回抽样,并行训练,投票评选
Boosting: 全量数据,串行训练,加权投票
5 重难点与易错提醒
- ❗重点:Bagging有放回抽样,Boosting全量数据。
- ❗重点:Bagging并行,Boosting串行。
- ❗重点:Bagging投票评选(平等),Boosting加权投票(不平等)。
- ❗重点:Bagging关注独立训练,Boosting关注前分类器不足。
- ⚠️易错:混淆有放回和无放回抽样。
- ⚠️易错:混淆投票评选和加权投票。
- 💡深入理解:Bagging通过数据差异保证多样性,Boosting通过针对不足提升精度。
6 课堂问答精选
Q: Bagging和Boosting有什么区别?
A:
- Bagging:有放回抽样,并行训练,投票评选(每人一票)
- Boosting:全量数据,串行训练,加权投票(权重不同)
Bagging通过数据差异保证多样性,Boosting通过针对前分类器不足提升精度。
Q: 为什么Bagging要有放回抽样?
A: 有放回抽样保证多个弱学习器的数据既有交集又有差异。如果无放回,抽500条后没数据了,或者各弱学习器数据完全不同,没有意义。有放回抽样让各弱学习器训练结果不同,投票才有意义。
7 本课小结
- Bagging:有放回抽样,并行训练,投票评选。
- Boosting:全量数据,串行训练,加权投票。
- Bagging代表:随机森林。
- Boosting代表:AdaBoost、GBDT、XGBoost。
8 延伸思考与实践
- 实践:对比Bagging和Boosting的效果。
- 预习:随机森林算法介绍。
- 思考:为什么Boosting要针对前分类器的不足?