决策树算法详解
决策树算法详解
什么是决策树
决策树(Decision Tree)是一种直观且易于理解的分类和回归算法。它通过一系列的"是/否"判断,将数据逐步划分到不同的类别中。决策树的结构类似于流程图,每个内部节点表示一个特征判断,每个叶子节点表示一个预测结果。
决策树的构建过程
- 选择最佳特征:选择最能区分数据的特征进行分裂
- 创建节点:根据选定特征创建判断节点
- 递归分裂:对每个子集重复上述过程
- 终止条件:达到最大深度、节点样本数过少或纯度足够
分裂准则
信息增益(Information Gain)
基于信息熵的概念,选择使信息增益最大的特征进行分裂。
信息熵计算:
$$H(D) = -\sum_{k=1}^{K}p_k\log_2(p_k)$$
信息增益:
$$IG(D, A) = H(D) - \sum_{v \in Values(A)} \frac{|D_v|}{|D|}H(D_v)$$
基尼指数(Gini Index)
基尼指数衡量数据的不纯度:
$$Gini(D) = 1 - \sum_{k=1}^{K}p_k^2$$
基尼指数越小,数据越纯。
基尼指数 vs 信息增益
| 指标 | CART使用 | ID3/C4.5使用 |
|---|---|---|
| 计算速度 | 较快 | 较慢 |
| 倾向性 | 倾向较多取值的特征 | 无明显偏向 |
| 实现复杂度 | 简单 | 较复杂 |
代码示例:决策树分类与可视化
import numpy as np
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.tree import DecisionTreeClassifier, export_text, plot_tree
from sklearn.metrics import classification_report, accuracy_score
import warnings
warnings.filterwarnings('ignore')
# 加载葡萄酒数据集
wine = load_wine()
X, y = wine.data, wine.target
feature_names = wine.feature_names
target_names = wine.target_names
print(f"特征数: {X.shape[1]}, 样本数: {X.shape[0]}")
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 不同参数设置的决策树比较
configs = [
('默认', {}),
('限制深度', {'max_depth': 3}),
('最小叶子样本', {'min_samples_leaf': 5}),
('基尼指数', {'criterion': 'gini'}),
('信息增益', {'criterion': 'entropy'}),
]
print("\n=== 不同配置的决策树性能 ===")
print("-" * 50)
best_score = 0
best_config = None
for name, params in configs:
dt = DecisionTreeClassifier(random_state=42, **params)
dt.fit(X_train, y_train)
train_acc = dt.score(X_train, y_train)
test_acc = dt.score(X_test, y_test)
cv_scores = cross_val_score(dt, X, y, cv=5)
print(f"{name:12} | 训练: {train_acc:.4f} | 测试: {test_acc:.4f} | "
f"CV: {cv_scores.mean():.4f}")
if cv_scores.mean() > best_score:
best_score = cv_scores.mean()
best_config = (name, params)
# 使用最佳配置训练模型
print(f"\n最佳配置: {best_config[0]}")
dt_best = DecisionTreeClassifier(random_state=42, **best_config[1])
dt_best.fit(X_train, y_train)
# 详细评估
print("\n=== 分类报告 ===")
y_pred = dt_best.predict(X_test)
print(classification_report(y_test, y_pred, target_names=target_names))
# 文本形式展示决策树
print("=== 决策树结构(文本) ===")
tree_rules = export_text(dt_best, feature_names=feature_names, max_depth=3)
print(tree_rules)
# 特征重要性
print("=== 特征重要性 ===")
importance = dt_best.feature_importances_
sorted_idx = np.argsort(importance)[::-1]
for idx in sorted_idx[:5]:
print(f" {feature_names[idx]}: {importance[idx]:.4f}")
# 深度对模型的影响
print("\n=== 树深度与性能关系 ===")
for depth in range(1, 10):
dt_temp = DecisionTreeClassifier(max_depth=depth, random_state=42)
dt_temp.fit(X_train, y_train)
train_acc = dt_temp.score(X_train, y_train)
test_acc = dt_temp.score(X_test, y_test)
print(f"深度{depth:2d} | 训练: {train_acc:.4f} | 测试: {test_acc:.4f}")
剪枝策略
为防止过拟合,需要对决策树进行剪枝:
- 预剪枝:在构建过程中限制最大深度、最小样本数等
- 后剪枝:先生成完整树,再剪去不必要的分支
决策树的优缺点
优点:
- 模型可解释性强,易于可视化
- 不需要数据标准化
- 能处理数值和类别特征
- 训练和预测速度快
缺点:
- 容易过拟合
- 对数据微小变化敏感
- 倾向于选择取值较多的特征
- 不能很好地处理线性关系
总结
决策树是理解集成学习方法(随机森林、梯度提升树)的基础。掌握决策树的原理和实现,将为后续学习更强大的模型奠定基础。