DecisionTree:Python决策树分类回归

2026-10-11 02:35:30 811阅读 0评论

DecisionTree:用Python决策树搞定分类与回归,别只会调包

做预测任务时,很多人一上来就堆随机森林、XGBoost,效果不一定稳,解释起来还费劲。真正适合先摸清楚数据规律的,往往是决策树。它既能做分类,也能做回归,规则看得见,结果讲得明,Python里几行代码就能跑起来。

决策树到底在干什么

决策树本质上是在不断做“如果……就……”的判断。

比如判断一个用户会不会购买商品:先看访问时长,超过某个阈值进入一侧;再看历史订单数;最后看是否领取优惠券。每分裂一次,数据集就被切得更纯一点。分类任务看类别是否集中,回归任务看目标值差异是否变小。

在scikit-learn中,分类用DecisionTreeClassifier,回归用DecisionTreeRegressor。两者接口相似,但分裂依据和输出不同:

  • 分类树输出类别,常用基尼系数或信息增益衡量节点纯度。
  • 回归树输出连续值,通常用均方误差(MSE)或平均绝对误差(MAE)衡量分裂效果。
  • 回归树的叶子节点返回的是该节点样本目标值的均值,而不是某条线性趋势。

这也解释了一个常见误区:决策树回归不是拟合一条直线,而是把特征空间切成多个区域,每个区域给一个固定预测值。单棵回归树画出来,预测结果常常是阶梯状的。

一个可直接套用的Python流程

以分类任务为例,先准备数据,再训练模型:

import pandas as pd
from sklearn.datasets importload_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report

data = load_iris(as_frame=True)
X = data.data
y = data.target

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

clf = DecisionTreeClassifier(
    criterion="gini",
    max_depth=3,
    min_samples_leaf=5,
    random_state=42
)

clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

print(accuracy_score(y_test, y_pred))
print(classification_report(y_test, y_pred))

换成回归任务也很直接:

from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error

reg = DecisionTreeRegressor(
    criterion="squared_error",
    max_depth=4,
    min_samples_leaf=10,
    random_state=42
)

reg.fit(X_train, y_train)
y_pred = reg.predict(X_test)

print(mean_squared_error(y_test, y_pred))

关键不是记住API,而是明白训练前要做什么。决策树对特征缩放不敏感,不需要标准化、归一化;但它对异常值、样本扰动和过拟合很敏感。训练集准确率很高、测试集掉得厉害,基本就是树长太“疯”了。

调参时真正该盯的地方

很多教程会把参数列一长串,但实际项目里优先看这几个:

max_depth:限制树深,是最直接的防过拟合手段。数据量不大时,可以从3、5、8依次尝试。

min_samples_leaf:叶子节点至少包含多少样本。值太小,模型容易记住个别噪声;值太大,又可能欠拟合。做风控、医疗这类样本差异大的任务,适当提高它通常更稳。

min_samples_split:节点继续分裂所需的最小样本数。它和min_samples_leaf作用相近,不建议一开始就同时大幅调整,否则很难判断是谁起了作用。

class_weight:分类样本不均衡时可设为balanced。它能缓解少数类被淹没的问题,但不能替代合理的抽样和评估指标。

调参不要只看训练集分数,更不要凭测试集反复挑参数。更稳妥的做法是用交叉验证,把验证集表现作为选择依据,测试集只在最后评估一次。

怎么判断树有没有学歪

分类任务别只盯准确率。样本不均衡时,全部预测多数类也可能有很高准确率,却没有实际价值。此时应结合混淆矩阵、精确率、召回率、F1值判断。

回归任务除了MSE,也建议看MAE。MSE会放大异常误差,MAE对极端错误没那么敏感。如果两者差距很大,往往说明模型在少数极端样本上预测偏差明显。

还可以查看特征重要性:

importance = pd.Series(clf.feature_importances_, index=X.columns)
print(importance.sort_values(ascending=False))

但这里有个坑:特征重要性高,不代表它和目标有可靠因果关系。高基数特征、取值很多的ID类变量,可能被决策树反复利用,看起来很重要,实际只是在“背答案”。这类特征应提前剔除或谨慎处理。

可视化不是为了好看

树不深时,可以把规则导出来看:

from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

plt.figure(figsize=(16, 8))
plot_tree(
    clf,
    feature_names=X.columns,
    class_names=data.target_names,
    filled=True,
    rounded=True
)
plt.show()

实际分析时,重点看三件事:根节点选中的特征是否符合业务逻辑;叶子节点里的样本量是否过少;某些路径是否只是在迎合极少数样本。如果一棵深度为10的树只能给出复杂却不可解释的规则,它的业务价值通常不如一棵稍浅、但稳定的树。

单棵决策树适合什么场景

它适合作为基线模型,帮你快速理解特征关系、发现重要变量、验证数据加工是否有明显问题。表格数据量不大、特征含义明确、需要向业务方解释判断依据时,决策树尤其好用。

如果单棵树泛化能力不足,再考虑随机森林、梯度提升树等集成方法。只是别把模型复杂度当成效果保证。先让一棵浅树跑出可信基线,再逐步增加复杂度,往往比一开始就上重型模型更省时间,也更容易排查问题。

决策树的价值,不在于它多先进,而在于它把预测过程摊开给你看。规则能检查,错误能追溯,模型才真正用得踏实。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,811人围观)

还没有评论,来说两句吧...

目录[+]