理解accuracy/precision_score、micro/macro


  • 1、accuracy即我們通常理解的准確率,計算的時候是指在預測值pred與目標值target之間重疊的部分的大小除以pred的大小(或target的大小,因為sklearn要求pred與target大小必須一致)。

比如

target=[2,2,2,3,2]
pred=[2,2,1,3,4]

此時重疊的部分為pred[0]、pred[1]、pred[3],accuracy=3/5=0.6

而precision_score意思類似,但不完全一樣,它是從pred的角度考慮,意思是我雖然預測了這么多個,但有幾個預測對了?占比多少?這就是precision。
舉例:

target=np.array([1,1,1,1,1])
pred=np.array([2,2,1,1,1])
p=precision_score(target,pred)
print(p)#1.0

的結果為1.0(看不懂?馬上解釋);
但如果是accuracy_score(target,pred),就會輸出0.60(預測了5個,對了3個)  此外,

p=precision_score(target,pred)

 其實等價於

p=precision_score(target,pred,average='binary',pos_label=1)

average='binary'表示pred當中(最多)只有兩種標簽(此處是1,2),pos_label=1表示最后輸出的結果是針對類別值"1"的計算結果。

如果改成pos_label=2

p=precision_score(target,pred,average='binary',pos_label=2)

則表示計算結果是針對類別為"2"的統計結果,結果為0.0(因為pred中有兩個2,但都預測錯了,所以為0)。

pos_label這個參數只有average='binary'時管用,若pred中出現3種及以上類別的標簽,則pos_label參數即使設置了也會被忽略。

 

  • 2、下面說說average參數的作用,當pred當中有3種或以上類別時,average的值只能取[None, 'micro', 'macro', 'weighted']當中的一種,

其中,有趣的是,當average='micro'時,precision_score(target,pred,average='micro')等價於accuracy的算法,就是看預測對的標簽總個數,再除以pred的大小。

 

而當average='macro'時,會計算每個種類標簽的precision_score,再取平均(不考慮各個類別的樣本分布差異)。例如:

target=np.array([1,1,2,3,3])
pred=np.array([2,2,1,3,4])
precision_score(target,pred,average='macro')

的結果為0.25,怎么算出來的0.25?

這樣算:首先確定,pred中一共是4個類別(1,2,3,4),預測對的只有pred[3],

類別1的precision=0/1(pred中只有1個標簽1,預測對了0個)結果為0
類別2的precision=0/2(pred中有2個標簽2,預測對了0個),結果為0
類別3的precision=1/1(pred中有1個標簽3,預測對了1個),結果為1
類別4的precision=0/1(pred中有1個標簽4,預測對了0個),結果為0

再取平均(不考慮類別的分布差異):(0+0+1+0)/4=0.25。

Macro另外一個需要注意的地方在於,它在做平均的時候,它認為的類別數不是看target有多少個類別,也不是看pred有多少個類別,而是兩者取並集,作為總的類別數。

例如,

target=np.array([1,1,3,3,4])
pred = np.array([1,1,2,0,0,])
print(precision_score(target,pred,average='macro'))#輸出0.2

輸出0.2,你敢信?並且報了一個警告:

D:\Anaconda3\lib\site-packages\sklearn\metrics\_classification.py:1221: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, msg_start, len(result))

說那些沒有被預測的類別的precision_score默認為0,

於是,就是類別1的預測precision_score=1,但一共有0,1,2,3,4,共5類別,而其余類別的precison均為0,所以1/5=0.2。

而當average='weighted'時,前面的步驟跟macro相同,分別計算pred中各個類別的precision_score,但匯總時則會考慮各個類別的樣本的分布差異。例如,

target=np.array([1,1,2,2,3,3])
pred=np.array([2,2,1,3,4,3])
precision_score(target,pred,average='macro')

輸出0.125

計算過程:pred中有4個類別,類別1、2、4預測正確的個數為0,precision_score均為0,而類別3,預測了2個(pred[3]、pred[5]),僅對了1個(pred[5]),precision_score=0.5,再取平均(0+0+0.5+0)/4=0.125,而

precision_score(target,pred,average='weighted')

 則輸出0.1666

因為average='weighted'時,會考慮各個類別(在target中,而非pred中)的分布比例,比如,類別1在target中出現占比為2/6,同理類別3的占比為2/6=1/3,
因此最后結果等於0*1/3+0*1/3+0.5*1/3+0*1/3=1/6=0.1666

 

  • 3、再講講召回率recall_score的計算方法。

舉例:

target=np.array([1,2,2,2,3,3])
pred=np.array([2,2,1,3,4,3])
recall_score(target,pred,average='macro')

輸出0.20833333333333331,其實就是5/24。怎么來的?

首先依據定義,pred的召回率是指pred中出現的各類標簽,預測正確的次數占target中該類標簽數的比例。

類別1的recall=0/1=0
類別2的recall=1/3(1個,即pred[1]預測正確,target中類別2出現了3次)
類別3的recall=1/2(1個,即pred[5]預測正確,target中類別3出現2次)
類別4的recall=0,類別4在target中沒有出現,因此預測錯誤。

最后求平均:(1/3+1/2)/4=5/24=0.20833333333333334

同理,average='weighted'時,

recall_score(np.array([1,2,2,2,3,3]),np.array([2,2,1,3,4,3]),average='weighted')

輸出0.333333=1/3

即分別用標簽1、2、3、4的recall_score再乘上它們再target中的占比,0*1/6+1/3*3/6+1/2*2/6+0*0/6=1/3。

 

  • 4、另外,需要注意的是sklearn.metrics模塊中的precision_score,recall_score中對比的target和pred參數都是一維數組(若不是一維數組,則會認為某一行代表一個樣本有多個標簽),因此在模型的批訓練時,獲得的預測結果,需要先轉換成一維數組再計算precision,recall,f1等指標。

參考:https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_score.html#sklearn.metrics.precision_score


免責聲明!

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



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