最近在做一個multilabel classification(多標簽分類)的項目,需要一些特定的metrics去評判一個multilabel classifier的優劣。這里對用到的三個metrics做一個總結。
首先明確一下多標簽(multilabel)分類和多類別(multiclass)分類的不同:multiclass僅僅表示輸出的類別大於2個,這樣可以和一般的二分類(binary)區別開,但每一個輸入x僅僅對應一個輸出標簽。而multilabel里的每一個輸入可以對應多個輸出標簽。舉個例子,對動物圖片進行分類,一個輸入(某一動物)只可能有一個輸出(貓or狗),因為一個動物不可能同時是貓還有狗,這就是multiclass;但對新聞進行分類,一個輸入(某一新聞)可以對應多個輸出(海外,體育),這就是multilabel。
這次用到的數據集是MS-COCO 2014年的數據集,它的testset里有40504張圖片,因為MS-COCO主要是用來做目標檢測(detection)或者物體分割的(segmentation),每張圖片里包含了多個物體。我們就用這些物體為圖片的對應標簽來做multilabel分類。一共有80個可能出現在圖片里的物體,所以每張圖片對應一個(80x1)的標簽向量,被分到類的物體對應的標量為1,沒有分到類的為0(只要圖片中出現了某物體,此圖片就被分到對應的物體類里,然后一張圖片會有多個類別因為大多圖片都包含了幾個物體)。
N表示testset的大小,L表示所有備選label合集的大小,在MS-COCO2014的testset里,\(M=40504,L=80\)
Hamming Loss
\(h_{loss}\)可能是最直觀也是最容易理解的一個loss,它直接統計了被誤分類label的個數(不屬於這個樣本的標簽被預測,或者屬於這個樣本的標簽沒有被預測)。\(h_{loss}=0\)表示所有的每一個data的所有label都被分對了。
\(h_{loss}= \frac{1}{p}∑_{i=1}^ph(x_{i})ΔY_{i}\), where \(p=N\times L\)
\(F_{1}\) score
介紹F score之前首先要理清准確率(Accuracy),精確率(Precision)和召回率(Recall)之間的關系。
Accuracy的定義是:分類器正確分類的次數與總分類數之比。Hamming Loss可以說是accuracy的一種呈現。但其實如果只追求hamming loss/accuracy的話,就會出現以下問題:已知MS-COCO里的大多數圖片只包含幾個(<=4)物體,這樣只要把所有圖片的標簽都設為0,也能達到大約4/80(0.08)的hamming loss。
所以我們需要precision(查准率)和recall(查全率)作為別的metrics去評判一個classifier的給力程度。下面解釋了如何用precision和recall,還有這兩個metrics的合成F score來評判一個multilabel classifier。
precision和recall一開始是從信息檢索衍生出來的。precision(查准率)計算的是所有"正確被檢索的item(TP)"占所有"實際被檢索到的(TP+FP)"的比例,recall(查全率)計算的是所有"正確被檢索的item(TP)"占所有"應該檢索到的item(TP+FN)"的比例。后來也可以延伸去二分類問題,如下表所示。
gt\pred | 1 | 0 |
---|---|---|
1 | TP | FP |
0 | FN | TN |
precision:\(P = \frac{TP}{TP+FP}\)
recall:\(R = \frac{TP}{TP+FN}\)
\(F_{1}\)值就是precision和 recall的調和均值(harmonic mean):\(\frac{2}{F_1} = \frac{1}{P} + \frac{1}{R}\),也能寫成\(F_1 = \frac{2PR}{P+R} = \frac{2TP}{2TP + FP + FN}\)
Scikit-learn的官方文檔中把precision,recall的關系解釋得十分清楚(https://scikit-learn.org/stable/auto_examples/model_selection/plot_precision_recall.html#sphx-glr-auto-examples-model-selection-plot-precision-recall-py)
實際上\(F_{1}\)是\(F_{\beta}\)的一個特殊形式,在一些應用中,對查准率和查全率的重視程度不同。比如在商品推薦中,要盡可能少的打擾用戶,所以查准率更重要;在疾病篩查中,要盡可能漏掉可能疾病,所以查全率更重要。
\(F_{\beta}= \frac{(\beta^2 + 1 )PR}{\beta^2P+R}\),從左邊式子可以看出\(\beta>1\)時查全率更重要,\(\beta<1\)時查准率更重要,\(\beta=1\)時查全和查准同樣重要。
\(F_{1}\) score in Multilabel Classification:
在針對multilabel分類計算F score的時候,通常有macro和micro兩種average的方法。Python的scikit-learn庫在計算f1 score也提供了micro和macro兩種選擇,具體在multilabel的情況下,怎么計算\(F_{1}\) score,在網上查閱了很多博客和資料都沒有給出一個明確的用列子解釋的步驟,這邊我自己通過整合資料代碼驗證出了macro和micro兩種\(F_1\)score的計算方法。
請看下面的簡單例子:
讓\(,N=3, L=3\) ,一共有三個data,每個data有三個預備分類:
import numpy as np
y_gt = np.array ([[1,0,1],[0,1,1],[0,1,0]])
y_pred = np.array ([[0,0,1],[1,1,1],[1,1,1]])
from sklearn.metrics import f1_score
f1_score(y_gt, y_pred, average="macro") #0.6
f1_score(y_gt, y_pred, average="micro") #0.66666666666666666
對於每一個class,我們都需要先算一個2x2的confusion matrix,里面分別標明了對於這一個class的TP,FP,FN和TN。注意,這個confusion matrix不是multiclass里的那個,而是類似於binary classifier里,只有0和1分類的confusion matrix。
macro:
對於macro,我們通過每一個class的confusion matrix算出它的precision和recall,並計算出對與那個class的F1 score,最后通過平均所有class的\(F_1\) score得到\(F1_{macro}\)
Class 0:
gt\pred | 1 | 0 |
---|---|---|
1 | 0 | 1 |
0 | 2 | 0 |
\(P_0 = \frac{0}{0+2}=0, R_0 = \frac{0}{0+1}=0\)
\(F1_0=\frac{2\times0\times0}{0+0}=0\)
Class 1:
gt\pred | 1 | 0 |
---|---|---|
1 | 2 | 0 |
0 | 0 | 1 |
\(P_1 = \frac{2}{2+0}=1, R_1 = \frac{2}{2+0}=1\)
\(F1_1=\frac{2\times1\times1}{1+1}=1\)
Class 2:**
gt\pred | 1 | 0 |
---|---|---|
1 | 2 | 0 |
0 | 1 | 0 |
\(P_2 = \frac{2}{2+1}=\frac{2}{3}, R_2 = \frac{2}{2+0}=1\)
\(F1_2=\frac{2\times{\frac{2}{3}}\times1}{\frac{2}{3}+1}=\frac{4}{5}\)
\(F1_{macro}=\frac{1}{N}(F1_0+ F1_1+…+F1_N)=\frac{1}{3}(F1_0+F1_1+F1_2)=\frac{1}{3}(0+1+\frac{4}{5})=0.6\)
micro:
對於micro,我們把所有class的binary confusion matrix整合成一個大的2x2confusion matrix,然后並對於整合成的confusion matrix算出一個precision和recall值(\(P_{comb}\) and \(R_{comb}\)),最后通過公式得到\(F1_{micro}\) score。
Combined all classes:
gt\pred | 1 | 0 |
---|---|---|
1 | 4 | 1 |
0 | 3 | 1 |
\(P_{comb}=\frac{4}{4+3}=\frac{4}{7}, R_{comb}=\frac{4}{4+1}=\frac{4}{5}\)
\(F1_{micro}=\frac{2P_{comb}R_{comb}}{P_{comb}+R_{comb}}=\frac{2\times\frac{4}{7}\times\frac{4}{5}}{\frac{4}{7}+\frac{4}{5}}=0.66666666...\)