集成学习入门:以随机森林为例解析Bagging与随机特征选择如何降低过拟合

1次阅读
没有评论

共计 2505 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

背景痛点:为什么我们需要集成学习?

在机器学习实践中,我们常常遇到一个棘手的问题——过拟合。简单来说,过拟合就像是一个死记硬背的学生,把训练数据中的每一个细节都记住了,包括噪声和异常值,导致在新数据上表现很差。传统的决策树算法特别容易陷入这个问题,因为它们会不断分裂节点,直到完美拟合训练数据。

  • 决策树的局限性
  • 对训练数据中的微小变化非常敏感
  • 容易捕捉到数据中的噪声而非真实模式
  • 通常具有高方差(即在不同的训练集上会产生很大差异)

集成学习:集体智慧的力量

集成学习通过组合多个模型来提高整体性能。主要有两种策略:

  1. Bagging(自助聚合):并行训练多个模型,然后投票或平均它们的预测
  2. Boosting:顺序训练模型,每个新模型都试图修正前一个模型的错误

随机森林采用了 bagging 策略,相比 boosting 方法(如 AdaBoost、XGBoost)有这些优势:

  • 更不容易过拟合
  • 对超参数选择不太敏感
  • 训练可以并行化,效率更高

随机森林的核心原理

Bagging 如何降低方差

Bagging 的核心思想是:通过构建多个略有不同的数据集来训练多个模型,然后组合它们的预测。数学上,对于回归问题,bagging 的预测可以表示为:

$$\hat{f}{bag}(x) = \frac{1}{B}\sum(x)$$}^B \hat{f}^{*b

其中 $B$ 是基模型数量,$\hat{f}^{*b}$ 是在第 b 个自助样本上训练的模型。

对于分类问题,采用多数投票法。理论证明,如果基模型彼此独立,集成的方差可以降低为单个模型的 $1/B$。

随机特征选择的多样性增强

随机森林在 bagging 基础上增加了另一个随机性来源:在每棵树分裂节点时,只考虑特征的一个随机子集(而不是所有特征)。这样做的好处是:

  • 进一步降低模型间的相关性
  • 让不同的树关注数据的不同方面
  • 提高整体模型的鲁棒性

集成学习入门:以随机森林为例解析 Bagging 与随机特征选择如何降低过拟合

代码实战:用 sklearn 构建随机森林

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

# 加载数据
data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 创建随机森林模型
rf = RandomForestClassifier(
    n_estimators=100,  # 树的数量
    max_depth=5,       # 树的最大深度
    max_features='sqrt', # 每次分裂考虑的特征数(sqrt 是总特征数的平方根)min_samples_split=2, # 分裂节点所需的最小样本数
    random_state=42
)

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

# 评估模型
print(f"训练集准确率: {rf.score(X_train, y_train):.4f}")
print(f"测试集准确率: {rf.score(X_test, y_test):.4f}")

避坑指南

树深度与过拟合

  • 树太深:容易记住训练数据的细节,导致过拟合
  • 树太浅:模型可能欠拟合,无法捕捉数据中的模式

经验法则:

  1. 从适中的深度开始(如 5 -10)
  2. 观察训练和验证集性能差距
  3. 如果差距大(训练高,验证低),尝试减小 max_depth

特征重要性解读

随机森林提供的特征重要性基于:

  • 该特征被用于分裂的次数
  • 这些分裂带来的纯度改善总和

常见误区:

  • 认为重要性高的特征就是因果性的
  • 忽略特征间的相关性影响
  • 对重要性值的绝对大小过度解读

性能验证

学习曲线分析

import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve

# 绘制学习曲线
train_sizes, train_scores, test_scores = learning_curve(
    rf, X, y, cv=5, n_jobs=-1,
    train_sizes=np.linspace(0.1, 1.0, 5)
)

plt.plot(train_sizes, np.mean(train_scores, axis=1), label='训练分数')
plt.plot(train_sizes, np.mean(test_scores, axis=1), label='验证分数')
plt.xlabel('训练样本数')
plt.ylabel('准确率')
plt.legend()
plt.show()

理想情况下,我们会看到:

  • 训练和验证分数随着数据量增加而收敛
  • 两者之间的差距不大

对比单一决策树

from sklearn.tree import DecisionTreeClassifier

# 单一决策树
tree = DecisionTreeClassifier(max_depth=5, random_state=42)
tree.fit(X_train, y_train)

print(f"单一决策树测试集准确率: {tree.score(X_test, y_test):.4f}")
print(f"随机森林测试集准确率: {rf.score(X_test, y_test):.4f}")

通常会发现随机森林在测试集上表现更好,特别是当数据有噪声或特征间相关性复杂时。

延伸思考

  1. Bagging 的普适性 :你能想到其他可以应用 bagging 思想的算法吗?比如可以尝试对 KNN 或线性回归做 bagging。
  2. 特征工程 :随机森林提供的特征重要性可以用于指导特征选择,尝试用这些信息创建新特征或移除不重要的特征。
  3. 模型解释 :虽然随机森林比单一决策树更难解释,但可以探索 SHAP 值或部分依赖图等现代解释工具。

随机森林是机器学习工具箱中非常实用的算法,特别适合作为基准模型。通过理解其背后的 bagging 和随机特征选择机制,你不仅能更好地使用它,还能将这些思想应用到其他建模场景中。

正文完
 0
评论(没有评论)