在 SQL 中计算 AUC

Posted

技术标签:

【中文标题】在 SQL 中计算 AUC【英文标题】:Computing AUC in SQL 【发布时间】:2019-06-16 12:23:09 【问题描述】:

的最佳方法是什么?

这是我得到的(假设表 T(label, confid) 和 label=0,1):

SELECT sum(cumneg * label) * 1e0 / (sum(label) * sum(1-label)) AS auc
FROM ( 
  SELECT label,
    sum(1-label) OVER(ORDER BY confid ROWS UNBOUNDED PRECEDING) (BIGINT) cumneg
  FROM T
) t;

我必须在 Teradata 中乘以 1e0 才能得到真正的结果。 Bigint 强制转换对于避免溢出是必要的。

【问题讨论】:

【参考方案1】:

下面的伪 SQL 利用 AUC ROC 与预测分数区分随机正标签和随机负标签的概率相同的事实。 SQL 假定两个标签至少有 10000 个元素。计算的 AUC 并不精确,而是随机的。另见the same question for R。

WITH POSITIVE_SCORES AS (
  select
    score as p_pos
  from
    TABLE
    where label = positive
    order by rand()
    limit 10000
),

NEGATIVE_SCORES AS (
  select
    score as p_neg
  from
    TABLE
    where label = negative
    order by rand()
    limit 10000
)

select
  avg(case 
    when p_pos > p_neg then 1 
    when p_pos = p_neg then 0.5 
    else 0 
  end) as auc
from
  POSITIVE_SCORES
  cross join
  NEGATIVE_SCORES

【讨论】:

嗯,抽样有什么好处,特别是如果它需要通过 rand() 进行完整排序? 采样后有交叉连接。如果不采样,交叉连接可能会爆炸。【参考方案2】:

这是我发现的一个稍微不同但可能更简单的解决方案:

SELECT (sum(label*r) - 0.5*sum(label)*(sum(label)+1)) / (sum(label) * sum(1-label)) AS auc
FROM ( 
  SELECT label, row_number() OVER (ORDER BY confid) r
  FROM T
) t;

返回与问题中的查询相同的结果。

更新

当有多个具有相同预测(可信)但标签不同的示例时,此 SQL 查询(以及问题中的查询)是不确定的。要使用插值计算确定性 AUC,可以按如下方式修改查询:

SELECT (sum(pos*r) - 0.5*sum(pos)*(sum(pos)+1) - 0.5*sum(pos*neg)) / 
  (sum(pos) * sum(neg)) AS auc
FROM ( 
  SELECT pos, neg, 
    sum(pos+neg) OVER (ORDER BY confid ROWS UNBOUNDED PRECEDING) r
  FROM (
    SELECT confid, sum(label) AS pos, sum(1-label) AS neg
    FROM T
    GROUP BY confid) t
) t;

在AUC公式中,分母是对的总数(正X负)。分子计算有多少对被正确排列。 sum(pos*r) 计算到目前为止的对总数(基于置信度顺序)。该数字包括正 X 正对,因此第二项减去这些。最后,最后一项减去具有相同预测的正 X 负对的一半。

【讨论】:

你能分享一下基本的数学解释吗? 看看这是否有帮助:stephanosterburg.gitbook.io/scrapbook/data-science/…【参考方案3】:

为了计算准确的确定性 AUC 分数,我们应该按“confid”聚合以处理并非所有置信度值都是唯一的情况。然后我们只计算每个唯一置信值的梯形面积并求和。此外,额外检查所有标签为零或一的情况。请注意,类型可能会因为乘法而溢出 - 您可以使用 BIGINT 来防止它。

MS SQL 实现

select
    IIF(SUM(Ones) * SUM(Zeros) <> 0,
    SUM(IIF(Zeros * Ones > 0, 0.5 * Zeros * Ones + Height * Ones, Height * Ones)) / (SUM(Ones) * SUM(Zeros)), 0)
from (
        select
        Zeros,
        Ones,
        SUM(IIF(Zeros * Ones > 0, 0, Zeros) + IIF(PrevZeros * PrevOnes > 0, PrevZeros, 0)) OVER (ORDER BY PD) as Height
    from (
        select
            confid as PD,
            SUM(label) as Ones,
            SUM(ABS(1 - label)) as Zeros,
            LAG(SUM(label), 1, NULL) OVER (ORDER BY confid) as PrevOnes,
            LAG(SUM(ABS(1 - label)), 1, NULL) OVER (ORDER BY confid) as PrevZeros
        from T
        group by confid
    ) q1
) q2;

【讨论】:

以上是关于在 SQL 中计算 AUC的主要内容,如果未能解决你的问题,请参考以下文章

计算AUC的方法以及代码实现

如何在sklearn中计算随机森林模型的AUC?

如何在 keras 中计算接收操作特征 (ROC) 和 AUC?

药物代谢动力学中对数梯形法如何计算AUC

auc计算方法总结

scikit-learn 中决策树中的 AUC 计算