1. 引言:从“独木”到“森林”

在上一篇文章中,我们深入探讨了支持向量机(SVM),一个以寻找最优超平面为核心的强力分类器。然而,许多实际问题通过集成多个“弱”学习器来构建一个“强”学习器,往往能取得更稳健、更强大的效果。随机森林(Random Forest) 正是这类集成学习方法的杰出代表。

随机森林的核心思想简单而强大:通过自助采样(Bootstrap)生成多个不同的训练集,并在每个训练集上训练一棵决策树,最后通过投票(分类)或平均(回归)来汇总所有树的预测结果。 “随机”体现在两个方面:①每棵树的训练样本是随机有放回抽样的;②每棵树在分裂节点时,只随机选取一部分特征进行考虑。这两重随机性,极大地降低了模型的方差,增强了其泛化能力,使其不易过拟合。

SVM与随机森林各具特点:

  • SVM 更侧重于通过复杂的数学变换(核技巧)在高维空间寻找清晰的决策边界。
  • 随机森林 则更侧重于通过“群体的智慧”来鲁棒地拟合数据规律,且能提供宝贵的特征重要性评估。

本文将带你:

  1. 理解决策树集成学习的基本概念。
  2. 掌握随机森林的构建原理与关键参数。
  3. 使用scikit-learn,在同一个鸢尾花数据集上,完整实现一个随机森林分类任务。
  4. 通过对比分析,直观感受随机森林与SVM的异同与各自优势。

2. 目录

3. 环境与数据准备

环境配置与上一篇文章基本一致,确保scikit-learnnumpypandasmatplotlib已安装。

pip install numpy pandas matplotlib scikit-learn

我们将继续使用鸢尾花数据集(Iris Dataset)。为了确保与SVM实验的可比性,数据的加载方式、划分比例、随机种子以及预处理(标准化)步骤将保持完全一致

4. 随机森林核心原理简述

4.1 基石:决策树

决策树是随机森林的基本组成单元。它通过一系列**“if-then-else”规则对数据进行划分。其目标是将数据集划分为越来越“纯”的子集。划分标准通常使用基尼不纯度(Gini Impurity)** 或信息增益(Information Gain)

一棵简单的决策树就像一个流程图:从根节点开始,根据某个特征(如“花瓣长度≤2.45cm?”)将数据分成两组,然后递归地对子节点进行同样的操作,直到节点足够“纯”或达到停止条件。

优点:模型直观,易于解释。
缺点:单棵决策树非常容易过拟合,对训练数据中的噪声和细微波动过于敏感,导致泛化能力差。

4.2 核心:Bagging与特征随机性

随机森林通过集成多棵决策树来克服单棵树的弱点。其构建过程如下:

  1. Bagging(自助聚合)

    • 假设原始训练集有 N N N 个样本。
    • 随机且有放回地从原始数据集中抽取 N N N 个样本,形成一个自助样本集。由于是有放回抽样,每个自助样本集中约有 63.2 63.2% 63.2 的原始样本,其余的样本称为袋外样本(Out-of-Bag, OOB)
    • 重复上述过程 T T T 次,生成 T T T 个不同的自助样本集。
  2. 特征随机性

    • 在训练每棵决策树的每个节点进行分裂时,不从所有 d d d 个特征中选择最优特征,而是随机选取 k k k 个特征( k ≪ d k \ll d kd,然后仅在这 k k k 个特征中寻找最优划分。
    • 通常,对于分类问题, k = d k = \sqrt{d} k=d ;对于回归问题, k = d / 3 k = d/3 k=d/3。这是一个关键超参数(max_features)。
  3. 汇总预测

    • 对于一个新的样本,将其输入到所有 T T T 棵决策树中。
    • 分类任务:每棵树投票预测一个类别,得票最多的类别作为最终预测结果。
    • 回归任务:所有树的预测值取平均,作为最终预测结果。

“随机”的作用:Bagging让每棵树学习数据的不同“视角”,特征随机性进一步降低了树与树之间的相关性。当这些“略有不同”的树组合在一起时,它们的平均预测会比任何单棵树都更稳定、更准确。

5. 代码实现详解

5.1 导入库与数据加载(对比SVM)

我们加载与SVM文章中完全相同的数据,以便后续进行直接对比。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings(‘ignore’)

# 加载鸢尾花数据集
iris = datasets.load_iris()
df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
df[‘target’] = iris.target
print(“数据集信息(与SVM文章一致):”)
print(df.head())
print(f”数据集形状:{df.shape})

5.2 数据预处理与划分(保持一致性)

# 划分特征和标签
X = iris.data
y = iris.target

# 使用与SVM文章相同的随机种子和划分比例,确保可比性
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

print(f”训练集大小:{X_train.shape[0]})
print(f”测试集大小:{X_test.shape[0]})

# 特征标准化(虽然树模型对尺度不敏感,但为保持流程一致性,我们仍进行标准化)
# 注意:实践中,对于纯粹的决策树/随机森林,不标准化通常影响很小。
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

5.3 构建随机森林模型并训练

我们将先使用默认参数构建一个基准模型。

# 构建随机森林分类器
# 关键参数:
# n_estimators: 森林中树的数量,越多通常越好,但计算成本也越高。
# max_features: 每次分裂时考虑的最大特征数,’sqrt’表示sqrt(特征总数)。
# random_state: 控制Bootstrap抽样和特征选择的随机性,确保结果可复现。
rf_model = RandomForestClassifier(n_estimators=100, max_features=‘sqrt’, random_state=42, n_jobs=-1)

# 训练模型
rf_model.fit(X_train_scaled, y_train)

print(“随机森林模型训练完成!”)
print(f”森林中决策树的数量:{rf_model.n_estimators})

5.4 模型预测、评估与特征重要性分析

  随机森林的一个巨大优势是能够提供特征重要性评分,这对于理解模型和数据非常有帮助。

# 在测试集上预测
y_pred_rf = rf_model.predict(X_test_scaled)

# 计算准确率
accuracy_rf = accuracy_score(y_test, y_pred_rf)
print(f”随机森林模型准确率:{accuracy_rf:.4f})

# 打印详细分类报告
print(“\n随机森林分类报告:”)
print(classification_report(y_test, y_pred_rf, target_names=iris.target_names))

# 混淆矩阵
print(“随机森林混淆矩阵:”)
print(confusion_matrix(y_test, y_pred_rf))

# 获取特征重要性
feature_importances = rf_model.feature_importances_
feature_names = iris.feature_names

# 创建特征重要性的DataFrame并排序
fi_df = pd.DataFrame({
    ‘Feature’: feature_names,
    ‘Importance’: feature_importances
}).sort_values(by=‘Importance’, ascending=False)

print(“\n特征重要性排序:”)
print(fi_df)

# 绘制特征重要性图
plt.figure(figsize=(10, 6))
plt.barh(fi_df[‘Feature’], fi_df[‘Importance’])
plt.xlabel(‘重要性分数’)
plt.ylabel(‘特征’)
plt.title(‘随机森林 - 特征重要性’)
plt.gca().invert_yaxis() # 最重要的特征在顶部
plt.tight_layout()
plt.show()

结果解读:你将看到类似“花瓣长度”和“花瓣宽度”的重要性远高于“花萼宽度”,这符合我们对鸢尾花分类的直观认知。

5.5 关键参数调优:网格搜索

  随机森林的性能对参数敏感。我们使用网格搜索(GridSearchCV)交叉验证来寻找最优参数组合。

# 定义要搜索的参数网格
param_grid = {
    ‘n_estimators’: [50, 100, 200], # 树的数量
    ‘max_features’: [‘sqrt’, ‘log2’], # 考虑的特征数
    ‘max_depth’: [None, 10, 20], # 树的最大深度,None表示不限
    ‘min_samples_split’: [2, 5], # 节点分裂所需的最小样本数
}

# 初始化网格搜索对象
# cv=5表示5折交叉验证, n_jobs=-1表示使用所有CPU核心并行计算
grid_search = GridSearchCV(estimator=RandomForestClassifier(random_state=42),
                           param_grid=param_grid,
                           cv=5,
                           n_jobs=-1,
                           verbose=1)

# 执行网格搜索
grid_search.fit(X_train_scaled, y_train)

# 输出最佳参数和最佳分数
print(f”最佳参数:{grid_search.best_params_})
print(f”最佳交叉验证准确率:{grid_search.best_score_:.4f})

# 使用最佳模型在测试集上评估
best_rf_model = grid_search.best_estimator_
y_pred_best = best_rf_model.predict(X_test_scaled)
accuracy_best = accuracy_score(y_test, y_pred_best)
print(f”优化后模型在测试集上的准确率:{accuracy_best:.4f})

6. 结果分析与与SVM的对比思考

  现在,让我们将随机森林的结果与上一篇文章SVM的结果放在同一张桌子上进行对比。

评估维度 支持向量机 (SVM) 随机森林 (Random Forest)
测试集准确率 约 96%-98% 约 96%-100% (调优后)
核心优势 高维表现佳,理论清晰,泛化能力强 抗过拟合,可并行训练,提供特征重要性
主要劣势 参数敏感,大规模数据训练慢 模型解释性稍弱于单棵决策树,内存占用大
关键参数 C, kernel, gamma n_estimators, max_features, max_depth
是否需要特征标准化 非常关键 不影响性能(但保持流程一致性有时也做)
对新数据/特征的解释 决策边界依赖于支持向量 可直接给出每个特征对预测的贡献度

深度思考

  1. 数据视角:在本例中(小数据、清晰特征),两者性能相近。但在特征维度极高(如文本数据)样本噪声较大时,随机森林的Bagging和特征随机性可能带来更好的鲁棒性。而SVM在中小型、特征经过良好工程的数据上往往表现优异。
  2. 任务视角:随机森林的特征重要性输出,对于数据探索和业务解释极其有价值。例如,在金融风控中,知道“征信记录”比“年龄”重要得多,比单纯知道模型预测准确率为98%更有意义。
  3. 实践视角:随机森林通常作为强基线模型使用。在项目初期,用默认参数跑一个随机森林,就能快速获得一个不错的结果和特征重要性洞察,指导后续的特征工程和模型选择。SVM则可能需要更多的调参工作。

结论:没有“最好”的模型,只有“最合适”的模型。SVM和随机森林代表了两种不同的建模哲学:一个是通过数学优化寻找确定性边界,另一个是通过统计方法集成多样性结果。理解它们的原理和差异,是机器学习工程师的关键素养。

7. 总结与完整代码获取

本文我们完成了从单棵决策树到随机森林的飞跃:

  1. 理解了决策树的原理及其易过拟合的缺点。
  2. 掌握了随机森林通过Bagging和特征随机性集成多棵树的核心思想。
  3. 在鸢尾花数据集上复现了完整的机器学习流程,并特别强调了与SVM实验的对比分析。
  4. 实践了利用特征重要性和网格搜索进行模型解释与优化。

  随机森林以其优秀的性能、稳定的输出和良好的可解释性,在Kaggle竞赛和工业界中经久不衰,是每个机器学习者工具箱中必备的利器。

本文完整代码已整合在上文各步骤中,你可以直接复制运行。对比实验可以非常直观地感受两种算法的异同。

如果你对SVM或随机森林有更深的疑问,或者想探讨其他集成算法(如梯度提升树GBDT、XGBoost),欢迎在评论区留言。别忘了点赞、收藏,以便后续学习参考!

8. 参考文献

  1. Breiman, L. (2001). Random forests. Machine learning, 45(1), 5-32.
  2. Scikit-learn官方文档 - RandomForestClassifier: https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
  3. Scikit-learn官方文档 - GridSearchCV: https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html
  4. Hastie, T., Tibshirani, R., & Friedman, J. (2009). The elements of statistical learning: data mining, inference, and prediction. Springer Science & Business Media.
  5. 周志华. 《机器学习》. 清华大学出版社. - 第8章 集成学习。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐