- 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等指標。