机器学习基础

随机森林:三个臭皮匠

14 分钟

上一节结尾提到,单棵决策树方差高、不稳定。随机森林用一个朴素的想法解决它:种很多棵树,让它们投票。


核心直觉

一个人判断容易出错,但如果一群人各自独立判断然后投票,多数意见通常比任何单个人都准——前提是他们的错误不往同一个方向偏。

数学上:若单个模型的错误相互独立,平均之后方差会下降 个方差为 的独立预测取平均,方差变成

关键在「独立」二字。 如果所有树都长得一模一样,投票毫无意义。所以随机森林的全部技巧,都在制造差异


两重随机,制造差异

① 样本随机(Bagging)

每棵树不用全部训练数据,而是有放回地抽样出一个同样大小的子集。有放回意味着有的样本被抽中多次,有的一次没抽中。

数学上,每棵树大约只见到 63.2% 的原始样本()。

没被抽中的那 36.8% 叫袋外样本(OOB),可以直接拿来当验证集——这是随机森林白送的一个免费验证集,不用额外划分数据。

② 特征随机

每次分裂时,不考虑全部特征,只从随机抽取的一部分特征里选最佳切分

通常分类任务取 个特征( 是特征总数),回归任务取

这一步是随机森林相比普通 Bagging 的关键改进。 如果不做特征随机,遇到一个特别强的特征,所有树都会优先用它来切根节点,结果树与树高度相似,投票效果大打折扣。


用起来

from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(
    n_estimators=300,      # 种 300 棵树
    max_features='sqrt',   # 每次分裂随机看 sqrt(d) 个特征
    oob_score=True,        # 用袋外样本自测
    n_jobs=-1)             # 多核并行
clf.fit(X, y)
print(clf.oob_score_)      # 免费的验证分数

注意 n_jobs=-1:每棵树独立训练,天然可以并行,多核机器上几乎线性加速。这是随机森林相比下一节梯度提升的一大优势。


树的数量怎么选

随机森林不会因为树多而过拟合——这一点和单棵树完全不同。树越多,方差降得越低,只是收益递减、耗时增加。

实践中 100–500 棵通常足够,画一条「树数量 vs OOB 分数」曲线,看它在哪里走平就行。


特征重要性:免费的洞察

importances = clf.feature_importances_

它统计每个特征在所有树中带来的不纯度下降总量,告诉你哪些特征真正有用。这在特征工程和业务解释中非常实用。

但要注意一个陷阱:这种重要性对取值多的特征有偏好(连续特征、高基数类别特征会被高估)。更可靠的做法是用置换重要性permutation_importance)——把某一列打乱,看模型性能掉多少。


什么时候用随机森林

适合 不适合
表格数据、特征几十到几千 图像、语音、文本原始数据
需要快速拿到一个像样的基线 需要极致精度(用梯度提升)
想知道哪些特征重要 内存极度受限(要存几百棵树)

一条实用建议:拿到一份表格数据,先跑随机森林当基线。 它几乎不用调参就能给出不错的结果,用来判断「这个问题到底有多难」。

练习:解释一下——如果去掉「特征随机」这一重,只保留样本随机,随机森林的效果为什么会变差?

小纸条

随机森林靠哪两重随机制造树之间的差异?为什么「特征随机」这一重不能省?OOB 是什么?

登录 后可看答案