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

scikit-learn中DecisionTree与ExtraTree的ROC曲线异常问题咨询

问题描述

在二分类(是/否)任务中,使用scikit-learn训练多个分类器并绘制ROC曲线时,DecisionTreeClassifier()和ExtraTreeClassifier()的ROC曲线呈现异常形态,其他分类器曲线形态正常。尝试了scikit-learn所有绘制ROC曲线的函数,结果一致,需要指导如何优化模型或调整绘图方式。

原决策树代码如下:

model3 = make_pipeline(preprocessor, DecisionTreeClassifier())
model3[:-1].get_feature_names_out()
m=model3[:-1].get_feature_names_out()
model3 = model3.fit(data_train, target_train)

plt.figure(figsize=(12,12))
plot_tree(model3.named_steps['decisiontreeclassifier'], fontsize=10, node_ids=True,
feature_names=m, max_depth=5)

cm3 = confusion_matrix(target_test, y_pred3, normalize='all')
cm3_display = ConfusionMatrixDisplay(cm3).plot()
plt.xlabel('Klasa predykowana – wynik testu')
plt.ylabel('Klasa rzeczywista')
plt.show()

RocCurveDisplay.from_estimator(model3, data_test, target_test)
plt.show()

RocCurveDisplay.from_predictions(target_test, y_pred3)
plt.show()

model3_probs = model3.predict_proba(data_test)
model3_probs = model3_probs[:, 1]
model3_fpr, model3_tpr, _ = roc_curve(target_test, model3_probs)
roc_auc = metrics.auc(model3_fpr, model3_tpr)
display = metrics.RocCurveDisplay(fpr=model3_fpr, tpr=model3_tpr,
roc_auc=roc_auc,estimator_name='example estimator')
display.plot()
解决方案

一、模型优化(核心原因:决策树过拟合导致概率输出离散)

决策树和极端树默认无限制生长,极易过拟合训练数据,导致输出的预测概率只有少数离散值(甚至只有0和1),进而让ROC曲线形态异常。可以通过以下参数约束模型:

  • 限制树的最大深度:设置max_depth参数(如max_depth=5),避免树过度分裂,可通过交叉验证(GridSearchCV)选择最优深度。
  • 增加叶节点最小样本数:设置min_samples_leaf=5或min_samples_split=10,防止树在少量样本上分裂,降低过拟合风险。
  • 启用代价复杂度剪枝:通过ccp_alpha参数进行剪枝,可先调用model.cost_complexity_pruning_path()获取候选值,再用交叉验证选最优ccp_alpha。
  • 处理类别不平衡:如果数据集存在类别不平衡,添加class_weight='balanced'参数,让模型自动调整类别权重,避免偏向多数类。

二、绘图方式调整

  • 避免用硬预测结果绘制ROC:RocCurveDisplay.from_predictions()接收的是分类结果(0/1),只能生成单个点或少数几个点的曲线,这不是标准ROC曲线的绘制方式。必须使用模型输出的概率值(predict_proba()返回的正类概率)来绘制,即使用RocCurveDisplay.from_estimator()或手动计算FPR/TPR的方式。
  • 检查预测概率的分布:先打印model3_probs的唯一值,如果只有少数几个值,说明模型过拟合严重,需要优先优化模型。
调整后的代码示例
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, RocCurveDisplay, roc_curve, auc

# 1. 优化决策树参数
param_grid = {
    'decisiontreeclassifier__max_depth': [3,5,7],
    'decisiontreeclassifier__min_samples_leaf': [3,5,10],
    'decisiontreeclassifier__class_weight': ['balanced']
}
model3 = make_pipeline(preprocessor, DecisionTreeClassifier())
grid_search = GridSearchCV(model3, param_grid, cv=5, scoring='roc_auc')
grid_search.fit(data_train, target_train)
model3 = grid_search.best_estimator_

# 2. 生成预测结果(补全原代码中缺失的y_pred3定义)
y_pred3 = model3.predict(data_test)

# 3. 绘制树结构
plt.figure(figsize=(12,12))
plot_tree(model3.named_steps['decisiontreeclassifier'], fontsize=10, node_ids=True,
          feature_names=model3[:-1].get_feature_names_out(), max_depth=5)
plt.show()

# 4. 混淆矩阵
cm3 = confusion_matrix(target_test, y_pred3, normalize='all')
cm3_display = ConfusionMatrixDisplay(cm3).plot()
plt.xlabel('预测类别 – 测试结果')
plt.ylabel('真实类别')
plt.show()

# 5. 用模型直接绘制ROC(基于概率)
RocCurveDisplay.from_estimator(model3, data_test, target_test, estimator_name='优化后的决策树')
plt.show()

# 6. 手动计算并绘制ROC
model3_probs = model3.predict_proba(data_test)[:, 1]
model3_fpr, model3_tpr, _ = roc_curve(target_test, model3_probs)
roc_auc = auc(model3_fpr, model3_tpr)
display = RocCurveDisplay(fpr=model3_fpr, tpr=model3_tpr, roc_auc=roc_auc,
                          estimator_name='优化后的决策树')
display.plot()
plt.show()

内容的提问来源于stack exchange,提问作者PawelKinczyk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:18:26