决策树实战:从零开始用CART算法构建高效分类模型

1次阅读
没有评论

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

image.webp

一、为什么选择 CART 算法?

刚入门机器学习时,我发现决策树虽然直观,但面对这些问题总是头疼:

决策树实战:从零开始用 CART 算法构建高效分类模型

  • 特征太多不知道该选哪个作为分裂节点
  • 训练集表现很好但测试集准确率暴跌(典型的过拟合)
  • 遇到连续型特征就手足无措

后来发现 CART 算法完美解决这些痛点——它用二叉树结构统一处理分类和回归任务,通过基尼系数自动选择最佳分裂特征,还能通过剪枝控制过拟合。

二、CART 与其他决策树算法的区别

  1. 与 ID3 对比
  2. ID3 只能用信息增益,且只能处理离散特征
  3. CART 改用基尼系数,计算效率更高(不用算 log)

  4. 与 C4.5 对比

  5. C4.5 虽然支持连续值,但生成的是多叉树
  6. CART 强制二叉树结构,模型更简洁

关键优势:

# CART 处理连续特征的示例
age = [12, 15, 18, 22, 30]
# 会自动尝试所有可能的分割点:# age<=12.5、age<=16.5...

三、手把手实现 CART 核心逻辑

3.1 基尼系数计算

公式看起来复杂其实很简单:

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

实际计算时:

  1. 统计当前节点各类别的占比
  2. 用 1 减去各占比平方和

Python 实现:

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

3.2 递归分裂过程

关键步骤:

  1. 遍历所有特征的所有可能分割点
  2. 选择使基尼系数下降最多的分裂方案
  3. 递归处理左右子树直到满足停止条件

终止条件建议设置:

  • 节点样本数 <min_samples_leaf
  • 深度达到 max_depth
  • 基尼下降小于 min_impurity_decrease

四、sklearn 实战调优技巧

4.1 重要参数解析

from sklearn.tree import DecisionTreeClassifier

# 关键参数设置示例
tree = DecisionTreeClassifier(
    criterion='gini',  # 一定要选这个!max_depth=5,       # 控制树深防过拟合
    min_samples_leaf=10, # 每个叶节点最少样本
    class_weight='balanced'  # 处理类别不平衡
)

4.2 交叉验证选择最优深度

from sklearn.model_selection import GridSearchCV

params = {'max_depth': range(3, 8)}
grid = GridSearchCV(tree, params, cv=5)
grid.fit(X_train, y_train)

print(f'最佳深度:{grid.best_params_}')

五、新手常见踩坑点

5.1 类别不平衡陷阱

错误做法:

  • 直接使用原始数据训练

正确方案:

# 方法 1:设置 class_weight
tree = DecisionTreeClassifier(class_weight='balanced')

# 方法 2:过采样少数类
from imblearn.over_sampling import SMOTE
X_res, y_res = SMOTE().fit_resample(X, y)

5.2 特征重要性误读

注意:

  • 重要性高的特征不一定因果关系强
  • 重要性受特征间相关性影响
  • 用 permutation_importance 更可靠

六、进阶方向建议

  1. 尝试回归任务
  2. 改用 DecisionTreeRegressor
  3. 分裂标准变为 MSE/MAE

  4. 升级到随机森林

  5. CART 是随机森林的基学习器
  6. 通过 ensemble 降低方差
# 随机森林示例
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(
    n_estimators=100,
    max_features='sqrt'  # 特征采样
)

写在最后

通过这个实战项目,我深刻体会到:

  • CART 的二叉树结构让模型解释性极佳
  • 合理剪枝比追求训练集高分更重要
  • sklearn 的参数看似简单实则影响巨大

建议大家在泰坦尼克数据集上动手实现一遍,遇到问题欢迎在评论区交流~

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