共计 1336 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点
决策树在真实业务场景中备受青睐,主要因为它具备极强的可解释性。模型训练完成后,我们可以直接通过树的结构理解每个决策背后的逻辑,这在金融风控、医疗诊断等领域尤为重要。业务方往往需要知道为什么拒绝某笔贷款,或者为什么判断患者有某种疾病,决策树能够提供清晰的规则路径。

然而,传统的 ID3 算法在实际应用中存在明显缺陷:
- 无法直接处理连续特征,需要手动离散化
- 采用信息增益作为划分标准,容易偏向取值较多的特征
- 缺乏剪枝机制,容易过拟合训练数据
算法对比
| 算法 | 特征选择标准 | 树结构 | 计算复杂度 | 连续特征处理 |
|---|---|---|---|---|
| ID3 | 信息增益 | 多叉树 | O(n_features * n_samples) | 不支持 |
| C4.5 | 信息增益比 | 多叉树 | O(n_features * n_samples log n_samples) | 支持 |
| CART | 基尼系数 | 二叉树 | O(n_features * n_samples) | 支持 |
核心实现
基尼系数计算
基尼系数衡量数据集的不纯度,计算公式为:
$$Gini(D) = 1 – \sum_{k=1}^{K} (p_k)^2$$
其中 $p_k$ 是第 k 类样本在数据集 D 中的比例。几何意义上,基尼系数可以理解为从数据集中随机抽取两个样本,它们类别不一致的概率。
递归终止条件
在构建决策树时,递归分裂需要设置合理的终止条件:
- 当前节点样本数小于预设阈值(如 min_samples_split=10)
- 所有样本属于同一类别(基尼系数 =0)
- 特征集合为空
- 节点深度达到最大值(max_depth)
代码示例
基尼系数计算函数
import numpy as np
def gini_impurity(y):
_, counts = np.unique(y, return_counts=True)
probabilities = counts / len(y)
return 1 - np.sum(probabilities ** 2)
树结构可视化
from sklearn.tree import export_text
def print_tree(tree, feature_names):
tree_rules = export_text(tree, feature_names=feature_names)
print(tree_rules)
生产建议
连续特征离散化
处理连续特征时,常见的分桶策略包括:
- 等宽分桶:按值范围均匀划分
- 等频分桶:使每个桶包含相同数量的样本
- 基于决策树的最优分桶:用决策树学习离散化边界
预剪枝调优
关键超参数优化技巧:
- max_depth:从 3 开始逐步增加,观察验证集表现
- min_samples_split:防止过小的节点分裂,通常设置 10-100
- min_impurity_decrease:分裂带来的不纯度下降需超过该阈值
性能测试
在 sklearn 的乳腺癌数据集上测试不同 max_depth 的影响:
| max_depth | 训练准确率 | 测试准确率 | 训练时间 (ms) |
|---|---|---|---|
| 3 | 0.95 | 0.92 | 12 |
| 5 | 0.98 | 0.94 | 15 |
| 10 | 1.00 | 0.91 | 22 |
从结果可见,深度过大虽然训练准确率高,但测试准确率下降,出现过拟合现象。
总结
CART 算法通过基尼系数和二叉树结构,在保持可解释性的同时,有效解决了连续特征处理和过拟合问题。实际应用中,合理的参数设置和特征工程能显著提升模型性能。建议在业务初期使用较浅的树结构,随数据量增加再逐步调整复杂度。
正文完
