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%。为什么?因为树把一些偶然的样本特征当成了规律。

随机森林就是来解决这个问题的。它的思路很朴素:多找几棵树,让它们投票

具体做法有两步:

  1. 随机选择样本:每棵树只从原始数据里随机抽一部分来训练(有放回抽样)
  2. 随机选择特征:每个节点分裂时,只从部分特征里选最优的

这样一来,每棵树都「看到」了不同的数据,也「关注」了不同的特征。它们各自有偏见,但合在一起反而更准确。

# 随机森林策略生成示例
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