共计 1530 个字符,预计需要花费 4 分钟才能阅读完成。
核心概念
决策树在分类任务中像一位经验丰富的医生,通过一系列精心设计的判断条件(特征问题),最终给出明确的诊断结果(分类标签)。它的核心价值在于模型可解释性强,且对数据分布假设较少,适合处理混合类型特征。

- 基尼系数 (Gini Index) vs 信息增益 (Information Gain):这是初学者常见的困惑点。两者都是衡量节点纯度的指标,但计算方式不同。基尼系数计算更简单,且对类别分布更敏感;信息增益则基于信息论,倾向于选择更多取值的特征。
- 过拟合问题 :决策树容易生成过于复杂的树结构,表现为训练集准确率接近 100% 但测试集表现差,叶子节点样本量过少,或出现明显不合业务逻辑的分支规则。
算法实现
基尼系数计算
基尼系数衡量数据的不纯度,数学表达式为:
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 = 0.0
for class_val in classes:
p = [row[-1] for row in group].count(class_val) / size
score += p * p
gini += (1.0 - score) * (size / n_instances)
return gini
CART 二叉树构建
CART(Classification and Regression Trees) 采用二叉树结构:
- 从根节点开始,计算所有特征的基尼系数
- 选择使子节点纯度提升最大的特征进行分裂
- 递归处理子节点,直到满足停止条件
- 生成叶子节点并确定其类别
优化策略
剪枝技术对比
-
预剪枝 (Pre-pruning):在树构建过程中提前停止,通过 max_depth/min_samples_split 等参数控制
# sklearn 预剪枝示例 from sklearn.tree import DecisionTreeClassifier clf = DecisionTreeClassifier(max_depth=3, min_samples_leaf=5) -
后剪枝 (Post-pruning):先构建完整树再修剪,通常效果更好但实现复杂
def prune_tree(node, min_gain): """递归后剪枝""" if node.is_leaf: return # 先剪枝子节点 prune_tree(node.left, min_gain) prune_tree(node.right, min_gain) # 计算剪枝前后的损失差异 if gain < min_gain: node.make_leaf()
生产实践
连续特征处理
对连续特征采用二分法离散化:
1. 排序特征值
2. 取相邻值的均值作为候选切分点
3. 选择基尼系数最小的切分阈值
类别不平衡调整
- 设置 class_weight 参数
- 采用过采样 / 欠采样技术
- 在计算基尼系数时引入样本权重
# 加权基尼计算示例 weighted_p = sum(w for row, w in zip(group, weights) if row[-1] == class_val) / total_weight
延伸思考
- 特征重要性可以通过累计各特征带来的基尼不纯度减少量来计算,但如何解释某个具体特征的重要性数值?
- 当特征与标签间是线性关系时,决策树需要多次分裂才能近似线性边界,此时线性模型可能更高效。还有哪些典型场景适合 / 不适合决策树?
决策树就像数据分析的瑞士军刀,简单却功能强大。通过本文的实践,希望你能感受到算法背后的设计哲学——用最直观的方式揭示数据规律。在实际项目中,不妨先尝试基准决策树模型,再逐步优化,往往能获得意想不到的好效果。
正文完
