評價指標AUC 原理及實踐
-
- 對CTR問題的理解:
- 分類角度
- 點擊和未點擊作爲兩種類別
- loss:LogLoss
- 迴歸角度
- 將點擊和未點擊作爲迴歸的值
- loss:MSE
- 一般在估計時都是得到一個[0,1]的概率值,代表點擊的可能性大小
- 最常用的評價指標還是 AUC
- 分類角度
- 1、二分類評估指標
- 1.1 混淆矩陣
- 1.1 混淆矩陣
- 對CTR問題的理解:
真實\預測 |
Positive |
Negative |
Positive |
TP |
FN |
Negative |
FP |
TN |
-
-
-
- TP:樣本爲正,預測結果爲正
-
-
FN:樣本爲正,預測結果爲負 (False Negative 錯誤的負預測)
FP:樣本爲負,預測結果爲正 (False Positive 錯誤的正預測)
TN:樣本爲負,複測結果爲負
-
- TP和TN是預測正確的,數量越大越好;FN和FP是預測錯誤的,數量越小越好
-
- 1.2 準確率 Accuracy
- 分類正確的樣本數佔總樣本數的比例
- 1.3 精確率 Precision 和召回率 Recall
- Precision:表示預測結果中,預測爲正樣本的樣本中,正確預測的概率
- Recall:表示在原始樣本的正樣本中,最後被正確預測的概率
- Precision 和 Recall 通常是一對矛盾的指標
- Precision:表示預測結果中,預測爲正樣本的樣本中,正確預測的概率
- 1.4 F-1 Score
- 爲了折中 Precision 和 Recall ,引入F1值
- 1.5 ROC 與 AUC
- 在分類器中,產生的是一個概率預測值,將其與一個設置好的分類閾值進行比較。
- 1.2 準確率 Accuracy
如果重視精確率可以將閾值設置高;如果重視召回率,可以將閾值設置低
-
- ROC 受試者工作特徵 Receiver Operating Characteristic
- 將預測結果進行排序,逐個把樣本作正例進行預測,每次計算出假正例率 FPR 和 真正例率 TPR,將它們作爲橫縱座標作圖,得到 ROC 曲線
- 假正例率 False Positive Rate FPR
- 預測爲正樣本但是預測錯了的可能性,越小越好
- 真正例率 True Positive Rate TPR
- 預測爲正樣本且預測對了的可能性,越大越好
- ROC計算過程
- ROC 受試者工作特徵 Receiver Operating Characteristic
1)首先每個樣本都需要有一個label值,並且還需要一個預測的score值(取值0到1);
2)然後按這個score對樣本由大到小進行排序,假設這些數據位於表格中的一列,從上到下依次降序;
3)現在從上到下按照樣本點的取值進行劃分,位於分界點上面的我們把它歸爲預測爲正樣本,位於分界點下面的歸爲負樣本;
4)分別計算出此時的TPR和FPR,然後在圖中繪製(FPR, TPR)點。
-
- AUC Area Under the Curve
- 即ROC 曲線下方的面積
- AUC 量化了 ROC 曲線表達的分類能力;分類能力越好,AUC越大,輸出概率越合理,排序的結果越合理
- 2.AUC的計算
- 等價於 Wilcoxon-Mean-Witney Test
- 測試任意給一個正類樣本和一個負類樣本,正類樣本的score有多大的概率大於負類樣本的score。
- 複雜度O(n^2), n = M+N
- 化簡
- 首先對score從大到小排序,然後令最大score對應的sample的rank值爲n,第二大score對應sample的rank值爲n-1,以此類推從n到1。
- 然後把所有的正類樣本的rank相加,再減去正類樣本的score爲最小的那M個值的情況。
- 得到的結果就是有多少對正類樣本的score值大於負類樣本的score值,最後再除以M×N即可。
- 當存在score相等的時候,對於score相等的樣本,需要賦予相同的rank值(無論這個相等的score是出現在同類樣本還是不同類的樣本之間,都需要這樣處理)。具體操作就是再把所有這些score相等的樣本 的rank取平均。然後再使用上述公式
- 等價於 Wilcoxon-Mean-Witney Test
- 3. AUC計算代碼
- AUC Area Under the Curve
import numpy as np
# 隨機生成0或1 的10*1
label_all = np.random.randint(0,2,[10,1]).tolist()
# 隨機生成0~1 的10*1
pred_all = np.random.random((10,1)).tolist()
print(label_all)
print(pred_all)
# 正例數量
posNum = len(list(filter(lambda s:s[0] == 1,label_all)))
if (posNum > 0):
negNum = len(label_all) - posNum
sortedq = sorted(enumerate(pred_all),key=lambda x:x[1])
posRankSum = 0
for j in range(len(pred_all)):
if (label_all[j][0] == 1):
posRankSum += list(map(lambda x:x[0],sortedq)).index(j) + 1
auc = (posRankSum - posNum * (posNum + 1) / 2 ) / (posNum * negNum)
print("auc:",auc)