随机森林:三个臭皮匠
约 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 是什么?
登录 后可看答案