學習筆記,持續更新修訂中.......
1.混淆矩陣
(1)常見二分類混淆矩陣如下:
混淆矩陣 | 預測值 | ||
正 | 負 | ||
真實值 | 正 | TP | FN |
負 | FP | TN |
True Positive:真正類(TP),樣本的真實類別是正類,並且模型預測的結果也是正類。
False Negative:假負類(FN),樣本的真實類別是正類,但是模型將其預測成為負類。(統計學上的第二類誤差(Type II Error))
False Positive:假正類(FP),樣本的真實類別是負類,但是模型將其預測成為正類。(統計學上的第一類誤差(Type I Error))
True Negative:真負類(TN),樣本的真實類別是負類,並且模型將其預測成為負類。
(2)類別為3,每類分別記為A,B,C
混淆矩陣 | 預測值 | |||
A | B | C | ||
真實值 | A | AA | AB | AC |
B | BA | BB | BC | |
C | CA | CB | CC |
2.精度指標
2.1 Overall Accuracy、Average Accuracy
2.1.1 定義及計算方式
以上述二分類為例:
#1.總體精度(Overall Accuracy, OA):樣本中正確分類的總數除以樣本總數。 OA=(TP+TN)/(TP+FN+FP+TN) #2.平均精度(Average Accuracy, AA):每一類別中預測正確的數目除以該類總數,記為該類的精度,最后求每類精度的平均。 AA=(TP/(TP+FN)+TN/(FP+TN))/2
2.1.2 指示意義
OA與Accuracy定義一致。AA與Recall計算公式比較一致,不過考慮了正負兩例的計算。
2.2 Accuracy、Precision、Recall以及F-score
一般針對二分類,有正負例區分。
2.2.1 定義及計算方式
#1.准確率(Accuracy):模型的精度,即模型預測正確的個數 / 樣本的總個數;一般情況下,模型的精度越高,說明模型的效果越好。 Accuracy=(TP+TN)/(TP+TN+FP+FN) #2.精確率(Precision):模型預測為正的部分的正確率。 Precision=TP/(TP+FP) #3.召回率(Recall):真實值為正的部分,被模型預測出來且正確的比重。 Recall=TP/(TP+FN) #4.F1-score:此指標綜合了Precision與Recall的產出的結果,取值范圍從0到1的,1代表模型的輸出最好,0代表模型的輸出結果最差。 F=2*Precision*Recall/(Precision+Recall)
2.2.2 指示意義
總體上來說,我們希望這些值盡可能大。但實際上卻不能盡如人意,而且每個指標的指示意義各不相同,需要參照定義、具體樣本和預測預期進行分析;
2.3 IoU與MIoU
2.3.1 定義與計算
以二分類為例:
IoU(Intersection over Union,交並比):計算某一類別預測結果和真實值的交集和並集的比值。計算公式如下:
MIoU(Mean Intersection over Union,平均交並比):計算所有類別的IoU的平均值。計算公式如下(因k從0開始,故需要加1):
# 計算1中二分類混淆矩陣中正負兩類的MIoU MIoU=(IoU(正)+IoU(負))/2
=(TP/(FN+FP+TP)+TN/(TN+FN+FP))/2
更一般的,多分類:
某一類的IoU的分子為:該類所在混淆矩陣對角線的值。
某一類的IoU的分母為:該類所在混淆矩陣對角線的位置對應的行和列的總和。(對角線位置的值只能計算一次)
2.3.2 指示意義
因對於一個樣本來說,FN+TP是固定的,那么IoU就可以變為IoU=TP/(K+FP),那么主要相當於分析TP與FP的變化趨勢。孤立的分析IoU,這里有4種情況可能使得IoU變大:
1)TP不變,FP減小;IoU肯定變大
2)TP變小,FP變小;IoU應該可大可小
3)TP變大,FP不變;IoU肯定變大
3)TP變大,FP變大;IoU應該可大可小!如下表格C1到C2,IC1=1/(1+5)=1/6、IC2=3/(4+5)=1/3;此時雖然IoU變大,但是Accuracy卻變小了,模型的好壞需要另外討論。
假設 | TP | FN | FP | TN | Total |
C1 | 1 | 4 | 1 | 4 | 10 |
C2 | 3 | 2 | 4 | 1 | 10 |
C3 | 2 | 3 | 2 | 3 | 10 |
也就是說IoU變大,模型不一定變好,但大多數情況下還是變好的。
2.4 Kappa系數
2.4.1 定義及計算
Kappa系數用於一致性檢驗,也可以用於衡量分類精度,其計算是基於混淆矩陣的。公式如下:
其中,po是每一類正確分類的樣本數量之和除以總樣本數,也就是總體分類精度(OA);pe為每一類真實數量乘以該類預測數量的總和除以所有類別總數的平方,如下:
,
其中Gk為第k類的真實標簽數量,Pk為第k類的預測標簽數量,K為總的類別數量,N為所有類別標簽的總數。
在上述二分類混淆矩陣中,po,pe為:
,
2.4.2 指示意義
kappa計算結果為-1~1,但通常kappa是落在 0~1 間,可分為五組來表示不同級別的一致性(真實值與預測值):0.0~0.20極低的一致性(slight)、0.21~0.40一般的一致性(fair)、0.41~0.60 中等的一致性(moderate)、0.61~0.80 高度的一致性(substantial)和0.81~1幾乎完全一致(almost perfect)。
Kappa范圍 | 指示意義 |
0.00~0.20 | 一致性極低 |
0.21~0.40 | 一致性一般 |
0.41~0.60 | 一致性中等 |
0.61~0.80 | 一致性高度 |
0.81~1.00 | 幾乎完全一致 |
3.代碼實現
scikit-learn中集成了較為全面的精度指標計算,方便快捷(推薦)。
便於熟悉個指標計算,使用Python進行簡單的實現(粗略檢查,可能存在問題),分為二分類和多分類版本:

import numpy as np def computeAccuracyIndex2BinaryClassification(gt,pd,nclass,decimal_digits=4,verbose=True): assert gt.shape[0]==pd.shape[0] N=gt.shape[0] '''confusion matrix''' cmat=np.zeros((nclass,nclass)) # confusion matrix for i in range(nclass): for j in range(nclass): tmp= np.sum((gt==i)&(pd==j)) cmat[i][j]=tmp '''OA、AA''' OA=np.sum(np.diagonal(cmat))/np.sum(cmat) # equal to OA AA=np.mean(np.diagonal(cmat)/np.sum(cmat,axis=1)) # 求和維度 '''Accuracy、Precision、Recall、F''' Accuracy=OA Precision=cmat[1,1]/np.sum(cmat[1,:]) Recall=cmat[1,1]/np.sum(cmat[:,1]) F=2*Precision*Recall/(Precision+Recall) '''IoU、MIoU''' MIoU=0 IoU=np.zeros(nclass) for i in range(nclass): IoU[i]=cmat[i,i]/(np.sum(cmat[i,:])+np.sum(cmat[:,i])-cmat[i,i]) MIoU=np.mean(IoU) '''Kappa''' po=OA pe=0 for i in range(nclass): pe+=(np.sum(cmat[i,:])*np.sum(cmat[:,i])) pe=pe/(N*N) Kappa=(po-pe)/(1-pe) if decimal_digits is not None: OA=np.around(OA,decimal_digits) AA=np.around(AA,decimal_digits) Accuracy=np.around(Accuracy,decimal_digits) Precision=np.around(Precision,decimal_digits) Recall=np.around(Recall,decimal_digits) F=np.around(F,decimal_digits) IoU=np.around(IoU,decimal_digits) MIoU=np.around(MIoU,decimal_digits) Kappa=np.around(Kappa,decimal_digits) if verbose: print(f'confusion matrix:\n {cmat}') print(f'Index 1: OA={OA} AA={AA}') print(f'Index 2: Accuray={Accuracy} Precision={Precision} Recall={Recall} F={F}') # 此體系一般針對二分類,且1對應正例 print(f'Index 3: MIoU={MIoU} IoU={IoU}') print(f'Index 4: Kappa={Kappa}') return [OA,AA],[Accuracy,Precision,Recall,F],[MIoU,IoU],[Kappa] # 測試 gt=np.array([0, 1, 0, 0]) pd=np.array([0, 1, 0, 1]) nclass=2 decimal_digits=4 computeAccuracyIndex2BinaryClassification(gt,pd,nclass,4,True)

import numpy as np def computeAccuracyIndex2MultiClassification(gt,pd,nclass,decimal_digits=4,verbose=True): assert gt.shape[0]==pd.shape[0] N=gt.shape[0] '''confusion matrix''' cmat=np.zeros((nclass,nclass)) # confusion matrix for i in range(nclass): for j in range(nclass): tmp= np.sum((gt==i)&(pd==j)) cmat[i][j]=tmp '''OA、AA''' OA=np.sum(np.diagonal(cmat))/np.sum(cmat) # equal to OA AA=np.mean(np.diagonal(cmat)/np.sum(cmat,axis=1)) # 求和維度 '''IoU、MIoU''' MIoU=0 IoU=np.zeros(nclass) for i in range(nclass): IoU[i]=cmat[i,i]/(np.sum(cmat[i,:])+np.sum(cmat[:,i])-cmat[i,i]) MIoU=np.mean(IoU) '''Kappa''' po=OA pe=0 for i in range(nclass): pe+=(np.sum(cmat[i,:])*np.sum(cmat[:,i])) pe=pe/(N*N) Kappa=(po-pe)/(1-pe) if decimal_digits is not None: OA=np.around(OA,decimal_digits) AA=np.around(AA,decimal_digits) IoU=np.around(IoU,decimal_digits) MIoU=np.around(MIoU,decimal_digits) Kappa=np.around(Kappa,decimal_digits) if verbose: print(f'confusion matrix:\n {cmat}') print(f'Index 1: OA={OA} AA={AA}') print(f'Index 2: MIoU={MIoU} IoU={IoU}') print(f'Index 3: Kappa={Kappa}') return [OA,AA],[MIoU,IoU],[Kappa] gt=np.array([2, 0, 2, 2, 0, 1]) pd=np.array([0, 0, 2, 2, 0, 2]) nclass=3 decimal_digits=4 computeAccuracyIndex2MultiClassification(gt,pd,nclass,4,True)