AUC及TensorFlow AUC計算相關

2021-08-25 05:52:26 字數 3606 閱讀 7345

最近在打天池的比賽,裡面需要用auc來評測模型的效能,所以這裡介紹一下auc的相關概念,並介紹tensorflow含有的函式來計算auc。

先介紹一些前置的概念。在乙個二分類問題中,如果本身是正例(positive),**正確也**成正例,則稱為真正例(true positive),簡稱tp,而**錯誤**成了反例,則稱為假反例(false negative),簡稱fn,如果本身是反例(negative),**正確也**成反例,則稱為真反例(true negative),簡稱tn,而**錯誤**成了正例,則稱為假正例(false positive),簡稱fp。查準率、查全率以及f1值都是根據上述四個值計算出來的,這裡不做贅述。

真正例率(true positive rate,簡稱tpr),計算公式為tpr = tp / (tp + fn),和查全率的公式一致,表示**為正例且本身是正例的樣本數佔所有本身是正例的樣本數的比重。假正例率(false positive rate,簡稱fpr),計算公式為fpr = fp / (tn + fp),表示**為正例且本身是反例的樣本數佔所有本身是反例的樣本數的比重。

roc全稱是受訪者工作特徵(receiver operating characteristic)曲線,用來研究一般情況下模型的泛化效能。先根據模型的**結果將樣本進行排序,將最可能是正例,也就是**出是正例的概率最高的樣本排在前面,然後概率依次降低,將最不可能是正例也就是**時正例概率最低的樣本排在最後。然後roc曲線以真正例率作為縱軸,假正例率作為橫軸,按順序逐個把樣本**成正例,在每個樣本**後tpr、fpr的值都會改變,就在影象上增加乙個新的點,直到所有點都**為正例為止。可以考慮一種極端情況作為例子,如果模型非常完美,泛化效能很好,則在排序後前面的全是**正例實際上也是正例,後面的全是反例,實際上也是反例。一開始將所有樣本都**為反例,此時tp和fp都是0,所以曲線從原點(0,0)開始,將第乙個樣本**為正例,此時它本身是正例,**也是正例,所以tp為1,tpr此時為1/正例樣本數,而fp還是為0,所以曲線下乙個點沿y軸向上。以此類推,一直**到最後乙個正例,此時tp為正例樣本數,tpr為1,所以曲線延伸到了(0,1),然後將第乙個反例**成了正例,此時tp值不變,fp變為1,fpr此時為1/反例樣本數,所以曲線在y值仍然為1的情況下沿x軸正方向增加乙個點進行延伸,以此類推一直到把所有的反例都**正正例,此時fp為反例樣本數,fpr值也為1。上面的例子是乙個完美的模型,而如果有**錯誤的,即按順序**將所有的正例**為正例前遇到了 反例**為正例,則fp值會增加,此時仍有正例沒有被**為正例,所以tp不為1,而fp會變為1,即曲線沒有達到(0,1)點後就會向右延伸。下圖為乙個roc曲線的例項。

而直接對比兩個交叉的roc曲線,仍然無法很好地評測模型的效能,所以用曲線下的面積來代表模型的效能,也就是本文要介紹的auc(area under roc curve)。從上文完美模型的例子可知,auc的面積上限為1。隨機猜測時auc的值即為0.5,所以在深度學習中一般模型的auc都會大於0.5,如果模型的值遠遠小於0.5,可能是你的標籤弄反了,我在天池乙個比賽中,一開始auc只有0.24,比胡亂猜測的0.5都要低,一開始百思不得其解,後來發現題目要求上傳的是反例的概率,我上傳的是正例的概率,所以實際上我模型的auc是0.76,這點要注意。

由於我的模型是用tensorflow **生成的,所以auc也自然使用tensorflow提供的函式來計算。網上很多的資料是用用tf.contrib.metrics.streaming_auc這個函式來計算的,但訪問官方文件會提示該函式已經棄用,在未來版本會刪去,應該使用tf.metrics.auc函式,函式體如下:

tf.metrics.auc(

labels,

predictions,

weights=none,

num_thresholds=200,

metrics_collections=none,

updates_collections=none,

curve='roc',

name=none,

summation_method='trapezoidal'

)

args:

returns:

即最簡單的使用方法是直接傳兩個引數labels和predictions,也就是樣本的標籤和**的概率,會得到返回的auc的值,num_thresholds的值預設為200,而越大auc的值會越精確,一直到你的樣本數量為止,之後再增大不會改變,所以樣本數大於200需要對num_thresholds進行傳參。但是實際使用上會遇到一些問題。首先,在寫好該公式,在已經執行過sess.run(tf.global_variables_initializer())後進行sess.run該auc,會提示下列錯誤:

failedpreconditionerror (see above for traceback): attempting to use uninitialized value auc/true_negatives

sess.run(tf.local_variables_initializer()) 或 sess.run(tf.initialize_local_variables())
第二種方式執行時會建議你使用第一種。

這樣編碼後程式能順利執行不報錯,但這樣執行後的auc的值始終是0.0,怎麼調整引數都沒有用,我一度懷疑是**的問題,後來在stackoverflow,發現在sess.run(auc_value)以前,由於tf.metrics.auc會返回兩個引數,第乙個引數auc_value是auc的值,第二個引數auc_op是auc的更新操作,要先執行sess.run(auc_op)後再執行計算auc的值,才會正確顯示auc的值。我的**例子如下: 

prediction_tensor = tf.convert_to_tensor(prediction_list)

label_tensor = tf.convert_to_tensor(label_list)

auc_value, auc_op = tf.metrics.auc(label_tensor, prediction_tensor, num_thresholds=2000)

sess.run(tf.global_variables_initializer())

sess.run(tf.local_variables_initializer())

sess.run(auc_op)

value = sess.run(auc_value)

print(prediction_tensor)

print(label_tensor)

print("auc:" + str(value))

其中prediction_list和label_list都是python list型別,prediction_list每個元素都是0~1的概率值,label_list每個元素的值都是true或false,轉化為tensor後即可計算對應的auc,執行結果如下。

tensor("const:0", shape=(1544,), dtype=float32)

tensor("const_1:0", shape=(1544,), dtype=bool)

auc:0.97267157

這樣就能成功執行並顯示auc了。

ROC曲線及AUC評價指標

很多時候,我們希望對乙個二值分類器的效能進行評價,auc正是這樣一種用來度量分類模型好壞的乙個標準。現實中樣本在不同類別上的不均衡分布 class distribution imbalance problem 使得accuracy這樣的傳統的度量標準不能恰當的反應分類器的效能。舉個例子 測試樣本中有...

auc計算公式 AUC與logloss

在ctr預估中,auc area under curve 用於衡量排序能力,auc值為roc曲線下的面積,是乙個概率值,越大越好。簡單來說這個指標的含義其實就是隨機抽出一對樣本 乙個正樣本,乙個負樣本 然後用訓練得到的分類器來對這兩個樣本進行 得到正樣本的概率大於負樣本概率的概率。auc是乙個二分類...

AUC如何計算

auc area under curve 是機器學習二分類模型中非常常用的評估指標,相比於f1 score對專案的不平衡有更大的容忍性,目前常見的機器學習庫中 比如scikit learn 一般也都是整合該指標的計算,但是有時候模型是單獨的或者自己編寫的,此時想要評估訓練模型的好壞就得自己搞乙個au...