二元分类变量的 AUC 的有效性

机器算法验证 分类数据 预测模型 奥克
2022-03-23 19:19:32

Scikit-learn 函数roc_auc_score可用于获取 ROC 曲线的曲线下面积 (AUC)。该分数通常用于预测结果中的数字预测值。

但是,此函数也可用于分类变量。下面是一个示例(Python 语言),其中变量sex用于预测变量survived,并使用此函数获得 AUC:

import seaborn, pandas, sklearn
from sklearn.metrics import roc_auc_score
tdf = seaborn.load_dataset('titanic')
print(tdf[['survived','sex']].head(10))
x = tdf['sex'].apply(lambda x: 1 if x=='female' else 0)
y = tdf['survived']
auc = roc_auc_score(y, x)   
auc = round(auc, 4)
print()
print("AUC for sex to predict survived:", auc)

输出:

   survived     sex
0         0    male
1         1  female
2         1  female
3         1  female
4         0    male
5         0    male
6         0    male
7         0    male
8         1  female
9         1  female


AUC for sex to predict survived: 0.7669

但是,这种技术在统计上是否合理?使用这种方法获得的 AUC 是否是 2 个分类变量之间关系的有效值?谢谢你的帮助。

编辑:我已将性别编码反转为 0 和 1,因此 AUC 现在为 0.7669

Edit2:从下面给出的非常有趣的答案来看,以下几点似乎很重要:

  • 只要解释正确,AUC 也可以与分类变量一起使用。

  • 需要强调的是,AUC离0.5越大越好,不一定越高。因此,0.1 的 AUC 比 0.7 的 AUC 更具预测性,尽管方向相反

  • 可以通过以下简单的 Python 代码报告“绝对 AUC”:

    Abs_AUC = AUC if (AUC>0.5) else (1-AUC)

因此,对于 0.1 的 AUC,绝对 AUC 为 0.9;这将有助于比较不同变量的 AUC,而不会遗漏 ROC 曲线对角线另一侧的 AUC。注意:这建议用于只有 2 个类别的预测变量。

4个回答

ROC 曲线是一种等级统计,因此只要您对数据进行排序的方式有意义,它就有效。在其最常见的应用中,我们根据模型产生的预测概率进行排序。这是有意义的,因为我们在一个极端有最可能的事件,而在另一个极端有最不可能的事件。 ”在每个阈值处捕获了多少结果,以及(2)有多少您使用相同的规则捕获的误报。p^>threshold

ROC AUC 是随机选择的正例比随机选择的负例排名更高的概率。当我们使用 ROC AUC 来评估机器学习模型时,我们总是想要一个更高的 AUC 值,因为我们希望我们的模型给正面的排名更高。另一方面,如果我们构建了一个样本外 AUC 远低于 0.5 的模型,我们就会知道该模型是垃圾。

在 OP 的示例中,OP 证明了他们如何编码分类数据的任意选择可以反转 AUC 的含义。在最初的帖子中,OP 写道:

性别预测存活的 AUC:0.2331

但随后进行了编辑以反转性别的排序和查找方式

编辑:我已将性别编码反转为 0 和 1,因此 AUC 现在为 0.7669。

结果完全相反。在第一种情况下,我们的 AUC 为,但在第二种情况下,我们的 AUC 为这有效地证明了为什么选择如何对分类数据进行排序至关重要!因此,我不建议使用 AUC 来解释无序数据。c1c

这通常是人们会指出你可以扭转非常糟糕的预测以获得非常高的 AUC 的地方。就目前而言,这是正确的,但是“让我们运行 2 个测试,修改我们的数据,并报告最有利的结果”不是合理的统计实践。

您建议的报告 AUC 和 1-AUC 中较大者的程序给您带来了巨大的乐观偏见。

  • 如果您的数据有 3 个或更多类别,并且您对它们施加任意顺序,则您可能需要测试所有排列以获得最高 AUC,而不仅仅是颠倒排序(报告 1 - AUC 相当于颠倒排序)。例如,类别是“红色”、“绿色”和“蓝色”,而不是“男性”和“女性”。有超过 2 种方法可以对它们进行排序,因此简单地颠倒顺序并不能涵盖所有可能的排列。
  • 在极端情况下,您可能会遇到唯一标识每个观测单元的分类变量(例如,国家身份证号码、电话号码、地理位置坐标或类似信息)。这些唯一标识符的最佳排序将具有 1 的 AUC(将所有正数放在最低等级),但它不会一概而论,因为您不知道应该将新的唯一标识符放在哪里。
  • 如果您严重过度拟合分类器,则此方法会愉快地报告比您实际拥有的 AUC 高得多的 AUC。
  • 假设检验将是虚假的,因为您选择的是最有利的统计数据。

另一方面,一个如果您更改类别的排序方式,则不会给出不同的统计信息。当您有 3 个或更多类别时,它也适用。

看到这里的 ROC 曲线并不是真正的曲线是很有帮助的。相反,您实际上是在生成一个模型,显示 P(Survive|Male) = .18 和 P(Survive|Female) = .74(数据中的平均值),并使用一系列阈值进行预测,例如prediction = 1p_survive > threshold0其他。

你最终预测每个人都将在任何阈值 < .18 内存活,所有女性和男性都将在 0.18 和 0.74 之间的阈值内存活,并且没有人会在阈值 > .74 时存活。希望这应该清楚地表明计算 AUC 或绘制 ROC 并没有真正提供任何额外信息,因为更改阈值不会影响预测,除非您将其设置为 daft 值。但是,它也表明您获得的 AUC 分数仍然是有效的。

在此处输入图像描述

在此处输入图像描述

           true_positives  false_positives
threshold                                 
0.0                  1.00             1.00
0.1                  1.00             1.00
0.2                  0.68             0.15
0.3                  0.68             0.15
0.4                  0.68             0.15
0.5                  0.68             0.15
0.6                  0.68             0.15
0.7                  0.68             0.15
0.8                  0.00             0.00
0.9                  0.00             0.00
1.0                  0.00             0.00

代码

p_male, p_female = [tdf.loc[tdf['sex'] == sex, 'survived'].mean() for sex in ['male', 'female']]
tdf['p_survived'] = np.where(tdf['sex'] == 'male', p_male, p_female)

thresholds = np.linspace(0, 1, 11)

def check_calibration(threshold, predicted_probs, outcome):
    prediction = 1 * (predicted_probs > threshold)
    return {
        'true_positives' : prediction[outcome == 1].mean(),
        'false_positives' : prediction[outcome == 0].mean()        
    }

calibration = pd.DataFrame([
    check_calibration(thresh, tdf['p_survived'], tdf['survived'])
    for thresh in thresholds
]).fillna(0)
calibration.index = pd.Index(thresholds, name = 'threshold')

print(calibration.round(2))

accuracies.plot()
plt.xlabel('Threshold (Predict "Survived" if P(Survived > Threshold))')
plt.ylabel('True/False Positive Rate')
plt.title('Calibration')

plt.figure(figsize=(5,5))
plt.plot(accuracies['false_positives'], accuracies['true_positives'])
plt.scatter(accuracies['false_positives'], accuracies['true_positives'])
plt.plot([0,1], [0,1], linestyle = 'dashed', color = 'k')
plt.xlabel('False Positives')
plt.ylabel('True Positives')
plt.title('ROC Curve')

这种方法没有错,但它不是 ROC 的一个非常有用的应用程序。ROC 曲线的目的是显示模型在一系列分类阈值上的性能,AUC 总结了模型在所有可能阈值上的质量。使用二分类预测变量,您只有三个可能的选择,其中两个是退化的一类模型 - 您可以将所有内容归为一类,或将所有内容归类为另一类,或者实际使用预测变量进行预测结果。ROC 曲线仅由三个点组成,一个位于 (0,1),一个位于 (1,0),另一个位于实际有用模型的特定灵敏度/特异性。既然你真的只有一个合理的“阈值”选择,你可以更直接地使用敏感性和特异性来总结模型,

请注意,在此特定示例中,您已向后设置类别。随机分类器的 AUC 是 0.5,所以如果你发现 AUC 小于 0.5,那么你做的比随机分类器还差。这通常意味着您应该翻转类的顺序。您已经建立了一个擅长获得错误答案的模型,因此您实际上应该将其归类为与它所说的相反的东西。

澄清一下,ROC 曲线意味着绘制与假阳性相比,你得到多少真阳性。

目标标签是数字标签还是分类标签是一个实现问题,但它不会改变原则的有效性,您仍在评估您的模型在区分两个分布方面的“好” (AUC) 程度。

AUC 越高,您可以通过调整阈值获得的 TP 与 FP 比率越高。

这就是 AUC 被解释为模型性能度量的方式,据我所知,AUC 并没有量化两个变量之间的关系。