模型评估&AUC

来源:互联网 发布:服装淘宝产品验收标准 编辑:程序博客网 时间:2024/05/24 06:09

 在机器学习中评判一个模型好坏的标准有很多,常用的有准确率、召回率、AUC等。本文介绍下AUC及其计算方式。

AUC常用来评估一个二元分类模型,二元分类模型通常有4中预测结局,以是否患高血压为例:

  1. 真阳性(TP):诊断为有实际上也有高血压。
  2. 伪阳性(FP):诊断为有实际却没有高血压。
  3. 真阴性(TN):诊断为没有实际上也没有高血压。
  4. 伪阴性(FN):诊断为没有实际却有高血压。

我们可以得到一个TPR = TP / (TP + FN)            FPR = FP / (FP + TN)

 如果我们去很多不同的阈值就可以得到一系列的(FPR, TPR)点,这些点可以拟合成一条曲线,我们称之为ROC(Receiver Operating Characteristic);该曲线下方与横轴之间的面积大小即为AUC。因此,我们计算AUC的方式如下:

 

#!/usr/bin/pythonimport sysdef get_auc(arr_score, arr_label, pos_label):    score_label_list = []    for index in xrange(len(arr_score)):        score_label_list.append((float(arr_score[index]), int(arr_label[index])))    score_label_list_sorted = sorted(score_label_list, key = lambda line:line[0], reverse = True)    fp, tp = 0, 0    lastfp, lasttp = 0, 0    A = 0    lastscore = None    for score_label in score_label_list_sorted:        score, label = score_label[:2]        if score != lastscore:            A += trapezoid_area(fp, lastfp, tp, lasttp)            lastscore = score            lastfp, lasttp = fp, tp        if label == pos_label:            tp += 1        else:            fp += 1    A += trapezoid_area(fp, lastfp, tp, lasttp)    A /= (fp * tp)    return Adef trapezoid_area(x1, x2, y1, y2):    delta = abs(x2 - x1)    return delta * 0.5 * (y1 + y2)if __name__ == "__main__":    if len(sys.argv) != 2:        print "Error!\n%s pred_model_file"        sys.exit(-1)    arr_score, arr_label = [], []    for line in file(sys.argv[1]):        line = line.strip().split('\t')        if len(line) < 2 : continue        arr_score.append(line[0])        arr_label.append(line[1])    print arr_score;print arr_label;    print "AUC = %s" % get_auc(arr_score, arr_label, 2)


 

F:\python_workspace\offline_evaluation>python model_evaluation.py pred_model_file.txt['0.1', '0.4', '0.35', '0.8']['1', '1', '2', '2']AUC = 0.75


采用sklearn里的代码也可以得到AUC值,http://scikit-learn.org/stable/modules/generated/sklearn.metrics.auc.html#sklearn.metrics.auc

>>> import numpy as np>>> from sklearn import metrics>>> y = np.array([1, 1, 2, 2])>>> pred = np.array([0.1, 0.4, 0.35, 0.8])>>> fpr, tpr, thresholds = metrics.roc_curve(y, pred, pos_label=2)>>> metrics.auc(fpr, tpr)0.75

 

换个例子:

F:\python_workspace\offline_evaluation>python model_evaluation.py tmp.txt['0.1', '0.2', '0.4', '0.5', '0.35', '0.8', '0.9', '0.95']['1', '2', '1', '1', '2', '2', '2', '1']AUC = 0.5

 

>>> import numpy as np>>> from sklearn import metrics>>> y = np.array([1,2,1,1,2,2,2,1])>>> pred = np.array([0.1,0.2,0.4,0.5,0.35,0.8,0.9,0.95])>>> fpr, tpr, ths = metrics.roc_curve(y, pred, pos_label=2)>>> metrics.auc(fpr,tpr)0.5


 

 

从以上2个例子中可以看到与之前自己写的代码得到的AUC值一样!

 

从网上看到另外一种求解AUC的方法:

一个关于AUC的很有趣的性质是,它和Wilcoxon-Mann-Witney Test是等价的。这个等价关系的证明留在下篇帖子中给出。而Wilcoxon-Mann-Witney Test就是测试任意给一个正类样本和一个负类样本,正类样本的score有多大的概率大于负类样本的score。有了这个定义,我们就得到了另外一中计 算AUC的办法:得到这个概率。我们知道,在有限样本中我们常用的得到概率的办法就是通过频率来估计之。这种估计随着样本规模的扩大而逐渐逼近真实值。这 和上面的方法中,样本数越多,计算的AUC越准确类似,也和计算积分的时候,小区间划分的越细,计算的越准确是同样的道理。具体来说就是统计一下所有的 M×N(M为正类样本的数目,N为负类样本的数目)个正负样本对中,有多少个组中的正样本的score大于负样本的score

按照上面描述的方法,有如下代码:

getAUC2.py

#!/usr/bin/python  import sysdef get_auc(arr_score, arr_label, pos_label):    pos_cnt, neg_cnt , pos_gt_neg_cnt = 0, 0, 0    score_label_list = []    for index in xrange(len(arr_score)):        label = int(arr_label[index])        if label == pos_label : pos_cnt += 1        else : neg_cnt += 1        score_label_list.append((float(arr_score[index]), label))    score_label_list_sorted = sorted(score_label_list, key = lambda line:line[0], reverse = True)    rankvalue = neg_cnt    for score_label in score_label_list_sorted:        score, label = score_label[:2]        if label == pos_label :            pos_gt_neg_cnt += rankvalue        else :            rankvalue -= 1    return 1.0 * pos_gt_neg_cnt / (pos_cnt * neg_cnt)if __name__ == "__main__":    if len(sys.argv) != 2:        print "Error!\n%s pred_model_file"        sys.exit(-1)    arr_score, arr_label = [], []    for line in file(sys.argv[1]):        line = line.strip().split('\t')        if len(line) < 2 : continue        arr_score.append(line[0])        arr_label.append(line[1])    #print arr_score;print arr_label;      print "AUC = %s" % get_auc(arr_score, arr_label, 1)


下面拿实际应用中一个例子说明两种方式的求解:

第一种按小梯形求解面积的方法,代码文件命名为getAUC1.py, 其中最后一行代码修改为  print "AUC = %s" % get_auc(arr_score, arr_label, 1)

模型文件pred_model_file.txt放在  http://download.csdn.net/detail/lming_08/8607345

[lming_08]$ ./getAUC1.py pred_model_file.txt  AUC = 0.867382336327[lming_08]$ ./getAUC2.py pred_model_file.txt AUC = 0.867735229461
可以看到两种方式求解结果几乎一致。


参考链接:http://taoo.iteye.com/blog/760589 


0 0
原创粉丝点击