4、决策树与随机森林:从一棵树到一片森林
决策树和随机森林,说白了就是让机器学会「做选择题」。
我刚开始接触这个领域时,觉得决策树特别直观——它就像我们平时做决定一样,一步步问问题,最后得出结论。但真正用到策略生成里,才发现这里面坑不少。今天咱们就聊聊这个。
4.1 决策树构建原理
决策树的核心思想很简单:把数据不断切分,直到每个子集足够「纯」。
举个例子。假设我们要判断一个用户会不会点击广告。决策树会先问:「用户年龄大于30吗?」如果答案是「是」,再问:「用户最近7天有登录吗?」如果答案是「否」,那可能就不推荐了。你看,这就是一棵树。
但问题来了:先问哪个特征?
这里有个关键指标——信息增益。说白了,就是看某个特征能把数据「分得多开」。我习惯用信息熵来度量:
# 信息熵计算示例
import numpy as np
def entropy(y):
"""计算信息熵"""
_, counts = np.unique(y, return_counts=True)
probs = counts / len(y)
return -np.sum(probs * np.log2(probs))
# 假设有10个样本,6个正类,4个负类
y = [1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
print(f"信息熵: {entropy(y):.3f}") # 输出: 0.971
嗯,这里要注意:信息增益越大,说明这个特征越能帮我们做决策。决策树就是靠这个原则,一步步选择最优特征来分裂。
核心要点:决策树的每个节点都在问「选哪个特征、怎么切分」,目标是让子节点的纯度最高。
4.2 随机森林在策略生成中的应用
单棵决策树有个致命问题——容易过拟合。你想想看,如果树长得太深,它可能把训练集里的噪声都记住了。
我在项目中遇到过这种情况:用单棵决策树做用户分群策略,训练集准确率98%,上线后直接掉到65%。为什么?因为树把一些偶然的样本特征当成了规律。
随机森林就是来解决这个问题的。它的思路很朴素:多找几棵树,让它们投票。
具体做法有两步:
- 随机选择样本:每棵树只从原始数据里随机抽一部分来训练(有放回抽样)
- 随机选择特征:每个节点分裂时,只从部分特征里选最优的
这样一来,每棵树都「看到」了不同的数据,也「关注」了不同的特征。它们各自有偏见,但合在一起反而更准确。
# 随机森林策略生成示例
from sklearn.ensemble import RandomForestClassifier
# 假设我们有用户特征和是否点击的标签
X = [[25, 1, 0], [35, 0, 1], [28, 1, 1], [40, 0, 0]]
y = [1, 0, 1, 0]
# 构建随机森林
rf = RandomForestClassifier(
n_estimators=100, # 100棵树
max_depth=5, # 每棵树最大深度
random_state=42
)
rf.fit(X, y)
# 查看特征重要性
print(f"特征重要性: {rf.feature_importances_}")
我的经验:随机森林在策略生成中特别好用。比如做风控策略,我会用随机森林找出哪些特征最「重要」,然后基于这些特征设计规则。这样既保留了可解释性,又提升了稳定性。
4.3 过拟合与剪枝策略
过拟合是决策树的老大难问题。我曾经接手过一个项目,同事用决策树做推荐策略,树深到了20层。结果呢?线上效果还不如随机推荐。
为什么会这样?因为树把训练集里的每个细节都记住了,包括那些纯属巧合的样本。新数据一来,它反而不会「思考」了。
解决过拟合,核心手段就是剪枝。剪枝分两种:
| 剪枝类型 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 预剪枝 | 在树生长过程中提前停止 | 效率高,训练快 | 可能欠拟合 |
| 后剪枝 | 先让树长全,再剪掉不重要的分支 | 效果通常更好 | 计算量大 |
我个人习惯用预剪枝,因为它简单直接。常用的预剪枝参数有:
- max_depth:限制树的最大深度。我一般设3-5层,够用就行
- min_samples_split:节点分裂所需的最小样本数。设太大会欠拟合,太小会过拟合
- min_samples_leaf:叶子节点最少样本数。这个我通常设5-10
避坑指南:我曾经在调参时把min_samples_split设成了1,结果树长得跟藤蔓似的,完全失控。记住:剪枝参数不是越小越好,要结合验证集效果来调。
后剪枝虽然效果好,但实现起来麻烦一些。它的思路是:先让树长到最大,然后从下往上检查每个节点,如果去掉这个节点能让验证集效果提升,就把它剪掉。
# 后剪枝的简化思路
def prune_tree(tree, X_val, y_val):
"""后剪枝:从叶子往上检查"""
# 如果当前节点是叶子,直接返回
if tree.is_leaf():
return tree
# 递归剪枝左右子树
tree.left = prune_tree(tree.left, X_val, y_val)
tree.right = prune_tree(tree.right, X_val, y_val)
# 检查合并后效果是否更好
if should_merge(tree, X_val, y_val):
return make_leaf(tree)
return tree
嗯,这里要注意:后剪枝虽然效果好,但计算量确实大。如果你的数据量很大,建议先用预剪枝快速迭代,最后再用后剪枝精调。
总结一下:决策树是策略生成的好工具,但一定要配合剪枝使用。随机森林通过集成多棵树,天然抗过拟合,是更稳妥的选择。我个人建议:做原型用决策树,上线用随机森林。
好了,关于决策树和随机森林,咱们就聊到这儿。记住:工具是死的,思路是活的。下次遇到策略生成问题,不妨先想想——用一棵树还是用一片森林?
公众号:蓝海资料掘金营,微信deep3321