CART算法实战:从原理到代码实现决策树构建

1次阅读
没有评论

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

image.webp

1. CART 算法核心概念

决策树是机器学习中最直观的算法之一,而 CART(Classification and Regression Trees)则是其中应用最广泛的构建方法。与 ID3 和 C4.5 不同,CART 既能处理分类问题也能解决回归任务,其核心是通过递归二分(binary splitting)构建二叉树。

CART 算法实战:从原理到代码实现决策树构建

  • 分裂准则 :分类任务使用基尼系数(Gini Index),回归任务使用最小平方误差
  • 终止条件 :节点纯度达到阈值 / 样本数小于阈值 / 达到最大深度
  • 输出结果 :分类树返回类别标签,回归树返回叶节点样本均值

数学上,基尼系数计算公式为:

Gini(D) = 1 - Σ(p_i)^2  # p_i 是第 i 类样本占比 

2. 算法横向对比

特性 CART ID3 C4.5
树结构 二叉树 多叉树 多叉树
特征选择 基尼系数 /MSE 信息增益 信息增益率
任务类型 分类 + 回归 仅分类 仅分类
缺失值处理 需预处理 不支持 自动处理

CART 的优势在于:
– 计算效率更高(二叉树结构)
– 输出结果可解释性强
– 对异常值鲁棒性更好

3. Python 完整实现

3.1 基础结构

class Node:
    def __init__(self, feature=None, threshold=None, left=None, right=None, value=None):
        self.feature = feature   # 分裂特征
        self.threshold = threshold  # 分裂阈值
        self.left = left        # 左子树
        self.right = right      # 右子树
        self.value = value      # 叶节点值 

3.2 基尼系数计算

def gini(y):
    _, counts = np.unique(y, return_counts=True)
    probabilities = counts / len(y)
    return 1 - np.sum(probabilities**2)

3.3 最佳分裂点选择

def find_best_split(X, y):
    best_gini = float('inf')
    best_feature, best_thresh = None, None

    for feature in range(X.shape[1]):
        thresholds = np.unique(X[:, feature])
        for thresh in thresholds:
            left_idx = X[:, feature] <= thresh
            g = gini(y[left_idx]) * left_idx.sum() / len(y) + \
                gini(y[~left_idx]) * (~left_idx).sum() / len(y)
            if g < best_gini:
                best_gini = g
                best_feature = feature
                best_thresh = thresh
    return best_feature, best_thresh

3.4 递归建树

def build_tree(X, y, depth=0, max_depth=5):
    if len(np.unique(y)) == 1 or depth >= max_depth:
        return Node(value=np.mean(y))  # 回归任务

    feature, thresh = find_best_split(X, y)
    left_idx = X[:, feature] <= thresh

    left = build_tree(X[left_idx], y[left_idx], depth+1, max_depth)
    right = build_tree(X[~left_idx], y[~left_idx], depth+1, max_depth)
    return Node(feature, thresh, left, right)

4. 性能优化实践

4.1 时间复杂度分析

  • 训练阶段:O(n_features * n_samples * log(n_samples))
  • 预测阶段:O(tree_depth)

4.2 生产环境建议

  1. 特征预处理 :
  2. 数值特征标准化(回归任务必需)
  3. 类别特征进行 one-hot 编码
  4. 超参数调优 :
  5. 通过交叉验证选择 max_depth/min_samples_split
  6. 使用网格搜索或贝叶斯优化
  7. 内存优化 :
  8. 对于大型数据集,设置 min_samples_leaf 参数
  9. 考虑使用增量训练(warm_start)

5. 常见问题解决方案

过拟合现象

  • 症状 :训练集准确率高,测试集表现差
  • 对策 :
  • 增加 min_samples_leaf 参数值
  • 实施后剪枝(CCP 算法)
  • 使用随机森林替代单棵树

类别不平衡

  • 采用 class_weight 参数调整样本权重
  • 对少数类样本进行过采样

高维数据处理

  • 先进行特征选择(如方差阈值过滤)
  • 使用 PCA 降维后再建树

思考题延伸

针对高维稀疏数据(如文本特征),可以考虑:
1. 使用特征哈希(Feature Hashing)降低维度
2. 采用随机投影保留关键特征
3. 结合 L1 正则化进行特征选择
4. 改用梯度提升树(GBDT)等更适合稀疏数据的算法

通过本文的实践,我们完成了从理论到代码的完整闭环。建议读者尝试在 Kaggle 的 Titanic 数据集上实现完整流程,观察不同参数对模型效果的影响。决策树虽然简单,但仍是许多复杂模型的基础组件,深入理解其原理对后续学习随机森林、GBDT 等算法大有裨益。

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