基于CART决策树的西瓜数据集分类实战与调优指南

1次阅读
没有评论

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

image.webp

初识 CART 决策树与西瓜数据集

CART 决策树通过二叉树结构实现高效分类,天然支持混合型特征处理,且对缺失值不敏感——这正是我们选择它处理西瓜数据集的原因。这个经典数据集包含 17 个样本,特征既有离散型(如色泽、根蒂形态)也有连续型(如密度、含糖率),完美匹配 CART 算法的处理能力。更重要的是,生成的决策规则可解释性强,农业专家一眼就能看懂模型判断『坏瓜』的逻辑。

你肯定踩过这些坑

特征重要性评估的三大误区

  • 迷信默认排序:sklearn 的 feature_importances_基于训练集计算,可能高估噪声特征
  • 忽视特征交互:单独评估『纹理』重要性可能很低,但与『触感』组合后判别力飙升
  • 混淆信息量:连续特征的分箱方式会极大影响重要性得分,需用交叉验证确认

当特征取值过多时

比如『纹理』有清晰、稍糊、模糊三种取值,而『编号』特征包含 17 个唯一值。后者虽然信息增益高,但生成的决策树会在训练集表现完美(每个叶子节点一个样本),测试集准确率却可能不足 60%。

连续特征的标准化陷阱

决策树本不需要标准化!但如果你同时使用 PCA 降维:

# 错误做法:对全部特征标准化
scaler = StandardScaler()  # 会破坏离散特征的原始分布

# 正确做法:仅标准化连续特征
cont_features = ['密度', '含糖率']
df[cont_features] = scaler.fit_transform(df[cont_features])

手把手调优实战

从数据加载到建模

import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_text

# UCI 西瓜数据集简化版
cols = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '密度', '含糖率', '好瓜']
data = [['青绿', '蜷缩', '浊响', '清晰', '凹陷', '硬滑', 0.697, 0.460, '是'],
    # ... 其他 16 条数据
]
df = pd.DataFrame(data, columns=cols)

# 离散特征独热编码
df = pd.get_dummies(df, columns=['色泽', '根蒂', '敲声', '纹理', '脐部', '触感'])

# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(df.drop('好瓜', axis=1), 
    df['好瓜'], 
    test_size=0.3,
    stratify=df['好瓜']  # 保持类别比例
)

# 关键参数设置
model = DecisionTreeClassifier(
    criterion='gini',  # 基尼系数
    max_depth=3,       # 预剪枝
    min_samples_leaf=2 # 防止过拟合
)
model.fit(X_train, y_train)

可视化决策边界变化

通过网格搜索观察 max_depth 的影响:

depths = range(1, 8)
train_scores, test_scores = [], []

for d in depths:
    clf = DecisionTreeClassifier(max_depth=d)
    clf.fit(X_train, y_train)
    train_scores.append(clf.score(X_train, y_train))
    test_scores.append(clf.score(X_test, y_test))

plt.plot(depths, train_scores, 'bo-', label='训练集')
plt.plot(depths, test_scores, 'r*-', label='测试集')
plt.xlabel('决策树深度')
plt.ylabel('准确率')
plt.legend()

基于 CART 决策树的西瓜数据集分类实战与调优指南

当 max_depth= 4 时测试集准确率达到 92.3%,继续增加深度会导致过拟合。

资深工程师的避坑指南

检测数据泄露的黄金法则

检查特征中是否混入『未来信息』:

# 警惕这类特征
assert '好瓜_是' not in X_train.columns  # 标签泄露
assert '编号' not in X_train.columns     # 无意义 ID

处理类别不平衡

当正负样本比例为 1:4 时:

# 方法 1:调整 class_weight
model = DecisionTreeClassifier(class_weight={'是':4, '否':1})

# 方法 2:上采样少数类
from imblearn.over_sampling import SMOTE
X_res, y_res = SMOTE().fit_resample(X_train, y_train)

决策树可视化优化

import graphviz
dot_data = export_graphviz(
    model, 
    out_file=None,
    feature_names=X_train.columns,
    class_names=['坏瓜', '好瓜'],
    filled=True,
    rounded=True,
    special_characters=True,
    fontsize=8  # 小于 10 可能导致文字重叠
)
graph = graphviz.Source(dot_data)
graph.render('watermelon')

延伸思考

  1. 基尼系数 vs 信息增益 :修改criterion='entropy' 后,模型会更倾向选择具有更多取值的特征吗?
  2. 新增『糖度』特征:需要重新评估特征重要性,并可能调整 max_depth 防止决策路径过长

在真实农业检测场景中,还可以考虑加入『日照时长』、『降雨量』等环境特征。不过要记住:更多特征意味着需要更多数据来避免维度灾难。

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