高效的 ROC/AUC 计算和时间复杂度

时间:2021-06-22 18:24:27

标签: machine-learning roc auc

接收器操作特性 (ROC) 和曲线下面积 (AUC) 是众所周知的概念。我反复使用它们(使用 scikit-learn 之类的库),但从未真正学会如何实现它们。

想到的显而易见的实现是:固定步长 delta,将 0 - 1 的区间除以 delta,对于所有这些阈值,计算 TPR 和 FPR。

https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc 中,我了解到“为了计算 ROC 曲线中的点,我们可以使用不同的分类阈值多次评估逻辑回归模型,但这将是低效的。幸运的是,有一种高效的排序可以为我们提供这些信息的基于算法的算法,称为 AUC。” - 这让我想到,对于大量样本,使用哪些算法进行有效的 ROC/AUC 计算?这种高效算法的时间复杂度是多少?

1 个答案:

答案 0 :(得分:2)

因此,我研究了 scikit-learn 的实现。我将在这里尝试解释算法。

让我们考虑官方示例:

>>> import numpy as np
>>> from sklearn import metrics
>>> y = np.array([1, 1, 2, 2])
>>> scores = np.array([0.1, 0.4, 0.35, 0.8])
>>> fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2)
>>> fpr
array([0. , 0. , 0.5, 0.5, 1. ])
>>> tpr
array([0. , 0.5, 0.5, 1. , 1. ])
>>> thresholds
array([1.8 , 0.8 , 0.4 , 0.35, 0.1 ])

第 1 步:首先要决定的是我们需要多少个阈值点?

  • 我们不需要超过概率/分数的样本数。让我们考虑一下这个案例。我们有 scores = [0.1, 0.4, 0.35, 0.8],如果我们在 0.35 和 0.4 之间选择一个点,它不会在 ROC 曲线上添加任何新点(与 0.4 相同)。我们可以通过仅选择唯一的阈值(集合)来进一步减少阈值的数量。我们还可以删除任何共线点。

复杂度:O(n)

第 2 步:如何计算 TPR 和 FPR?

我们当然可以计算 TPR 和 FPR,方法是考虑每个阈值并计算超过该点的分数,并检查它们的真实标签。

现在,这将是 O(N^2)

但是我们可以使用贪婪的方法来提高效率。如果我们对分数数组进行排序会发生什么?

y_score = [0.8, 0.4, 0.35, 0.1]

y_true = [1, 0, 1, 0] # converted to binary

现在,如果我们迭代 y_score,对于 0.8,如果我们有 y_true = 1,那么真正的正数将为 1,因为只有 1 个真正的标签是 {{ 1}}。如果我们移动到 0.4,我们知道 >= 0.8 但对于 0.4,标签是假的,所以仍然,真阳性计数为 1,在 0.35,我们有 0.35 和 0.4 和 0.8 >= 0.35,并且有 2 个真标签,这意味着真正的正数是 2。 现在,我们可以很容易地用累积和来计算。

0.8 and 0.4 >= 0.4

我们可以通过最后一个元素 TPC = [1, 1, 2, 2] 对其进行标准化以获得 TPR。

TPC[-1]

这与 scikit-learn 的输出相同。额外的 TPR = [0.5, 0.5, 1, 1] 阈值用于确保 ROC 从 (0, 0) 开始。

同样,我们可以用 1 + max(score) 计算误报数。

所以,总时间复杂度:1 + index - true positive count(用于排序)