37e85415c66895376be31efda093b86a.png

在平时计算auc的时候,大都是使用 sklearn.metrics.roc_auc_score 来计算。一般操作是将每个batch预测出来的结果 拼接起来,然后扔到该函数中计算。

但是如果测试集量级过大(比如 10亿量级),每个样本的预测结果拼接起来之后至少需要 3G内存。这个开销显然不是我们想要的。有什么方法可以不用拼接batch预测出来的结果就可以计算auc呢?

回想auc的概率含义:从正例采出一个样本,从负例采出一个样本,这两个样本的模型预测值,正例排在负例前面的概率。对应下面这个公式

一个比较简单的方法,我们对连续的score进行分桶,然后统计 每个桶里的 正负例 数量,经过计算就可以得到auc。这个方法的好处是,因为只需要统计 每个桶里的正负例数量,所以就不用保存每个样本的预测值。很适合 样本量级很大的 auc计算。python代码如下(翻译自paddlepaddle计算auc的代码~)。

import numpy as np
import sklearn.metrics as sklearn_metrics


class Auc(object):
    def __init__(self, num_buckets):
        self._num_buckets = num_buckets
        self._table = np.zeros(shape=[2, self._num_buckets])

    def Reset(self):
        self._table = np.zeros(shape=[2, self._num_buckets])

    def Update(self, labels: np.ndarray, predicts: np.ndarray):
        """
        :param labels: 1-D ndarray
        :param predicts: 1-D ndarray
        :return: None
        """
        labels = labels.astype(np.int)
        predicts = self._num_buckets * predicts

        buckets = np.round(predicts).astype(np.int)
        buckets = np.where(buckets < self._num_buckets,
                           buckets, self._num_buckets-1)

        for i in range(len(labels)):
            self._table[labels[i], buckets[i]] += 1

    def Compute(self):
        tn = 0
        tp = 0
        area = 0
        for i in range(self._num_buckets):
            new_tn = tn + self._table[0, i]
            new_tp = tp + self._table[1, i]
            # self._table[1, i] * tn + self._table[1, i]*self._table[0, i] / 2
            area += (new_tp - tp) * (tn + new_tn) / 2
            tn = new_tn
            tp = new_tp
        if tp < 1e-3 or tn < 1e-3:
            return -0.5  # 样本全正例,或全负例
        return area / (tn * tp)


if __name__ == '__main__':
    label = np.random.randint(low=0, high=2, size=[1000])
    predict = np.random.uniform(0, 1, size=[1000])
    auc = Auc(num_buckets=102400)
    auc.Update(label, predict)
    print(auc.Compute())
    print(sklearn_metrics.roc_auc_score(label, predict))

参考资料

https://github.com/PaddlePaddle/Paddle/blob/v1.8.5/paddle/fluid/framework/fleet/box_wrapper.h#L51

https://github.com/PaddlePaddle/Paddle/blob/v1.8.5/paddle/fluid/framework/fleet/box_wrapper.cc#L32

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐