决策树实战:如何用100组数据构建高精度分类模型

1次阅读
没有评论

共计 2546 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

小样本数据的决策树挑战

当数据集仅有 100 组样本时,决策树训练会面临两个典型问题:

决策树实战:如何用 100 组数据构建高精度分类模型

  1. 过拟合风险 :树深度过大时,模型会记住训练数据的噪声而非规律。例如当max_depth=10 时,可能为每个样本创建单独分支
  2. 特征重要性偏差:少量特征可能因偶然相关性被误判为重要。比如某个特征在 20% 样本中恰好与标签同步变化

数学上,过拟合可通过泛化误差分解解释:
$$\text{Error} = \text{Bias}^2 + \text{Variance} + \text{Irreducible Error}$$
小样本下 Variance 项会显著增加

算法选型:为什么选择 CART

三种主流算法的对比:

  • ID3:仅支持离散特征,用信息增益选择划分属性,易偏向取值多的特征
  • C4.5:改进信息增益比,但仍需离散化处理连续特征
  • CART:本文选择,优势包括:
  • 直接支持连续特征(二分裂方式)
  • 基尼系数计算效率高于信息熵
  • 天然适合二分类任务

实战代码演示

数据预处理

from sklearn.preprocessing import MinMaxScaler
import pandas as pd

# 假设原始数据已加载为 df
features = df.iloc[:, :-1]  # 取所有特征
labels = df.iloc[:, -1]     # 最后一列为标签

# MinMax 缩放:将特征压缩到 [0,1] 区间
scaler = MinMaxScaler()  
# 重要:只在训练集上 fit,避免数据泄露
scaled_features = scaler.fit_transform(features)  

模型训练与调参

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV

# 参数网格示例
param_grid = {'max_depth': [3, 5, 7],  # 控制树复杂度
    'min_samples_split': [2, 5, 10]  # 节点继续分裂的最小样本数
}

# 使用 5 折交叉验证
grid_search = GridSearchCV(DecisionTreeClassifier(criterion='gini'), 
    param_grid, 
    cv=5,
    scoring='accuracy'
)
grid_search.fit(scaled_features, labels)

# 输出最佳参数
print(f"最佳参数: {grid_search.best_params_}")

决策树可视化

from sklearn.tree import export_graphviz
import graphviz

best_model = grid_search.best_estimator_

dot_data = export_graphviz(
    best_model,
    out_file=None, 
    feature_names=df.columns[:-1],
    class_names=['Class0', 'Class1'],  
    filled=True,
    rounded=True
)
graph = graphviz.Source(dot_data)
graph.render("decision_tree")  # 生成 PDF 文件

关键避坑策略

特征不足时的增强方法

当特征数少于 10 时,可采用 Bootstrap 采样:

  1. 从原始数据有放回地抽取 100 个样本
  2. 随机选择部分特征子集(如 50%)
  3. 重复生成多棵树构成随机森林

交叉验证实现

from sklearn.model_selection import cross_val_score

scores = cross_val_score(
    best_model, 
    scaled_features, 
    labels, 
    cv=5,  # 5 折
    scoring='precision'  # 可根据需求改为 recall/f1
)
print(f"交叉验证精度: {scores.mean():.2f}±{scores.std():.2f}")

特征筛选

importances = best_model.feature_importances_

# 筛选重要性 >5% 的特征
selected_idx = np.where(importances > 0.05)[0]  
print(f"有效特征: {df.columns[selected_idx]}")

模型评估与优化

性能指标分析

from sklearn.metrics import classification_report

preds = best_model.predict(scaled_features)
print(classification_report(labels, preds))

报告示例:

              precision    recall  f1-score   support

           0       0.93      0.89      0.91        54
           1       0.88      0.93      0.90        46

    accuracy                           0.91       100
   macro avg       0.91      0.91      0.91       100
weighted avg       0.91      0.91      0.91       100

召回率与精确度平衡

当需要优化特定类别时:

  1. 调整分类阈值(默认 0.5)

    probs = best_model.predict_proba(scaled_features)[:, 1]
    # 提高阈值增加精确度
    high_precision_preds = (probs > 0.7).astype(int)  

  2. 使用 class_weight 参数

    model = DecisionTreeClassifier(class_weight={0:1, 1:2})  # 类别 1 权重加倍

延伸思考

尝试回答以下问题来深化理解:

  1. 当把 max_depth 从 3 增加到 10 时,测试集准确率反而下降 2%,可能是什么原因?
  2. 如果用相同数据训练 GBDT 模型,哪些参数需要额外调整?
  3. 特征重要性排名前三的特征在 XGBoost 中是否仍然重要?如何验证?

建议通过修改以下代码进行对比实验:

from sklearn.ensemble import GradientBoostingClassifier

gbdt = GradientBoostingClassifier(
    n_estimators=100,
    learning_rate=0.1,
    max_depth=3
)
gbdt.fit(scaled_features, labels)

正文完
 0
评论(没有评论)