AUC曲线计算方法及代码实现

参考:AUC计算方法总结 - 白开水加糖 - 博客园

AUC计算  

1. 根据定义Aera Under Curve,计算面积。样本有限,所以得到的AUC曲线一般是个阶梯状,所以计算这些阶梯的面积即可。先按score排个序,然后从头遍历一遍,把每个score作为划分阈值,可以得到对应的TPR和FPR,计算出底下的面积。更直观的计算方法,参考《百面机器学习》:

这种直接计算面积的方法比较麻烦,一般使用下面的等价方法进行计算。

2. AUC等价于:测试任意给一个正类样本和一个负类样本,正类样本的score有多大的概率大于负类样本的score。所以可以计算这个概率。具体来说就是统计一下所有的 M×N(M为正类样本的数目,N为负类样本的数目)个正负样本对中,有多少个组中的正样本的score大于负样本的score。当二元组中正负样本的 score相等的时候,按照0.5计算。然后除以MN。实现这个方法的复杂度为O(n^2)。n为样本数(即n=M+N)
3.  第三种方法实际上和上述第二种方法是一样的,但是复杂度减小了。它也是首先对score从大到小排序,然后令最大score对应的sample 的rank为n,第二大score对应sample的rank为n-1,以此类推。然后把所有的正类样本的rank相加,再减去M-1种两个正样本组合的情况。得到的就是所有的样本中有多少对正类样本的score大于负类样本的score。然后再除以M×N。即 

 公式解释:

        1、为了求的组合中正样本的score值大于负样本,如果所有的正样本score值都是大于负样本的,那么第一位与任意的进行组合score值都要大,我们取它的rank值为n,但是n-1中有M-1是正样例和正样例的组合这种是不在统计范围内的(为计算方便我们取n组,相应的不符合的有M个),所以要减掉,那么同理排在第二位的n-1,会有M-1个是不满足的,依次类推,故得到后面的公式M*(M+1)/2,我们可以验证在正样本score都大于负样本的假设下,AUC的值为1

      2、根据上面的解释,不难得出,rank的值代表的是能够产生score前大后小的这样的组合数,但是这里包含了(正,正)的情况,所以要减去这样的组(即排在它后面正例的个数),即可得到上面的公式

      另外,特别需要注意的是,再存在score相等的情况时,对相等score的样本,需要 赋予相同的rank(无论这个相等的score是出现在同类样本还是不同类的样本之间,都需要这样处理)。具体操作就是再把所有这些score相等的样本 的rank取平均。然后再使用上述公式。(以下代码中未对rank求平均,但结果与sklearn中的auc计算基本一致)

import numpy as np
from sklearn.metrics import roc_auc_score


def calc_auc(y_labels, y_scores):
    f = list(zip(y_scores, y_labels))
    rank = [values2 for values1, values2 in sorted(f, key=lambda x:x[0])]
    rankList = [i+1 for i in range(len(rank)) if rank[i] == 1]
    pos_cnt = np.sum(y_labels == 1)
    neg_cnt = np.sum(y_labels == 0)
    auc = (np.sum(rankList) - pos_cnt*(pos_cnt+1)/2) / (pos_cnt*neg_cnt)
    print(auc)


def get_score():
    # 随机生成100组label和score
    y_labels = np.zeros(100)
    y_scores = np.zeros(100)
    for i in range(100):
        y_labels[i] = np.random.choice([0, 1])
        y_scores[i] = np.random.random()
    return y_labels, y_scores


if __name__ == '__main__':
    y_labels, y_scores = get_score()
    # 调用sklearn中的方法计算AUC,与后面自己写的方法作对比
    print('sklearn AUC:', roc_auc_score(y_labels, y_scores))
    calc_auc(y_labels, y_scores)

note:以上代码,没有考虑正负样本score相等的情况,相等时应该按0.5计算

  • 一种解决方案:在计算时,先将[score, label]按[升序,升序]排序,计算auc1;再按[升序, 降序]排序,计算auc2。最终auc = (auc1 + auc2) / 2
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要绘制多分类的AUC曲线,可以使用Micro和Macro两种方法。下面是一个示例代码,使用Python的sklearn库和matplotlib库来绘制多分类AUC曲线: ```python from sklearn.metrics import roc_auc_score, roc_curve from sklearn.preprocessing import LabelBinarizer import matplotlib.pyplot as plt import numpy as np # 假设有3个类别,分别为0、1、2 y_true = np.array([0, 1, 2, 1, 2]) y_pred = np.array([[0.2, 0.6, 0.2], [0.8, 0.1, 0.1], [0.3, 0.4, 0.3], [0.4, 0.3, 0.3], [0.1, 0.2, 0.7]]) # 将真实标签进行二值化处理 lb = LabelBinarizer() lb.fit(y_true) y_true_bin = lb.transform(y_true) # 计每个类别的AUCauc_scores = [] fpr = dict() tpr = dict() for i in range(len(lb.classes_)): fpr[i], tpr[i], _ = roc_curve(y_true_bin[:, i], y_pred[:, i]) auc = roc_auc_score(y_true_bin[:, i], y_pred[:, i]) auc_scores.append(auc) # 计Macro平均AUC值 mean_auc_macro = np.mean(auc_scores) # 计Micro平均AUC值 fpr["micro"], tpr["micro"], _ = roc_curve(y_true_bin.ravel(), y_pred.ravel()) auc_micro = roc_auc_score(y_true_bin, y_pred, average="micro") # 绘制AUC曲线 plt.figure(figsize=(8, 6)) plt.plot(fpr["micro"], tpr["micro"], label='Micro-average ROC curve (area = {0:0.2f})'.format(auc_micro), color='deeppink', linestyle=':', linewidth=4) for i in range(len(lb.classes_)): plt.plot(fpr[i], tpr[i], label='ROC curve of class {0} (area = {1:0.2f})'.format(i, auc_scores[i])) plt.plot([0, 1], [0, 1], 'k--', linewidth=2) plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('Receiver Operating Characteristic (ROC)') plt.legend(loc="lower right") plt.show() ``` 这段代码首先导入了需要的库,然后定义了一个示例的真实标签和预测概率矩阵。接着,使用`LabelBinarizer`将真实标签进行二值化处理,并计每个类别的AUC值以及Micro和Macro平均AUC值。最后,使用matplotlib库绘制AUC曲线,其中包括Micro-average曲线和每个类别的曲线

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值