You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Sklearn构建决策树:PlayTennis数据集根节点异常问题

问题分析与解决

你遇到的核心问题是手动计算基于全量数据集,而Sklearn决策树的特征选择是基于划分后的训练集,这直接导致了根节点选择的差异。下面具体拆解原因和解决方案:

1. 训练集与全量数据集的信息增益差异

你通过train_test_split将数据按7:3划分为训练集和测试集,Sklearn的DecisionTreeClassifier在拟合时,只会用训练集的样本计算熵和信息增益来选择根节点——而你手动计算的是所有14条样本的信息增益,两者的样本分布可能不同,自然会得到不同的最优特征。

验证方法:用全量数据训练

如果你去掉数据集划分,直接用所有数据训练决策树,根节点应该会和你手动计算的outlook_一致:

# 移除train_test_split步骤,直接使用全量数据
clf_entropy = DecisionTreeClassifier(criterion='entropy')
clf_entropy.fit(X.astype(int), Y.astype(int))

# 可视化决策树,查看根节点
import matplotlib.pyplot as plt
tree.plot_tree(clf_entropy, feature_names=X.columns, class_names=['No', 'Yes'], filled=True)
plt.show()

2. 代码中LabelEncoder的潜在问题

你反复使用同一个LabelEncoder实例处理不同特征,虽然当前数据集的特征类别无重叠(比如outlook的类别和temp的类别不重复),暂时不会出错,但这是不规范的做法——不同特征的编码应该相互独立,建议给每个特征单独创建编码器:

# 为每个特征单独创建LabelEncoder
le_outlook = LabelEncoder()
df['outlook_'] = le_outlook.fit_transform(df['outlook'])

le_temp = LabelEncoder()
df['temp_'] = le_temp.fit_transform(df['temp'])

le_humidity = LabelEncoder()
df['humidity_'] = le_humidity.fit_transform(df['humidity'])

le_windy = LabelEncoder()
df['windy_'] = le_windy.fit_transform(df['windy'])

le_play = LabelEncoder()
df['play_'] = le_play.fit_transform(df['play'])

3. 验证训练集的信息增益

如果你想确认训练集上各特征的信息增益,可以用Sklearn的mutual_info_classif计算特征与目标变量的互信息(互信息等价于信息增益,当目标变量的熵固定时):

from sklearn.feature_selection import mutual_info_classif

# 计算训练集上各特征的互信息
mi_scores = mutual_info_classif(X_train.astype(int), y_train.astype(int), discrete_features=True)
mi_df = pd.Series(mi_scores, index=X_train.columns).sort_values(ascending=False)

print("训练集特征互信息排序:")
print(mi_df)

输出中数值最高的特征就是决策树选择的根节点,这能帮你理解为什么训练集上humidity_会被选为根节点。


内容的提问来源于stack exchange,提问作者Sriram Arvind Lakshmanakumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:32:51