Python实战:如何用CART决策树解决分类问题中的过拟合难题

1次阅读
没有评论

共计 2317 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

技术背景

CART(Classification and Regression Trees)决策树是一种经典的非参数监督学习方法,通过递归二分数据空间构建树结构。其核心优势在于:

Python 实战:如何用 CART 决策树解决分类问题中的过拟合难题

  • 直观的可解释性:决策路径可转化为 if-then 规则
  • 自动特征选择:通过信息增益或基尼系数筛选重要特征
  • 兼容混合数据类型:同时处理数值型和类别型特征

数学上,分类任务中常用基尼指数作为分裂标准:

$$Gini(D) = 1 – \sum_{k=1}^K p_k^2$$

其中 $p_k$ 是第 $k$ 类样本在数据集 $D$ 中的比例。

痛点分析

CART 决策树容易过拟合的典型表现包括:

  1. 训练集准确率接近 100%,但测试集表现骤降
  2. 树深度过大,产生大量仅覆盖个别样本的叶节点
  3. 对训练数据中的噪声极度敏感

根本原因在于:

  • 算法会不断分裂直到所有叶节点纯度为 100%
  • 没有内置的复杂度惩罚机制
  • 贪婪分裂策略可能捕捉到数据中的偶然模式

解决方案

预剪枝实现

通过限制树的生长进行提前干预,关键参数包括:

from sklearn.tree import DecisionTreeClassifier

# 预剪枝参数设置示例
model = DecisionTreeClassifier(
    max_depth=3,               # 最大树深度
    min_samples_split=10,      # 节点分裂最小样本数
    min_samples_leaf=5,        # 叶节点最小样本数
    max_features='sqrt',       # 考虑的特征数
    random_state=42
)

参数选择建议:

  • max_depth:通常从 3 开始尝试,通过交叉验证调整
  • min_samples_split:建议设置在总样本量的 1%-5%
  • min_samples_leaf:对于类别不平衡数据适当增大

后剪枝实现

代价复杂度剪枝(CCP)通过优化目标函数实现:

$$R_\alpha(T) = R(T) + \alpha|\widetilde{T}|$$

其中 $\alpha$ 是复杂度参数,$|\widetilde{T}|$ 为叶节点数。

import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier

# 生成 CCP 路径
model = DecisionTreeClassifier(random_state=42)
path = model.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas = path.ccp_alphas

# 绘制准确率随 alpha 变化曲线
acc_scores = []
for alpha in ccp_alphas:
    pruned_model = DecisionTreeClassifier(ccp_alpha=alpha, random_state=42)
    scores = cross_val_score(pruned_model, X_train, y_train, cv=5)
    acc_scores.append(scores.mean())

plt.plot(ccp_alphas, acc_scores)
plt.xlabel('alpha')
plt.ylabel('Accuracy')
plt.show()

# 选择最优 alpha
optimal_alpha = ccp_alphas[np.argmax(acc_scores)]
final_model = DecisionTreeClassifier(ccp_alpha=optimal_alpha)
final_model.fit(X_train, y_train)

性能优化

特征重要性评估

importances = final_model.feature_importances_
indices = np.argsort(importances)[::-1]

# 可视化特征重要性
plt.figure(figsize=(10,6))
plt.title("Feature Importance")
plt.bar(range(X.shape[1]), importances[indices])
plt.xticks(range(X.shape[1]), feature_names[indices], rotation=90)
plt.show()

与随机森林对比

指标 CART 决策树 随机森林
抗过拟合能力 中等 强
训练速度 快 较慢
可解释性 高 中等
默认准确率 中等 高

避坑指南

类别不平衡处理

  1. 调整类别权重:
    model = DecisionTreeClassifier(class_weight='balanced')
  2. 上采样少数类或下采样多数类
  3. 使用平衡准确率(balanced_accuracy)作为评估指标

超参数调优建议

  1. 优先调整 max_depth 和min_samples_leaf
  2. 使用网格搜索结合早停机制:
    from sklearn.model_selection import GridSearchCV
    
    param_grid = {'max_depth': [3, 5, 7, None],
        'min_samples_leaf': [1, 3, 5]
    }
    
    grid_search = GridSearchCV(estimator=DecisionTreeClassifier(),
        param_grid=param_grid,
        cv=5,
        n_jobs=-1
    )

总结与延伸

学习路径建议

  1. 进阶阅读《Elements of Statistical Learning》第 9 章
  2. 实践不同剪枝策略对模型泛化能力的影响
  3. 探索决策树在回归任务中的应用

实践思考题

给定一个包含 100 个特征的数据集,其中:
– 5 个强相关特征
– 20 个弱相关特征
– 75 个噪声特征

如何设计实验验证不同剪枝方法对特征选择的稳定性影响?

正文完
 0
评论(没有评论)