共计 2419 个字符,预计需要花费 7 分钟才能阅读完成。
背景介绍
决策树是机器学习中常用的算法之一,因其直观的解释性和广泛的应用场景而备受青睐。CART(Classification and Regression Trees)算法是一种经典的决策树算法,既可以用于分类问题,也可以用于回归问题。与 ID3 和 C4.5 算法相比,CART 采用二叉树结构,更适合处理连续特征和复杂数据集。

核心概念
基尼系数(Gini Index)
基尼系数是 CART 算法中用于衡量节点纯度的指标,其计算公式为:
Gini = 1 - Σ (p_i)^2
其中,p_i是节点中第 i 类样本所占的比例。基尼系数越小,说明节点的纯度越高。
信息增益(Information Gain)
虽然 CART 主要使用基尼系数,但在某些实现中也会用到信息增益。信息增益基于信息熵,用于衡量特征分裂前后的信息不确定性减少程度。
计算步骤
1. 特征选择
CART 算法通过遍历所有特征及其可能的切分点,选择基尼系数最小的特征和切分点作为当前节点的分裂标准。
2. 节点分裂
一旦确定了最佳特征和切分点,算法将数据集分成两部分,分别进入左右子节点。这一过程递归进行,直到满足停止条件(如节点样本数小于阈值或基尼系数低于阈值)。
3. 剪枝(Pruning)
为了防止过拟合,CART 通常会进行剪枝操作。剪枝分为预剪枝和后剪枝,前者在树构建过程中提前停止分裂,后者在树构建完成后通过交叉验证选择最优子树。
代码示例
以下是一个简化的 Python 实现,展示如何从零构建 CART 决策树:
import numpy as np
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 gini(y):
classes = np.unique(y)
gini = 1
for c in classes:
p = np.sum(y == c) / len(y)
gini -= p ** 2
return gini
def best_split(X, y):
best_gini = float('inf')
best_feature, best_threshold = None, None
for feature in range(X.shape[1]):
thresholds = np.unique(X[:, feature])
for threshold in thresholds:
left_indices = X[:, feature] <= threshold
right_indices = X[:, feature] > threshold
if len(y[left_indices]) == 0 or len(y[right_indices]) == 0:
continue
current_gini = (len(y[left_indices]) * gini(y[left_indices]) +
len(y[right_indices]) * gini(y[right_indices])) / len(y)
if current_gini < best_gini:
best_gini = current_gini
best_feature = feature
best_threshold = threshold
return best_feature, best_threshold
def build_tree(X, y, max_depth=5, min_samples_split=2):
if len(y) < min_samples_split or max_depth == 0:
return Node(value=np.argmax(np.bincount(y)))
feature, threshold = best_split(X, y)
if feature is None:
return Node(value=np.argmax(np.bincount(y)))
left_indices = X[:, feature] <= threshold
right_indices = X[:, feature] > threshold
left = build_tree(X[left_indices], y[left_indices], max_depth-1, min_samples_split)
right = build_tree(X[right_indices], y[right_indices], max_depth-1, min_samples_split)
return Node(feature, threshold, left, right)
性能考量
- 时间复杂度 :构建决策树的时间复杂度为
O(n_features * n_samples * log(n_samples)),其中n_samples是样本数,n_features是特征数。 - 空间复杂度:决策树的空间复杂度取决于树的深度,通常为
O(2^depth)。
优化策略
- 特征选择:优先选择信息量大的特征,减少计算量。
- 并行化:在大规模数据集上,可以并行化特征选择和节点分裂过程。
- 剪枝:通过剪枝减少树的复杂度,提升泛化能力。
避坑指南
- 过拟合:决策树容易过拟合,尤其是在数据集较小或特征较多时。可以通过剪枝、设置最大深度或最小样本数来缓解。
- 类别不平衡:如果数据集中某些类别样本过少,可能导致模型偏向多数类。可以通过加权基尼系数或采样技术解决。
- 连续特征处理:CART 天然支持连续特征,但需要注意切分点的选择,避免计算量过大。
总结与思考
CART 决策树是一种强大且灵活的算法,适用于各种分类和回归任务。通过理解其核心计算步骤和实现细节,开发者可以更好地调优模型,解决实际问题。建议读者动手实现一个简单的 CART 决策树,并在自己的项目中尝试应用,逐步掌握其精髓。
正文完
