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

如何绘制各KFold混淆矩阵并通过循环展示以分析召回率为0的原因

没问题!要搞定每个KFold折的混淆矩阵并找出召回率为0的原因,我们需要跳出cross_val_score的封装,手动遍历每个折的训练和预测流程,这样才能拿到足够的细节来分析。下面是完整的实现和分析思路:

为每个KFold折绘制混淆矩阵的完整实现

首先我们需要补充必要的库,并手动遍历KFold的每个拆分(这样才能获取每个折的预测结果来生成混淆矩阵):

from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, recall_score
import matplotlib.pyplot as plt

# 初始化KFold(建议加上shuffle=True,避免数据顺序导致的分布偏差)
kfold = model_selection.KFold(n_splits=6, random_state=19, shuffle=True)
model = LogisticRegression()

# 遍历每个KFold折,enumerate给每个折加序号
for fold_idx, (train_idx, test_idx) in enumerate(kfold.split(X_under, y_under), 1):
    # 拆分当前折的训练集和测试集
    X_train, X_test = X_under.iloc[train_idx], X_under.iloc[test_idx]
    y_train, y_test = y_under.iloc[train_idx], y_under.iloc[test_idx]
    
    # 训练模型
    model.fit(X_train, y_train)
    
    # 生成测试集预测结果
    y_pred = model.predict(X_test)
    
    # 计算并绘制混淆矩阵
    cnf_matrix = confusion_matrix(y_test, y_pred)
    disp = ConfusionMatrixDisplay(confusion_matrix=cnf_matrix, display_labels=model.classes_)
    disp.plot(cmap=plt.cm.Blues)
    plt.title(f"Confusion Matrix - KFold Fold {fold_idx}")
    plt.tight_layout()
    plt.show()
    
    # 打印当前折的召回率,方便对应分析
    fold_recall = recall_score(y_test, y_pred)
    print(f"=== Fold {fold_idx} 召回率: {fold_recall:.4f} ===")

关键细节说明

  • 为什么不用cross_val_score?因为它只返回评估指标,没法拿到每个折的预测结果和数据集分布,手动遍历kfold.split()才能完整掌控每个折的流程,方便后续排查问题。
  • 一定要加shuffle=True:如果你的数据集是按类别排序的,不洗牌会导致某个折的测试集全是单一类别,这是召回率为0的常见诱因之一。
分析召回率得分为0的常见原因

结合每个折的混淆矩阵和数据集分布,你可以快速定位问题:

  • 测试集无正样本:查看对应折的y_test.value_counts(),如果你的目标正样本数量为0,召回率自然为0(这种情况在类别不平衡的数据集拆分时容易出现)。
  • 模型完全未预测出正样本:混淆矩阵中,正样本对应的预测列全为0。原因可能是:
    • 当前折的训练集正样本数量极少(即使做了欠采样,拆分后仍可能出现极端分布)
    • 模型正则化过强,或者参数设置不合理,导致欠拟合
    • 特征与目标变量相关性极低,模型无法学习到有效区分模式
  • 类别标签错误:检查你的y_under标签是否正确,有没有把正样本误标为负样本的情况。

额外调试小技巧

在循环里加入以下代码,能帮你更直观地排查数据分布问题:

# 打印当前折的训练/测试集类别分布
print(f"Fold {fold_idx} 训练集类别分布:\n{y_train.value_counts()}")
print(f"Fold {fold_idx} 测试集类别分布:\n{y_test.value_counts()}")

另外可以尝试给模型加上class_weight='balanced'参数,给少数类更高的权重,缓解类别不平衡带来的影响:

model = LogisticRegression(class_weight='balanced')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:51:55