共计 2604 个字符,预计需要花费 7 分钟才能阅读完成。
1. 核心概念解析
1.1 Gini 系数与信息增益
决策树的核心是分裂准则,CART(Classification and Regression Trees) 使用 Gini 系数作为分类问题的分裂标准。Gini 系数的计算公式为:

Gini(D) = 1 - \sum_{k=1}^{K} (p_k)^2
其中 D 是数据集,K 是类别数,p_k 是第 k 类样本的比例。
对于特征 A 将数据集 D 划分为 D1 和 D2 后,Gini 系数的变化量(即 Gini 增益)计算为:
\Delta Gini(A) = Gini(D) - \frac{|D1|}{|D|}Gini(D1) - \frac{|D2|}{|D|}Gini(D2)
与 ID3/C4.5 算法使用信息增益不同,CART 总是选择使 Gini 增益最大的特征进行分裂。
1.2 与 ID3/C4.5 的差异
- 分裂标准 :ID3 用信息增益,C4.5 用增益率,CART 用 Gini 系数
- 树结构 :ID3/C4.5 生成多叉树,CART 生成二叉树
- 任务类型 :ID3/C4.5 仅处理分类,CART 可处理分类和回归
- 缺失值 :CART 有完善的缺失值处理机制
2. Python 实现详解
2.1 基础实现框架
class TreeNode:
def __init__(self, feature_idx=None, threshold=None,
left=None, right=None, value=None):
self.feature_idx = feature_idx # 分裂特征索引
self.threshold = threshold # 分裂阈值
self.left = left # 左子树
self.right = right # 右子树
self.value = value # 叶节点预测值
2.2 核心算法实现
def gini(y):
"""计算 Gini 系数"""
_, counts = np.unique(y, return_counts=True)
probabilities = counts / len(y)
return 1 - np.sum(probabilities ** 2)
def find_best_split(X, y):
"""寻找最佳分裂特征和阈值"""
best_gini = float('inf')
best_feature, best_thresh = None, None
for feature_idx in range(X.shape[1]):
thresholds = np.unique(X[:, feature_idx])
for threshold in thresholds:
left_idx = X[:, feature_idx] <= threshold
right_idx = ~left_idx
if len(y[left_idx]) == 0 or len(y[right_idx]) == 0:
continue
g = (len(y[left_idx]) * gini(y[left_idx]) +
len(y[right_idx]) * gini(y[right_idx])) / len(y)
if g < best_gini:
best_gini = g
best_feature = feature_idx
best_thresh = threshold
return best_feature, best_thresh
3. sklearn 实战优化
3.1 基础使用示例
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(
criterion='gini', # 分裂标准
max_depth=3, # 最大深度
min_samples_split=2, # 最小分裂样本数
min_samples_leaf=1 # 叶节点最小样本数
)
clf.fit(X_train, y_train)
3.2 关键参数调优
- max_depth:控制树的最大深度,防止过拟合
- min_samples_split:节点最小样本数,建议值 2 -5
- min_samples_leaf:叶节点最小样本数,建议值 1 -3
- max_features:考虑的特征数,None 表示全部
推荐使用网格搜索进行参数优化:
from sklearn.model_selection import GridSearchCV
param_grid = {'max_depth': [3, 5, 7],
'min_samples_split': [2, 5, 10]
}
grid_search = GridSearchCV(DecisionTreeClassifier(), param_grid, cv=5)
grid_search.fit(X_train, y_train)
4. 常见问题与解决方案
- 问题:忽略特征缩放
- 现象:数值型特征量纲差异大时影响分裂
-
解决:对连续特征做标准化 (StandardScaler)
-
问题:未处理类别不平衡
- 现象:少数类识别率低
-
解决:设置 class_weight=’balanced’ 或过采样
-
问题:过拟合
- 现象:训练集准确率高但测试集差
-
解决:增加 min_samples_leaf 或使用剪枝
-
问题:缺失值处理不当
- 现象:含缺失值时报错
-
解决:sklearn 自动处理,自定义实现需补充
-
问题:忽略特征重要性
- 现象:无法解释模型
- 解决:使用 feature_importances_属性分析
5. 进阶应用方向
5.1 回归问题
CART 同样适用于回归任务,只需将分裂标准改为 MSE:
from sklearn.tree import DecisionTreeRegressor
reg = DecisionTreeRegressor(criterion='mse', max_depth=3)
reg.fit(X_train, y_train)
5.2 随机森林基础
随机森林通过构建多棵 CART 树并聚合结果来提高性能:
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(
n_estimators=100, # 树的数量
max_features='sqrt', # 每棵树考虑的特征数
criterion='gini' # 使用与 CART 相同的分裂标准
)
rf.fit(X_train, y_train)
结语
CART 决策树以其简单直观的特性成为机器学习入门必学算法。通过本文的系统讲解,希望读者能掌握其核心原理与实现细节,并在实际项目中灵活运用。建议进一步学习剪枝算法和集成方法,这些技术能显著提升单一决策树的性能。
正文完
