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

statsmodels Logit模型ROC与混淆矩阵结果不一致问题排查

statsmodels Logit模型ROC与混淆矩阵结果矛盾问题解答

核心问题根源

对逻辑回归的概率输出规则、阈值选择逻辑、ROC评估原理的认知偏差,叠加代码语法错误、阈值选择不符合数据分布特征,共同导致了结果矛盾。

问题1:statsmodels Logit的predict方法返回值是什么?

返回值是样本属于正类(即标签取值为1)的预测概率,取值范围为(0,1),不是直接的0/1分类标签。
你观测到正样本预测值在10-2量级、负样本在10-5量级,说明数据集存在明显的类别不平衡特征,正类占比极低,因此模型输出的整体正类概率都处于较低区间。
额外提示:你贴出的拟合代码存在语法错误,sm.Logit(df['with_payment', model_matrix)缺少列索引的闭合括号,正确写法为sm.Logit(endog=df['with_payment'], exog=model_matrix),语法错误会导致输入的特征、标签匹配异常,建议先修正。

问题2:predict方法是否会自动应用优化后的分类阈值?

不会。
statsmodels的Logit模块没有内置自动寻优分类阈值的逻辑,拟合完成的模型对象也不会存储所谓“最优阈值”参数。逻辑回归本质是概率预测模型,0.5作为分类阈值只是通用惯例,不是模型拟合过程中学习得到的参数。
你用np.round()处理预测值的本质是强制使用0.5作为分类阈值:所有预测概率小于0.5的样本都会被判为负类。由于你的模型输出的最高正类概率仅为10^-2量级,远低于0.5,自然所有样本都会被判定为负类,这就是混淆矩阵显示全预测为0的直接原因。
而ROC曲线评估的是模型对正负样本的排序能力,不依赖固定分类阈值:只要模型给正样本的预测概率整体高于负样本,哪怕所有概率值都远低于0.5,AUC也能表现正常,二者结果并不矛盾。

问题3:是否需要手动传入分类阈值?如何正确设置阈值完成分类?

需要手动选择分类阈值,不存在通用的“最优阈值”,阈值选择需要结合业务对假阳性、假阴性的容忍度决定,常见的阈值确定方法包括:

  • 基于Youden指数:取ROC曲线上tpr - fpr取最大值时对应的阈值,最大化整体分类的区分度
  • 基于业务指标要求:例如需要覆盖90%以上的正样本时,选择TPR=0.9对应的阈值
  • 类别极不平衡场景,可以用训练集中正类的占比作为初始参考阈值

修正后的可运行代码示例

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from sklearn.metrics import roc_curve, auc
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

# 1. 修正语法错误,拟合模型
log_reg = sm.Logit(endog=df['with_payment'], exog=model_matrix).fit()

# 2. 生成正类预测概率(不要直接转标签)
model_matrix['pred_prob'] = log_reg.predict(model_matrix)

# 3. 计算ROC指标,选取最优阈值
fpr, tpr, thresholds = roc_curve(df['with_payment'], model_matrix['pred_prob'])
roc_auc = auc(fpr, tpr)
print(f"Area under the ROC curve : {roc_auc:.4f}")

# 以Youden指数为例选取最优阈值
youden_idx = np.argmax(tpr - fpr)
best_threshold = thresholds[youden_idx]
print(f"Selected classification threshold: {best_threshold:.6f}")

# 4. 用选定阈值生成分类标签,替代np.round()的0.5硬阈值
pred_label = (model_matrix['pred_prob'] >= best_threshold).astype(int)

# 5. 绘制混淆矩阵
cm = confusion_matrix(df['with_payment'], pred_label)
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot()
plt.show()

注意事项

在正负样本分布不均衡的场景下,禁止直接用np.round()处理预测概率生成分类标签,该操作仅在正负样本占比大致均衡、模型输出概率分布在0.5两侧时适用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:09:25