问题描述
我正在尝试了解 Logit 模型的 Python statsmodels 中的 predict
函数。它的文档是 here。
当我构建 Logit 模型并使用 predict
时,它返回从 0 到 1 而不是 0 或 1 的值。现在我读到这篇文章说这些是概率,我们需要一个阈值。 Python statsmodel.api logistic regression (Logit)
现在,我想生成 AUC 数字,并使用 sklearn (docs) 中的 roc_auc_score
。
这就是我开始困惑的时候。
- 当我将 Logit 模型中的原始预测值(概率)放入
roc_auc_score
作为第二个参数y_score
时,我得到了大约 80% 的合理 AUC 值。roc_auc_score
函数如何知道我的哪些概率等于 1,哪些等于 0?我没有机会设置门槛。 - 当我使用 0.5 的阈值手动将概率转换为 0 或 1 时,我得到的 AUC 约为 50%。为什么会发生这种情况?
这是一些代码:
m1_result = m1.fit(disp = False)
roc_auc_score(y,m1_result.predict(X1))
AUC: 0.80
roc_auc_score(y,[1 if X >=0.5 else 0 for X in m1_result.predict(X1)])
AUC: 0.50
为什么会这样?
解决方法
predict
根据您的拟合模型产生事件的估计概率。也就是说,每个元素对应于您的模型为每个观察计算的预测概率。
构建 ROC 曲线背后的过程包括选择每个预测概率作为阈值,测量其误报率和真阳性率,并将这些结果绘制为折线图。该曲线下方的面积是 AUC。
为了可视化这一点,假设您有以下数据:
观察 | 观察结果 | predicted_prob |
---|---|---|
1 | 0 | 0.1 |
2 | 0 | 0.5 |
3 | 1 | 0.9 |
函数 roc_auc_score
将执行以下操作:
- 使用 0.1 作为阈值,使得
predicted_prob
≤ 0.1 的所有观察都归为 0,而predicted_prob
> 0.1 的观察将归为 1 - 使用 0.5 作为阈值,使得
predicted_prob
≤ 0.5 的所有观察都归为 0,而predicted_prob
> 0.5 的观察将归为 1 - 使用 0.9 作为阈值,使得
predicted_prob
≤ 0.9 的所有观察都归为 0,而predicted_prob
> 0.9 的观察将归为 1
三个不同的阈值(0.1、0.5 和 0.9)中的每一个都会导致各自的误报率和真阳性率。沿 x 轴绘制假阳性率,而沿 y 轴绘制真阳性率。
如您所料,您需要测试许多阈值才能绘制平滑曲线。如果您使用 0.5 作为阈值并将其传递给 roc_auc_curve
,则您正在测试单个阈值的假阳性率和真阳性率。这是不正确的,也是 roc_auc_curve
返回的 AUC 比以前更低的原因。
您可能想通过计算其相应的准确率、真阳性率或假阳性率来测试单个阈值(即 0.5)的性能,而不是这样做。
例如,假设我们在上面的数据中设置了 0.5 的阈值。
观察 | 观察到的结果 | predicted_prob | predicted_class |
---|---|---|---|
1 | 0 | 0.1 | 0 |
2 | 0 | 0.5 | 0 |
3 | 1 | 0.9 | 1 |
这是一个愚蠢的例子,但通过使用 0.5 作为截止值,我们做出了完美的预测,因为 observed_result
在所有情况下都匹配 predicted_class
。
您计算 AUC 的第二种方法是错误的;根据定义,AUC 需要概率,而不是阈值化后生成的硬类预测 0/1,就像您在此处所做的那样。所以,你的 AUC 是 0.80。
你在AUC计算中没有自己设置阈值;粗略地说,正如我已经解释过的那样elsewhere,AUC 衡量的是一个二元分类器的性能在所有可能的决策阈值上平均。
在这里再次解释 AUC 计算的基本原理和细节是多余的;相反,这些其他 SE 线程(以及其中的链接)将帮助您了解这个想法: