計算auc-python/awk


1.自己寫的計算auc的代碼,用scikit-learn的auc計算函數sklearn.metrics.auc(xyreorder=False)做了一些測試,結果是一樣的,如有錯誤,歡迎指正。

思路:1.首先對預測值進行排序,排序的方式用了python自帶的函數sorted,詳見注釋。

   2.對所有樣本按照預測值從小到大標記rank,rank其實就是index+1,index是排序后的sorted_pred數組中的索引

   3.將所有正樣本的rank相加,遇到預測值相等的情況,不管樣本的正負性,對rank要取平均值再相加

        4.將rank相加的和減去正樣本排在正樣本之后的情況,再除以總的組合數,得到auc

 
        
 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Wed May  3 10:48:28 2017
 4 
 5 @author: Vincent
 6 """
 7 import numpy as np
 8 from sklearn import metrics
 9 y = np.array(   [1,     0,  0,   1,   1,  1,  0,  1,  1,  1])
10 pred = np.array([0.9, 0.9,0.8, 0.8, 0.7,0.7,0.7,0.6,0.5,0.4])
11 fpr, tpr, thresholds = metrics.roc_curve(y, pred, pos_label=1)
12 print(metrics.auc(fpr, tpr))
13 def getAuc(labels, pred) :
14     '''將pred數組的索引值按照pred[i]的大小正序排序,返回的sorted_pred是一個新的數組,
15        sorted_pred[0]就是pred[i]中值最小的i的值,對於這個例子,sorted_pred[0]=8
16     '''
17     sorted_pred = sorted(range(len(pred)), key = lambda i : pred[i])
18     pos = 0.0 #正樣本個數
19     neg = 0.0 #負樣本個數
20     auc = 0.0 
21     last_pre = pred[sorted_pred[0]]
22     count = 0.0
23     pre_sum = 0.0  #當前位置之前的預測值相等的rank之和,rank是從1開始的,所以在下面的代碼中就是i+1
24     pos_count = 0.0  #記錄預測值相等的樣本中標簽是正的樣本的個數
25     for i in range(len(sorted_pred)) :
26         if labels[sorted_pred[i]] > 0:
27             pos += 1        
28         else:
29             neg += 1       
30         if last_pre != pred[sorted_pred[i]]: #當前的預測概率值與前一個值不相同
31             #對於預測值相等的樣本rank需要取平均值,並且對rank求和
32             auc += pos_count * pre_sum / count  
33             count = 1          
34             pre_sum = i + 1     #更新為當前的rank    
35             last_pre = pred[sorted_pred[i]] 
36             if labels[sorted_pred[i]] > 0:
37                 pos_count = 1   #如果當前樣本是正樣本 ,則置為1
38             else:
39                 pos_count = 0   #反之置為0
40         else:
41             pre_sum += i + 1    #記錄rank的和
42             count += 1          #記錄rank和對應的樣本數,pre_sum / count就是平均值了
43             if labels[sorted_pred[i]] > 0:#如果是正樣本
44                 pos_count += 1  #正樣本數加1
45     auc += pos_count * pre_sum / count #加上最后一個預測值相同的樣本組
46     auc -= pos *(pos + 1) / 2 #減去正樣本在正樣本之前的情況
47     auc = auc / (pos * neg)  #除以總的組合數
48     return auc
49 print(getAuc(y, pred))

 2.awk代碼

 1 #計算auc,輸入分別為預測值(可以乘以一個倍數之后轉化為整數),該相同預測值的樣本個數,該相同預測值的正樣本個數
 2 sort -t $'\t' -k 1,1n | awk -F"\t" 'BEGIN{
 3     OFS="\t";
 4     now_q="";
 5     begin_rank=1;
 6     now_pos_num=0;
 7     now_neg_num=0;
 8     total_pos_rank=0;
 9     total_pos_num=0;
10     total_neg_num=0;
11 }function clear(){
12     begin_rank += now_pos_num + now_neg_num;
13     now_pos_num=0;
14     now_neg_num=0;
15 }function update(){
16     now_pos_num += pos_num;
17     now_neg_num += neg_num;
18 }function output(){
19     n = now_pos_num + now_neg_num;
20     avg_rank = begin_rank + (n-1)/2;
21     tmp_all_pos_rank = avg_rank * now_pos_num;
22     total_pos_rank += tmp_all_pos_rank;
23     total_pos_num += now_pos_num;
24     total_neg_num += now_neg_num;
25 }{
26     q=$1;
27     show=$2;
28     clk=$3;
29     pos_num=clk;
30     neg_num=show-clk;
31     if(now_q!=q){
32         if(now_q!=""){
33             output();
34             clear();
35         }
36         now_q=q;
37     }
38     update();
39 
40 }END{
41     output();
42     auc=0;
43     m=total_pos_num;
44        n=total_neg_num;
45     if(m>0 && n>0){
46         auc = (total_pos_rank-m*(m+1)/2) / (m*n);
47     }
48     print auc;
49 }'

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM