问题描述
我正尝试使用MysqL为下表中的数据计算AUC:
y p
1 0.872637
0 0.130633
0 0.098054
...
...
1 0.060190
0 0.110938
我遇到了以下给出正确AUC分数的SQL查询(我使用sklearn方法进行了验证)。
SELECT (sum(y*r) - 0.5*sum(y)*(sum(y)+1)) / (sum(y) * sum(1-y)) AS auc
FROM (
SELECT y,row_number() OVER (ORDER BY p) r
FROM probs
) t
Using pandas this can be done as follows:
temp = df.sort_values(by="p")
temp['r'] = np.arange(1,len(df)+1,1)
temp['yr'] = temp['y']*temp['r']
print( (sum(temp.yr) - 0.5*sum(temp.y)*(sum(temp.y)+1)) / (sum(temp.y) * sum(1-temp.y)) )
我不明白我们如何使用这种方法来计算AUC。 有人可以提供直观的解释吗?
我已经很熟悉梯形法,它涉及将ROC曲线下的小梯形面积相加。
解决方法
简短答案:这是Wilcoxon-Mann-Whitney统计信息,请参见 https://en.wikipedia.org/wiki/Receiver_operating_characteristic#Area_under_the_curve 该页面也有证明。
公式的底部与Wiki中的公式相同。顶部比较棘手。 Wiki中的f
对应于您数据中的p
,而t_0
和t_1
是数据框中的索引。请注意,我们首先按p
进行排序,这使我们的生活更轻松。
请注意,两倍总和可能会分解为
Sum_{t_1 such that y(t_1)=1} #{t_0 such that p(t_0) < p(t_1) and y(t_0)=0}
#
代表此类索引的总数。
对于每个行索引t_1
(例如y(t_1) =1
),t_0
和p(t_0) < p(t_1)
有多少y(t_0)=0
?我们知道t_1
的确切p
个值小于或等于t_1
,因为值是经过排序的。我们得出结论
#{t_0: p(t_0) < p(t_1) and y(t_0)=1) = t_1 - #{t_0: t_0 <= t_1 and y(t_0)=1}
现在想象一下向下滚动排序的数据框。第一次遇到y=1
,#{t_0: t_0 <= t_1 and y(t_0)=1}=1
,第二次遇到y=1
,相同数量是2,第三次遇到y=1
,数量是3,依此类推。因此,当我们将t_1
上所有索引y=1
的相等性求和时,我们得到
Sum_{t_1: y(t_1)=1}#{t_0: p(t_0) < p(t_1) and y(t_0)=1) = Sum_{t_1: y(t_1)=1} t_1 - (1 + 2 + 3 + ... + n),
其中n
是y
列中的总数。现在,我们需要进一步简化。请注意
Sum_{t_1: y(t_1)=1} t_1 = Sum_{t_1: y(t_1)=1} t_1 y(t_1)
如果y(t_1)
不为1,则为零。因此,
Sum_{t_1: y(t_1)=1} t_1 = Sum_{t_1: y(t_1)=1} t_1 y(t_1) = Sum_{t} t y(t)
将其放在我们的公式中并使用
1 + 2+ 3 + ... + n = n(n+1)/2
完成了找到的公式的证明。
P.S。我认为将这个问题发布在数学或统计数据溢出方面会更有意义。