从原理到实践:如何用CART算法构建高性能决策树模型

1次阅读
没有评论

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

image.webp

背景介绍

决策树是机器学习中最直观的算法之一,广泛应用于金融风控、医疗诊断和推荐系统。CART(Classification and Regression Trees)算法因其以下优势成为工业界首选:

从原理到实践:如何用 CART 算法构建高性能决策树模型

  • 同时支持分类和回归任务
  • 使用二元分裂(每次只分两个分支)简化模型结构
  • 内置剪枝机制有效防止过拟合

技术对比:CART vs ID3/C4.5

  • 分裂标准
  • ID3 使用信息增益(易偏向多值特征)
  • C4.5 使用增益率(解决 ID3 缺陷)
  • CART 使用基尼系数(计算效率更高)

  • 输出类型

  • ID3/C4.5 仅支持分类
  • CART 支持分类和回归

  • 树结构

  • ID3/C4.5 生成多叉树
  • CART 生成二叉树

核心实现

1. 特征选择:基尼系数

基尼系数反映数据不纯度,计算复杂度低于信息熵:

def gini_index(groups, classes):
    n_instances = sum(len(group) for group in groups)
    gini = 0.0
    for group in groups:
        size = len(group)
        if size == 0:
            continue
        score = 1.0
        for class_val in classes:
            p = [row[-1] for row in group].count(class_val) / size
            score -= p ** 2
        gini += score * (size / n_instances)
    return gini

2. 递归建树流程

  1. 计算当前节点基尼指数
  2. 遍历所有特征及其可能分割点
  3. 选择使基尼系数下降最大的特征进行分裂
  4. 递归处理子节点直到终止条件(如深度限制)

3. 剪枝策略

  • 预剪枝 :在建树过程中通过参数控制

    from sklearn.tree import DecisionTreeClassifier
    
    # 关键参数控制
    model = DecisionTreeClassifier(
        max_depth=5,       # 树的最大深度
        min_samples_split=10,  # 节点继续分裂的最小样本数
        min_impurity_decrease=0.01  # 分裂需要的最小不纯度下降
    )

  • 后剪枝 :先构建完整树,再自底向上剪枝

Python 实现对比

scikit-learn 版本(推荐生产使用)

from sklearn.datasets import load_iris
from sklearn import tree
import matplotlib.pyplot as plt

# 加载数据
iris = load_iris()
X, y = iris.data, iris.target

# 训练模型
clf = tree.DecisionTreeClassifier(criterion='gini', max_depth=3)
clf = clf.fit(X, y)

# 可视化
plt.figure(figsize=(12,8))
tree.plot_tree(clf, feature_names=iris.feature_names, 
               class_names=iris.target_names, filled=True)
plt.show()

原生实现(理解原理)

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      # 叶节点预测值

# 完整实现代码较长,此处展示核心分裂函数
def split_dataset(X, y, feature_index, threshold):
    left_mask = X[:, feature_index] <= threshold
    right_mask = ~left_mask
    left = (X[left_mask], y[left_mask])
    right = (X[right_mask], y[right_mask])
    return left, right

性能优化实战

连续特征处理

  1. 对特征值排序
  2. 取相邻值中点作为候选分割点
  3. 选择最优分割点

并行计算

from sklearn.ensemble import BaggingClassifier

# 通过装袋法并行训练多棵树
model = BaggingClassifier(DecisionTreeClassifier(),
    n_estimators=10,
    max_samples=0.8,
    n_jobs=-1  # 使用所有 CPU 核心
)

常见问题解决方案

过拟合识别

  • 训练集准确率 >> 测试集准确率
  • 决策树深度过大(超过 15 层)

类别不平衡

  1. 调整 class_weight 参数
    model = DecisionTreeClassifier(class_weight='balanced')
  2. 对少数类样本进行过采样

业务落地建议

  1. 金融风控
  2. 用 SHAP 值解释单笔贷款拒批原因
  3. 设置动态评分阈值

  4. 医疗诊断

  5. 结合临床指标构建决策路径
  6. 输出可解释的诊断规则

思考题

在特征维度极高(如 >1000 维)的情况下,可以考虑:

  1. 先进行特征选择(如基于方差或互信息)
  2. 使用随机森林的特征重要性进行筛选
  3. 采用近似算法(如 Histogram-based Gradient Boosting)

决策树的魅力在于其可解释性与高效性。当业务需要模型 ” 讲道理 ” 时,CART 算法永远是可靠的选择。

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