AUC的全名是Area Under Curve,就是ROC曲线下的面积。因此,在介绍AUC之前,先介绍下ROC。
ROC
ROC的全称是”受试者工作特征“(Receiver Operating Characteristic)曲线。要了解ROC,需要先了解混淆矩阵。
混淆矩阵
对于二分类问题,可以把样例根据其真实类别与模型预测的类别的组合,划分为如下几种:
- 真正例:真实值是positive,模型认为是positive的数量(True Positive=TP)
- 假负例:真实值是positive,模型认为是negative的数量(False Negative=FN)
- 假正例:真实值是negative,模型认为是positive的数量(False Positive=FP)
- 真负例:真实值是negative,模型认为是negative的数量(True Negative=TN)
将这四个指标一起呈现在表格中,就能得到如下这样一个矩阵,我们称它为混淆矩阵
真实情况 | 预测结果 | |
正例(Positive) | 负例(Negative) | |
正例(Positive) | TP(真正例) | FN(假负例) |
负例(Negative) | FP(假正例) | TN(真负例) |
ROC曲线
先了解两个指标:
- 真正例率(True Positive Rate,简称TPR):表示当前预测为正样本的数据中,真实的正样本占所有正样本的比例
TPR = TP / (TP + FN)
- 假正例率(False Positive Rate,简称FPR):表示当前被分到正样本的数据中,真实的负样本占所有负样本的比例。
FPR = FP / (TN + FP)
我们根据模型的预测结果对样本进行排序,按顺序逐个把样本作为正样本进行预测,每次计算出TPR和FPT,分别以FPR为横坐标、以TPR为纵坐标作图,就得到了ROC曲线。ROC曲线示意图如下:
如何画ROC曲线
画ROC曲线,在西瓜书上有描述,摘抄如下:
给定P个正例和N个负例,根据模型的预测结果(比如,对二分类来说,预测样本为正例的概率)对样本进行排序,然后把分类阈值设为最大,即把所有样本都预测为负例,此时TPR和FPR都是0,在坐标(0,0)处标记一个点。然后,将分类阈值依次设置为每个样本的预测值,即依次将每个样本划分为正例。设前一个标记点坐标为(x,y),当前若为真正例,则对应标记点的坐标为(x,y + 1/P);当前若为假正例,则对应的标记点的坐标为(x + 1/N,y),然后用线段连接相邻点即可画出ROC曲线。
这种方法得到的ROC曲线是一个一个的小矩形堆积起来的。
以上方法,可能有个假设,模型为每个样本预测的分数都不同,实际可能的情况是,对不同的样本,模型预测的分数都一样。也就是说,一个分数对应多个样本,则此时标记点应该是(x + neg_num/N, y + pos_num/P)。
画ROC曲线,可能下面的方法更合适:
1. 统计正样本、负样本个数
2. 根据模型预测分数,对样本进行排序
3. 对每个分数,分别计算TPR、FPR。根据TPR及FPR公式,TPR = 当前累积正样本数 / 总正样本数,FPR = 当前累积负样本数 / 总负样本数
4. 根据坐标点,画出ROC曲线
假如数据输入为:正样本数、负样本数、模型打分,数据以 \t 分割
程序如下:
import sys
import numpy as np
import matplotlib.pyplot as plt
db = [] #[score,nonclk,clk]
pos, neg = 0, 0
with open(sys.argv[1], 'r') as fs:
for line in fs:
clk, nonclk, score = line.strip().split('\t')
clk = int(clk)
nonclk = int(nonclk)
score = float(score)
db.append([score, nonclk, clk])
pos += clk
neg += nonclk
db = sorted(db, key=lambda x:x[0], reverse=True)
xy_a