ML:随机森林的基本原理与实现
在机器学习中单棵决策树虽然直观、易解释但它也有一个很明显的问题对训练数据的微小变化往往比较敏感容易长得过深从而产生过拟合。随机森林Random Forest正是在这种背景下发展起来的重要方法。一、随机森林的基本思想随机森林的核心思想是训练多棵彼此不同的决策树并把它们的结果进行综合。如果只训练一棵决策树那么这棵树可能会过度依赖某些训练样本或某些特征从而把训练集中的偶然波动也学进去。随机森林则尝试通过“多样化 集成”的方式缓解这个问题。从直观上看随机森林完成的是这样一件事• 不只看一棵树而是同时训练很多棵树• 每棵树都基于一个略有差异的数据视角进行学习• 每棵树在分裂时也不会总是看到全部特征• 最终分类时采用投票回归时采用平均图 1随机森林的基本工作流程Scikit-learn 对随机森林的描述正是它是一种元估计器meta estimator会在数据的不同子样本上拟合多棵决策树并通过平均来提升预测准确性、控制过拟合分类场景对应 RandomForestClassifier回归场景对应 RandomForestRegressor。这说明随机森林并不是在发明一种全新的“树结构”而是在已有决策树基础上通过集成策略提升整体性能。二、随机森林为什么能比单棵树更稳图 2单棵决策树与随机森林的对比1、单棵树的问题单棵决策树的表达能力很强但也正因为如此它容易把训练集中的局部噪声和偶然模式学进去。这意味着• 单棵树往往方差较大• 数据稍有变化树结构就可能明显改变• 预测结果容易不稳定2、集成带来的稳定性如果训练很多棵树并让这些树尽可能“不要完全一样”那么每棵树出错的方式就不会完全一致。在这种情况下把它们的结果综合起来通常会产生两个重要效果• 分类中多数投票可以削弱个别树的错误判断• 回归中平均值可以平滑个别树的波动输出这就是随机森林比单棵树更稳健的根本原因。随机森林的核心就是用多棵带随机性的树来换取更好的泛化能力。3、关键不只是“多”而是“不同”需要注意的是随机森林成功的关键不只是树多而是这些树要彼此存在差异。如果所有树都看到完全相同的数据、总在每个节点上选择相同特征那么它们最终会非常相似集成的收益就会大幅下降。因此随机森林会通过两种主要机制来制造差异• 对训练样本做随机抽样• 对候选特征做随机抽样这两种随机性正是“random forest”中“random”的来源。三、随机森林中的两种随机机制1、自助采样让每棵树看到不同样本子集随机森林通常对原始训练集进行有放回抽样也就是 Bootstrap Sampling。这样每棵树虽然都来自同一份原始数据但它们实际看到的训练子集并不完全相同。图 3随机森林中的 Bootstrap 自助采样Scikit-learn 的随机森林分类器RandomForestClassifier和随机森林回归器RandomForestRegressor默认都使用 bootstrapTrue。如果开启 bootstrap每棵树所使用的样本子集大小还可以通过 max_samples 控制若 bootstrapFalse则每棵树会使用整个数据集。这意味着不同树训练在不同样本分布上树之间自然会产生差异这种差异有助于降低整体方差。2、特征子采样让每次分裂都更随机随机森林的第二种关键随机性不是在整棵树层面而是在每个节点分裂时体现出来。图 4随机森林中的特征随机子采样具体来说当树在某个节点寻找最佳划分特征时它并不会总是看全部特征而只会从一个随机抽取的特征子集中寻找最佳分裂。这正是 max_features 参数控制的内容。Scikit-learn 当前默认设置中分类器和回归器的 max_features 都是 sqrt也就是说在每次分裂时只考虑总特征数平方根数量级的随机特征子集。这意味着强势特征不会在所有树、所有节点上都一统天下不同树会学到不同的特征组合与划分路径集成结果会因此更加多样化。四、随机森林的预测方式1、分类多数投票在分类问题中随机森林会让每棵树分别给出一个类别判断然后以多数投票作为最终结果。图 5随机森林分类的多数投票机制如果有 T 棵树第 t 棵树对样本 x 的预测记为hₜ(x)那么最终类别可以理解为也就是说哪一个类别获得的票数最多就把样本判为哪一类。2、回归取平均值在回归问题中随机森林会让每棵树分别输出一个数值预测再对这些预测值做平均这里• T 表示树的数量• hₜ(x) 表示第 t 棵树的输出• ŷ 表示最终预测值图 6随机森林回归的平均预测机制这说明随机森林在分类和回归中虽然输出形式不同但核心思想是一致的把多棵树的判断进行综合。3、树的数量不是越少越好随机森林中的 n_estimators 表示树的数量。Scikit-learn 当前默认值为 100。一般来说树越多结果越稳定但训练与预测开销也会更大。因此n_estimators 并不是一个追求“越小越精简”的参数而更像是在计算成本与稳定性之间做权衡。五、随机森林的主要参数1、n_estimatorsn_estimators 表示森林中树的数量。树的数量越多模型通常越稳定但训练和预测时间也会增加。Scikit-learn 当前默认值是 100。2、max_featuresmax_features 表示每次分裂时可供选择的特征数。它直接决定了树之间的差异程度也是随机森林区别于普通 bagging 决策树的重要参数之一。当前默认值是 sqrt。3、max_depthmax_depth 用于限制单棵树的最大深度。如果不限制树可能会长得很深虽然单棵树拟合更强但也更容易复杂化。随机森林虽然通过集成缓解了过拟合但单棵树深度仍然值得控制。4、min_samples_split与min_samples_leaf这两个参数分别控制• 一个内部节点至少有多少样本才允许继续分裂• 一个叶节点至少保留多少样本它们都是调节单棵树复杂度的重要手段。5、bootstrap与max_samplesbootstrap 决定是否使用自助采样默认值为 True。max_samples 则在 bootstrapTrue 时控制每棵树实际抽取多少样本。这些参数共同决定了随机森林在“树的数量、树的复杂度、树之间差异性”三个方面的整体行为。六、模型结果如何解释1、比单棵树弱一些但仍有一定解释性随机森林的一个重要特点是它通常比单棵决策树预测更稳但可解释性会有所下降。原因很简单单棵树可以直接画出来而随机森林由很多棵树组成不再容易用一条清晰规则概括整体行为。2、特征重要性尽管整体规则难以完全展开随机森林仍常通过特征重要性来给出一定程度的解释。图 7随机森林中的特征重要性Scikit-learn 的树模型示例中随机森林训练后可以通过 feature_importances_ 查看基于树分裂贡献的特征重要性。这意味着我们通常可以回答• 哪些特征对模型更重要• 哪些特征几乎没有贡献但需要注意的是这种重要性并不等同于因果关系也不应被过度解释。3、局部解释与整体解释从整体上看随机森林不像线性回归那样能给出一组统一系数也不像单棵树那样能给出一条清晰路径规则。它更适合用来回答• 哪些特征总体上更有用• 模型预测整体上依赖哪些变量而不太适合直接给出一条“全局公式”。七、Python 实现随机森林分类示例下面用鸢尾花数据集演示随机森林分类的基本实现方式。RandomForestClassifier 用于分类任务。每棵树使用最佳分裂策略相当于底层 DecisionTreeClassifier(splitterbest)但通过样本与特征随机性形成整体集成。from sklearn.datasets import load_iris # 加载鸢尾花数据集from sklearn.ensemble import RandomForestClassifier # 随机森林分类器集成学习from sklearn.model_selection import train_test_split # 数据集划分 # 1. 加载数据iris load_iris()X iris.data # 特征 (150,4)y iris.target # 标签 (150,) # 2. 划分训练集与测试集测试集20%固定随机种子X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42) # 3. 创建随机森林分类器model RandomForestClassifier( n_estimators100, # 决策树数量集成100棵子树 max_depth4, # 每棵树最大深度限制复杂度 random_state42 # 固定随机种子保证可复现) # 4. 训练模型Bagging集成每棵树用不同自助样本训练model.fit(X_train, y_train) # 5. 预测所有树投票决定最终类别y_pred model.predict(X_test) print(前 10 个预测结果, y_pred[:10])print(测试集得分, model.score(X_test, y_test)) # 平均准确率print(特征重要性, model.feature_importances_) # 各特征对分类的贡献度总和为1这段代码展示了随机森林分类的基本工作流1、生成或加载数据2、划分训练集与测试集3、创建分类器4、用 fit 训练森林5、用 predict 输出类别6、用 feature_importances_ 查看特征重要性这里的 score() 对分类器默认返回准确率。八、Python 实现随机森林回归示例下面再给出一个回归示例说明随机森林如何通过多棵回归树的平均来完成连续数值预测。RandomForestRegressor 的基本思想与分类器相同只是最终输出由多数投票改为平均值。from sklearn.datasets import make_regression # 生成回归数据集from sklearn.ensemble import RandomForestRegressor # 随机森林回归器from sklearn.model_selection import train_test_split # 数据集划分 # 1. 生成回归数据X, y make_regression( n_samples200, # 200个样本 n_features5, # 5个特征 n_informative5, # 全部特征有效无冗余 noise20, # 添加噪声标准差20 random_state42) # 2. 划分训练集与测试集测试集20%X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42) # 3. 创建随机森林回归器model RandomForestRegressor( n_estimators100, # 100棵决策树 max_depth6, # 每棵树最大深度 random_state42) # 4. 训练模型所有树结果取平均作为最终预测model.fit(X_train, y_train) # 5. 预测y_pred model.predict(X_test) print(前 5 个真实值, y_test[:5])print(前 5 个预测值, y_pred[:5])print(测试集得分, model.score(X_test, y_test)) # R²决定系数越接近1越好print(特征重要性, model.feature_importances_) # 各特征贡献度总和为1这段代码说明随机森林回归并不是拟合一个单一公式而是通过多棵回归树分别给出预测再把这些结果平均起来。九、随机森林的适用场景与主要局限图 8随机森林的适用场景与主要局限1、适用场景随机森林较适合以下情况• 可以是分类任务也可以是回归任务• 特征与目标之间可能存在非线性关系• 希望模型比单棵树更稳健• 不想做过多复杂特征工程• 需要一个强力而通用的基线模型在很多实际任务中随机森林都是非常常见的首选基线之一。2、主要局限随机森林虽然强大但也并不是万能方法。1可解释性弱于单棵树整体决策逻辑更难完整展开。2模型体积和计算开销更大树多时训练和预测都更重。3对非常高维稀疏数据不一定最优在某些文本等任务中线性模型可能更合适。4特征重要性不等于因果关系解释时需要谨慎。5仍需调参树数、深度、特征采样比例等都会影响结果。因此随机森林更像是一种“稳健、强力、通用”的集成树模型而不是任何情况下都绝对最优的终极方案。 小结随机森林通过“样本随机抽样 特征随机抽样 多树集成”的方式提升了决策树的稳定性与泛化能力。它是理解 bagging、集成学习与树模型增强的重要入口。“点赞有美意赞赏是鼓励”