性能度量之Confusion Matrix


例子:一個Binary Classifier

假設我們要預測圖片中的數字是否為數字5。如下面代碼。

X_train為訓練集,每一個instance為一張28*28像素的圖片,共784個features,每個feature代表某個像素的顏色強度(0-255之間)。y_train_5為label, boolean類型的向量。

from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(random_state=42)
sgd_clf.fit(X_train, y_train_5)

784個features:

label,True代表是5,False代表非5.

使用Cross-Validation計算精確度

我們使用sklearn的cross validation,對訓練集進行分層抽樣為3份,每次對不同的抽樣進行評估(訓練則是使用其他另外2份抽樣)。

我們發現,准確率非常高,高的讓人懷疑。 如果圖片中10%都是5的話,那么我們可以自定義一個模型,不用訓練,只是在predict的時候,輸出false,即一直認為所有圖片里的數字都不是5,那么達到的准確率也是90%,如下所示:

所以,從上面的例子說明,評估模型的性能不能單單看准確率,特別是面對傾斜數據(skewed datasets)的時候(某些類別的頻率很高的情況)。

Confusion Matrix

Confusion Matrix背后的思想是計算Class A的實例被歸類為Class B的次數。我們的例子使用的是二元分類(confusion matrix矩陣包含兩行兩列),但是對多元分類同樣適用。

前面,我們使用cross validation計算的是准確性(scoring="accuracy"),為求出confusion matrix,我們需要得到具體的預測值,而不是score="accuracy"。我們通過cross_val_predict求出訓練集的預測值y_train_pred。True, False分別表示判斷出對應的圖片/實例是5后者不是5

然后通過使用confusion_matrix計算出confusion matrix如下。另外,我們還看到,如果將預測值修改為實際值,左下右上的值都為0,下面我們將詳細介紹其含義。

在上面的confusion矩陣中,每行表示真實的分類(actual class),而每列代表預測的分類(predicted class)。第一行全部為非5的圖片(nagative class),第二行全部為5的圖片(positive class)。因為是二元分類,所以矩陣的shape是(2,2)即兩行兩列。第一行中,第一列的值代表54287張圖片被正確地判斷為非5(真陰性,Ture Nagative),第二列的值代表292張圖片被錯誤地判斷為5(假陽性, False Positive)。第二行中,第一列的值代表2514張圖片被錯誤地判斷為非5(False Nagative),第二列的值2907張圖片被正確地判斷為5(True Positive). 所以,完美的分類算法是只有True Natative 和 True Positive的。Confusion Matrix包含的信息很多,我們可以求出精確度:Precision = TP/(TP+FP)。但是僅僅精確度是沒法衡量模型性能的,我們同時也要看reacall:Recall = TP/(TP+FN)。希望下面這張圖能能更清楚地表達Conofusion Matrix。

 

Precision精確度 , Recall(Also sensitivity, TPR-true positive rate) 召回率

我們通過sklearn求出的precision和recall和我們之前得到的confusion matrix一致。precision表示當模型識別一張圖片為5時,正確率在90%以上。但是,它只識別了53%為5的圖片,很差勁對吧?

我們可以將兩者的調和平均數(harmonic mean) F1 score作為單獨的度量來使用。因為當兩者值都高時,F1  score才會高。公式如3-3所示。
 

也有一些時候,我們可能並不關心F1  score(兩者的綜合得分)。可能更關心precision或者更關心recall. 比如,我們需要過濾掉少兒不宜的視頻(識別有害視頻),這個時候,我們應該看重的是precision。(模型寧可把正常的視頻當成有害的,也不能把有害的當成正常的). 再比如,超市的監控系統通過畫面識別偷竊行為,那可能更需要關注recall。(我們寧可多一些誤報,也不想放過真正的小偷造成損失)。不幸的是,我們不能同時提高兩者,增加一個,勢必減小另一個,如同某個算法的空間復雜度和時間復雜度一樣需要平衡。這叫做precision/recall tradeoff。下面我們詳細說明。

Precision / Recall Tradeoff

對於每個實例,模型會根據一個decision function計算出score,凡是score大於某個閾值(threshold),就歸為positive 類,小於則歸為nagative類。此例子中的SDGClassifier使用0作為默認的閾值。下圖中,score從左至右增大。如果我們將閾值設置為綠圈所在值,那么綠圈右邊全被判斷為5,左邊全部被識別成非5. precision=4/(4+5)=80%, recall=4/(4+2)=67%。 如果我們將閾值向右移動到藍圈處(增大閾值),我們計算的precision=3/(3+0)=100%, recall=3/(3+3)=50%。通過增大閾值,我們增大了precision,減小了recall. 同樣,我們如果將閾值移到紅圈的地方(減小閾值),則增大了recall,減小了precision。

sklearn沒有直接設置閾值去predict的方法,不過,我們可以通過decision_function計算出score來調整結果。如下所示,some_digit是某個實際值為5的圖片。

為了設置閾值,我們需要通過cross validation先計算出所有實例的score(而不是預測結果),然后通過sklearn的precision_recall_curve畫出precision和recall隨着不同閾值變化的曲線圖

y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function")
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)

你是否注意到precision的曲線並不像recall那樣平滑,事實上,當增加threshold的時候,precision是不一定增加的,而recall一定不會增加。比如,我們將之前的閾值從綠圈向右移動到綠圈藍圈之間(數字5,6之間),相比綠圈,其precision=3/(3+1)=75%,反而下降了。recall=3/(3+3)=50%,下降屬於正常。這就解釋了為什么precision曲線不一定很平滑。現在,你可以選擇閾值達到precision/recall平衡來適應你的需求了。我們也可以直接畫出兩者的關系,來選擇平衡點。

我們可以看到,precision在80%后,下降的很厲害(recall上升的很厲害),所以,你可能想選擇有一個在大幅度下降之前的值,recall為60% 。 我們可以通過上一張圖確定閾值大概為70000(需要zoom),運行如下代碼得到新的預測值。

y_train_pred_90 = (y_scores > 70000)

驗證precision/recall

 

了解了confusion matrix后,如果某某聲稱其模型的precision很高時,我們應該問模型的recall是多少。因為任何一個很低的時候,模型大多情況下是沒有太大意義的。


免責聲明!

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



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