随机森林
分类算法 - 随机森林
Section titled “分类算法 - 随机森林”随机森林简介
Section titled “随机森林简介”随机森林 (Random Forest) 是一种强大且广泛使用的集成学习 (ensemble learning) 方法,基于决策树构建。它可用于分类 (classification) 和回归 (regression) 任务,但在分类中尤为流行。
核心思想很简单:在训练过程中构建大量的决策树(“森林”),对于分类任务,输出单个树输出类别的众数 (mode)(最常见类别);对于回归任务,输出单个树预测值的平均值 (mean prediction)。
它利用了两个关键技术来创建多样化的树,从而提升单一决策树的性能:
- Bagging (自助聚合): 森林中的每棵树都在一个不同的随机训练数据子集上进行训练,该子集采用有放回抽样 (bootstrap sample)。
- 随机特征子集 (Random Feature Subsets): 在构建树时,每个节点进行分裂时,仅考虑特征 (features) 的随机子集来寻找最佳分裂点(而非考虑所有特征)。
这两个随机源有助于去相关森林中的树。虽然单个树可能容易过拟合 (overfitting),但对其预测结果进行平均可以降低方差 (variance),从而得到一个更鲁棒 (robust)、更准确的模型,对未见数据具有更好的泛化能力 (generalization)。
随机森林的工作原理
Section titled “随机森林的工作原理”构建随机森林分类器的算法通常包含以下步骤:
- 指定树的数量 (
n_estimators): 决定在森林中构建多少棵决策树(例如 100, 500)。 - 对于每棵树:
- a. 创建 Bootstrap 样本: 通过有放回抽样从原始训练数据中选择一个随机子集。该样本通常与原始数据集大小相同,但会包含重复的实例并省略其他实例。
- b. 构建决策树: 在此 bootstrap 样本上构建一棵决策树。
-
- **随机特征选择:** 在每个节点上,随机选择一个特征子集(由 `max_features` 超参数控制)。
-
- **寻找最佳分裂点:** 在*选定*的特征中,使用标准准则(如基尼不纯度 Gini impurity 或信息熵 entropy)寻找最佳分裂点。
-
- **通常完全生长:** 将树生长到最大可能大小,不进行剪枝(尽管可以使用 `max_depth` 或 `min_samples_leaf` 等超参数控制树的复杂度)。
- 预测: 对新的数据点进行分类:
- a. 将该数据点通过森林中的每一棵树,从每棵树获得一个预测结果。
- b. 聚合预测结果: 执行多数投票 (majority vote):最高数量的树预测的类别即为随机森林的最终预测结果。
概念上可以这样理解:想象一下,询问许多略有不同的专家(单个树,它们在不同的数据子集上训练,并考虑不同的因素)的意见,然后采纳最普遍的意见。
在 Python 中实现 (Scikit-learn)
Section titled “在 Python 中实现 (Scikit-learn)”我们将使用 Scikit-learn 的 RandomForestClassifier 在 Iris 数据集上进行演示。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsfrom sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_splitfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.metrics import classification_report, confusion_matrix, accuracy_score
# 1. 加载 Iris 数据集iris = load_iris()X = iris.datay = iris.targetfeature_names = iris.feature_namesclass_names = iris.target_names
# 2. 将数据分割为训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
# 3. 创建随机森林分类器对象# 关键超参数:# n_estimators: 森林中树的数量# max_features: 在每个分裂处考虑的特征数量('sqrt' 或 'log2' 是常见默认值)# max_depth: 单个树的最大深度(控制复杂度)# min_samples_split: 分割内部节点所需的最小样本数# min_samples_leaf: 叶节点所需的最小样本数# random_state: 用于结果重现# n_jobs: 使用的 CPU 核数(-1 表示使用所有可用核)
rf_clf = RandomForestClassifier(n_estimators=100, # 构建 100 棵树 random_state=42, n_jobs=-1, # 使用所有核 oob_score=True) # 启用袋外 (Out-of-Bag) 分数估计
# 4. 训练随机森林分类器rf_clf.fit(X_train, y_train)
# 5. 袋外 (Out-of-Bag, OOB) 分数(可选但有用)# OOB 分数是使用在 bootstrap 采样过程中未见过特定样本的树来估计泛化准确度。# 这就像内置的交叉验证。print(f"Out-of-Bag (OOB) Score Estimate: {rf_clf.oob_score_:.4f}\n")
# 6. 预测测试数据集的响应y_pred = rf_clf.predict(X_test)
# 7. 评估模型print("--- 在测试集上评估模型 ---")conf_mat = confusion_matrix(y_test, y_pred)acc = accuracy_score(y_test, y_pred)class_rep = classification_report(y_test, y_pred, target_names=class_names)
print(f"Test Accuracy: {acc:.4f}")print("\n混淆矩阵:")plt.figure(figsize=(6, 4))sns.heatmap(conf_mat, annot=True, fmt='d', cmap='Blues', xticklabels=class_names, yticklabels=class_names)plt.xlabel('预测标签')plt.ylabel('真实标签')plt.title('混淆矩阵 - 随机森林')plt.show()
print("\n分类报告:")print(class_rep)
# 8. 特征重要性importances = rf_clf.feature_importances_indices = np.argsort(importances)[::-1] # 按降序排列特征重要性
print("\n--- 特征重要性 ---")for i in range(X.shape[1]): print(f"{i + 1}. Feature '{feature_names[indices[i]]}' ({importances[indices[i]]:.4f})")
# Plot feature importancesplt.figure(figsize=(10, 5))plt.title("特征重要性 - 随机森林")plt.bar(range(X.shape[1]), importances[indices], align="center")plt.xticks(range(X.shape[1]), [feature_names[i] for i in indices], rotation=45)plt.xlim([-1, X.shape[1]])plt.ylabel('重要性')plt.tight_layout()plt.show()输出(示例)
Section titled “输出(示例)”Out-of-Bag (OOB) Score Estimate: 0.9429
--- Model Evaluation on Test Set ---Test Accuracy: 1.0000
Confusion Matrix:(Seaborn heatmap plot showing perfect classification on the test set for Iris)
Classification Report: precision recall f1-score support
setosa 1.00 1.00 1.00 15 versicolor 1.00 1.00 1.00 15 virginica 1.00 1.00 1.00 15
accuracy 1.00 45 macro avg 1.00 1.00 1.00 45weighted avg 1.00 1.00 1.00 45
--- Feature Importances ---1. Feature 'petal width (cm)' (0.4445)2. Feature 'petal length (cm)' (0.4233)3. Feature 'sepal length (cm)' (0.1066)4. Feature 'sepal width (cm)' (0.0256)输出展示了如何训练一个随机森林模型,获取 OOB 分数(无需单独验证集即可可靠估计性能),在测试集上评估模型(在此简单数据集上达到完美准确率),以及检查特征重要性。根据该模型,花瓣特征(‘petal width’ 和 ‘petal length’)在分类 Iris 物种时比萼片特征 (‘sepal length’ 和 ‘sepal width’) 显着更重要。
随机森林的优缺点
Section titled “随机森林的优缺点”- 高准确性: 通常在许多任务中实现高预测准确度。
- 鲁棒性强,不易过拟合: 由于对多个去相关的树的预测结果进行平均,因此比单一决策树更不易过拟合。
- 处理非线性: 继承了决策树捕捉复杂非线性关系的能力。
- 处理缺失值: 可以相对较好地处理缺失数据(尽管通常仍建议进行数据填充 imputation)。
- 特征重要性: 提供可靠的特征重要性估计。
- 较少的数据预处理: 通常无需大量的特征缩放即可工作良好。
- 可并行化: 单个树的训练可以并行进行,在多核系统上可加速计算 (
n_jobs=-1)。 - OOB 估计: 无需单独的验证集即可提供泛化误差的无偏估计。
- 可解释性较低: 与单一决策树相比,可以被视为一个“黑箱”。难以理解某个预测背后的确切推理过程。
- 计算密集: 与线性回归或朴素贝叶斯等更简单的模型相比,训练和预测可能较慢,尤其当树数量或数据集较大时。
- 内存占用: 存储森林(许多树)可能需要大量内存。
- 仍可能过拟合: 虽然更鲁棒,但如果超参数(如树深度)未受约束,仍可能在嘈杂数据集上过拟合。
- 偏向高基数特征: 对于具有许多类别的分类特征,随机森林可能偏向于选择这些特征。
随机森林被应用于许多领域:
- 金融: 信用评分,欺诈检测。
- 医疗保健: 疾病预测,患者结果预测。
- 电子商务: 推荐系统,客户流失预测。
- 遥感: 土地覆盖分类。
- 生物学: 基因表达分析。
- Scikit-learn 随机森林文档:https://scikit-learn.org/stable/modules/ensemble.html#random-forests
- StatQuest: 随机森林解释:https://statquest.org/video-index/(搜索 Random Forests)