从零开始构建CART决策树分类预测模型:原理详解与Python实战

1次阅读
没有评论

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

image.webp

背景与核心概念

在分类问题中,线性模型和树模型各有优劣。线性模型(如逻辑回归)适合处理特征间存在线性关系的数据,但当数据存在复杂非线性关系时,决策树的优势就显现出来了。决策树通过递归分割数据空间,能够捕捉复杂的特征交互作用,且模型结果易于解释。

从零开始构建 CART 决策树分类预测模型:原理详解与 Python 实战

然而,初学者在使用决策树时常会遇到两个典型问题:

  • 模型过拟合:决策树会不断生长直到完美拟合训练数据,导致在测试集上表现不佳
  • 特征重要性误判:由于算法贪婪特性,可能高估某些偶然性特征的贡献度

算法原理与对比

关键数学概念

CART(Classification And Regression Trees) 使用基尼系数作为分割标准,其定义为:

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

其中 $p_k$ 是第 k 类样本在节点中的比例。基尼系数越小,表示节点纯度越高。

相比 ID3 和 C4.5 算法:

  1. ID3 使用信息增益,倾向于选择取值多的特征
  2. C4.5 使用信息增益比,解决了 ID3 的偏好问题
  3. CART 使用基尼系数,计算效率更高且可处理连续特征

参数影响可视化

通过调整 max_depth 参数,可以直观看到模型复杂度的变化:

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

# 生成不同深度的树
for depth in [2, 4, 6]:
    clf = DecisionTreeClassifier(max_depth=depth)
    clf.fit(X_train, y_train)
    plt.figure(figsize=(12, 8))
    plot_tree(clf, filled=True)
    plt.title(f'Max Depth = {depth}')
    plt.show()

核心代码实现

基尼系数计算

使用 numpy 实现向量化计算,提升性能:

import numpy as np

def gini_impurity(y: np.ndarray) -> float:
    """计算基尼不纯度"""
    if len(y) == 0:
        return 0
    p = np.bincount(y) / len(y)
    return 1 - np.sum(p**2)

树节点结构设计

定义二叉树节点类,包含关键分裂信息:

class TreeNode:
    def __init__(self, feature_idx=None, threshold=None, 
                 left=None, right=None, value=None):
        self.feature_idx = feature_idx  # 分裂特征索引
        self.threshold = threshold      # 分裂阈值
        self.left = left                # 左子树
        self.right = right              # 右子树
        self.value = value              # 叶节点预测值 

生产环境优化

sklearn 参数调优

关键参数说明:

  • max_depth: 控制树的最大深度
  • min_samples_split: 节点最小样本数
  • min_impurity_decrease: 分裂最小纯度提升

使用网格搜索寻找最优参数组合:

from sklearn.model_selection import GridSearchCV

param_grid = {'max_depth': [3, 5, 7],
    'min_samples_split': [2, 5, 10],
    'min_impurity_decrease': [0, 0.01, 0.1]
}

grid_search = GridSearchCV(DecisionTreeClassifier(), 
    param_grid, 
    cv=5,
    scoring='accuracy'
)
grid_search.fit(X_train, y_train)
print("Best parameters:", grid_search.best_params_)

常见问题解决方案

类别不平衡处理

设置 class_weight 参数自动调整类别权重:

# 自动根据类别频率调整权重
clf = DecisionTreeClassifier(class_weight='balanced')

# 手动指定类别权重
clf = DecisionTreeClassifier(class_weight={0:1, 1:5})

特征重要性分析

通过 feature_importances_属性识别无效特征:

import pandas as pd

clf.fit(X_train, y_train)
feat_importances = pd.Series(
    clf.feature_importances_, 
    index=feature_names
).sort_values(ascending=False)

# 可视化特征重要性
feat_importances.plot(kind='barh')
plt.title('Feature Importances')
plt.show()

延伸思考与改进方向

  1. 如何处理连续特征缺失值?可以考虑用特征分布的中位数填充
  2. 如何提升模型对噪声数据的鲁棒性?尝试实现代价敏感学习
  3. 当特征维度很高时,如何加速训练过程?研究特征预筛选策略

通过本文的实践,你应该已经掌握了 CART 决策树的核心原理和实现方法。建议读者在理解这些基础后,可以进一步探索随机森林、GBDT 等集成树模型,它们能有效改善单棵决策树的局限性。

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