摘要:這篇文章主要向大家介紹深度學習分類任務評價指標,主要內容包括基礎應用、實用技巧、原理機制等方面,希望對大家有所幫助。
本文分享自華為雲社區《深度學習分類任務常用評估指標》,原文作者:lutianfei 。
這篇文章主要向大家介紹深度學習分類任務評價指標,主要內容包括基礎應用、實用技巧、原理機制等方面,希望對大家有所幫助。
分類模型
混淆矩陣
sklearn實現:
sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None) 返回值:一個格式化的字符串,給出了分類結果的混淆矩陣。 參數:參考classification_report 。 混淆矩陣的內容如下,其中Cij表示真實標記為i但是預測為j的樣本的數量。 Confusion Matrix: [[5 0] [3 2]] def calc_confusion_matrix(y_true: list, y_pred: list, show=True, save=False, figsize=(16, 16), verbose=False): """ 計算混淆矩陣 :param y_true: :param y_pred: :param show: :param save: :param figsize: :param verbose: :return: """ confusion = confusion_matrix(y_true, y_pred) if verbose: print(confusion) if show: show_confusion_matrix(confusion, figsize=figsize, save=save) return confusion def show_confusion_matrix(confusion, classes=MY_CLASSES, x_rot=-60, figsize=None, save=False): """ 繪制混淆矩陣 :param confusion: :param classes: :param x_rot: :param figsize: :param save: :return: """ if figsize is not None: plt.rcParams['figure.figsize'] = figsize plt.imshow(confusion, cmap=plt.cm.YlOrRd) indices = range(len(confusion)) plt.xticks(indices, classes, rotation=x_rot, fontsize=12) plt.yticks(indices, classes, fontsize=12) plt.colorbar() plt.xlabel('y_pred') plt.ylabel('y_true') # 顯示數據 for first_index in range(len(confusion)): for second_index in range(len(confusion[first_index])): plt.text(first_index, second_index, confusion[first_index][second_index]) if save: plt.savefig("./confusion_matrix.png") plt.show()
混淆矩陣是監督學習中的一種可視化工具,主要用於比較分類結果和實例的真實信息。矩陣中的每一行代表實例的預測類別,每一列代表實例的真實類別。
理解方法:
P(positive):預測為正樣本
N(Negative):預測為負樣本
T(True):預測正確
F(False):預測錯誤
- 真正(True Positive, TP): 被模型預測為正的正樣本。預測為1,預測正確,即實際1
- 假正(False Positive, FP): 被模型預測為正的負樣本。預測為1,預測錯誤,即實際0
- 假負(False Negative, FN): 被模型預測為負的正樣本。預測為0,預測錯確,即實際1
- 真負(True Negative, TN): 被模型預測為負的負樣本。預測為0,預測正確即,實際0
真正率(True Positive Rate, TPR)或靈敏率(sensitivity)
TPR= TP/(TP+FN) -> 正樣本預測結果數/正樣本實際數
由上述公式可知TPR等價於Recall
真負率(True Negative Rate, TNR)或 特指度/特異度(specificity)
TNR=TN/(TN+FP) -> 負樣本預測結果數/負樣本實際數
假正率(False Positive Rate, FPR)
FPR = FP/(FP+TN) -> 被預測為正的負樣本結果數/負樣本實際數
假負率(False Negative Rate, FNR)
FNR = FN/(TP+FN) -> 被預測為負的正樣本結果數/正樣本實際數
准確率(正確率,Accuracy)
也稱正確率,預測正確的結果占總樣本的百分比,最常用的分類性能指標。
公式:Accuracy = (TP+TN)/(TP+FN+FP+FN)
缺點:樣本不均衡時有局限性,
例如:當負樣本占99%時,分類器把所有樣本都預測為負樣本也可以獲得99%的准確率。所以,當不同類別的樣本比例非常不均衡時,占比大的類別往往成為影響准確率的最主要因素。
sklearn實現:
from sklearn.metrics import accuracy_score accuracy_score(y_true, y_pred, normalize=True, sample_weight=None) 返回值:如果normalize為True,則返回准確率;如果normalize為False,則返回正確分類的數量。 參數: y_true:真實的標記集合。 y_pred:預測的標記集合。 normalize:一個布爾值,指示是否需要歸一化結果。 如果為True,則返回分類正確的比例(准確率)。 如果為False,則返回分類正確的樣本數量。 sample_weight:樣本權重,默認每個樣本的權重為 1 。 # 方法封裝 def calc_accuracy_score(y_true: list, y_pred: list, verbose=False): res = accuracy_score(y_true, y_pred) if verbose: print("accuracy:%s" % res) return res
錯誤率(Error rate)
即,錯誤預測的正反例數/總數。
正確率與錯誤率是分別從正反兩方面進行評價的指標,兩者數值相加剛好等於1。
ErrorRate = (FP+FN)/(TP+FN+FP+TN)
精確率(查准率,Precision)
精准率(Precision)又叫查准率,它是針對預測結果而言的,它的含義是在所有被預測為正的樣本中實際為正的樣本的概率,意思就是在預測為正樣本的結果中,我們有多少把握可以預測正確,其公式如下:
Precision = TP/(TP+FP)
缺點:預測的結果只有1例正例,並且是正確的,精准率為100%。實際又很多預測錯誤的負例,即真實的正例。
場景:預測股票會漲,真實漲了10次,只預測到了兩次會漲,預測這兩次都對了,那么就是我們想要的精准度高,此時召回率不重要。
sklearn實現:
from sklearn.metrics import precision_score sklearn.metrics.precision_score(y_true, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None) 返回值:查准率。即預測結果為正類的那些樣本中,有多少比例確實是正類。 參數: y_true:真實的標記集合。 y_pred:預測的標記集合。 labels:一個列表。當average 不是'binary' 時使用。 對於多分類問題,它表示:將計算哪些類別。不在labels 中的類別,計算macro precision 時其成分為 0 。 對於多標簽問題,它表示:待考察的標簽的索引。 除了average=None 之外,labels 的元素的順序也非常重要。 默認情況下,y_true 和 y_pred 中所有的類別都將被用到。 pos_label:一個字符串或者整數,指定哪個標記值屬於正類。 如果是多分類或者多標簽問題,則該參數被忽略。 如果設置label=[pos_label] 以及average!='binary' 則會僅僅計算該類別的precision 。 average:一個字符串或者None,用於指定二分類或者多類分類的precision 如何計算。 'binary':計算二類分類的precision。 此時由pos_label 指定的類為正類,報告其precision 。 它要求y_true、y_pred 的元素都是0,1 。 'micro':通過全局的正例和負例,計算precision 。 'macro':計算每個類別的precision,然后返回它們的均值。 'weighted':計算每個類別的precision,然后返回其加權均值,權重為每個類別的樣本數。 'samples':計算每個樣本的precision,然后返回其均值。該方法僅僅對於多標簽分類問題有意義。 None:計算每個類別的precision,然后以數組的形式返回每個precision 。 sample_weight:樣本權重,默認每個樣本的權重為 1 # 方法封裝 def calc_precision_score(y_true: list, y_pred: list, labels=MY_CLASSES, average=None, verbose=False): res = precision_score(y_true, y_pred, labels=labels, average=average) if verbose: print("precision:%s" % res) return res
召回率(查全率,Recall)
召回率(Recall)又叫查全率,它是針對原樣本而言的,它的含義是在實際為正的樣本中被預測為正樣本的概率,其公式如下:
Recall = TP/(TP+FN)
缺點:都預測為正例時也會覆蓋所有真實的正例,召回率也為100%。
召回率的應用場景:比如拿網貸違約率為例,相對好用戶,我們更關心壞用戶,不能錯放過任何一個壞用戶。因為如果我們過多的將壞用戶當成好用戶,這樣后續可能發生的違約金額會遠超過好用戶償還的借貸利息金額,造成嚴重償失。召回率越高,代表實際壞用戶被預測出來的概率越高,它的含義類似:寧可錯殺一千,絕不放過一個。
sklearn實現:
from sklearn.metrics import recall_score sklearn.metrics.recall_score(y_true, y_pred, labels=None, pos_label=1,average='binary', sample_weight=None) 返回值:查全率。即真實的正類中,有多少比例被預測為正類。 參數:參考precision_score。 # 方法封裝 def calc_recall_score(y_true: list, y_pred: list, labels=MY_CLASSES, average=None, verbose=False): res = recall_score(y_true, y_pred, labels=labels, average=average) if verbose: print("recall: %s" % res) return res
下圖正精確率和召回率做了進一步說明
PR曲線
通過精確率和召回率的公式可知:精准率和召回率的分子是相同,都是TP,但分母是不同的,一個是(TP+FP),一個是(TP+FN)。兩者的關系可以用一個P-R圖來展示:
分類模型的最后輸出往往是一個概率值,我們一般需要把概率值轉換為具體的類別,對於二分類來說,我們設置一個閾值(threshold),然后大於此閾值判定為正類,反之負類。上述評價指標(Accuracy、Precision、Recall)都是針對某個特定閾值來說的,那么當不同模型取不同閾值時,如何全面的評價不同模型?因此這里需要引入PR曲線,即Precision-Recall曲線來進行評估。
為了找到一個最合適的閾值滿足我們的要求,我們就必須遍歷0到1之間所有的閾值,而每個閾值下都對應着一對查准率和查全率,從而我們就得到了這條曲線。
如下圖所示,縱坐標是精確率P,橫坐標是召回率R。對於一個模型來說,
其P-R曲線上的一個點代表着,在某一閾值下,模型將大於該閾值的結果判定為正樣本,小於該閾值的結果判定為負樣本,
此時返回結果對應一對兒召回率和精確率,作為PR坐標系上的一個坐標。
整條P-R曲線是通過將閾值從高到低移動而生成的。P-R曲線越靠近右上角(1,1)代表模型越好。在現實場景,需要根據不同決策要求綜合判斷不同模型的好壞。
評價標准:
先看平滑不平滑(越平滑越好)。一般來說,在同一測試集,上面的比下面的好(綠線比紅線好)。當P和R的值接近時F1值最大。此時畫連接(0,0)和(1,1)的線。線和PR曲線重合的地方F1值最大。此時的F1對於PR曲線就相當於AUC對於ROC一樣。
PR曲線下的面積稱為AP(Average
Precision),表示召回率從0-1的平均精度值。AP可用積分進行計算。AP面積不會大於1。PR曲線下的面積越大,模型性能越好。
所謂性能優的模型應該是在召回率增長的同時保持精確度在一個較高水平。
sklearn實現:
sklearn.metrics.precision_recall_curve(y_true, probas_pred, pos_label=None, sample_weight=None) 返回值:一個元組,元組內的元素分別為: P-R曲線的查准率序列。該序列是遞增序列,序列第 i 個元素是當正類概率的判定閾值為 thresholds[i]時的查准率。 P-R曲線的查全率序列。該序列是遞減序列,序列第 i 個元素是當正類概率的判定閾值為 thresholds[i]時的查全率。 P-R曲線的閾值序列thresholds。該序列是一個遞增序列,給出了判定為正例時的正類概率的閾值。 參數: y_true:真實的標記集合。 probas_pred:每個樣本預測為正類的概率的集合。 pos_label:正類的類別標記。 sample_weight:樣本權重,默認每個樣本的權重為 1。 def calc_precision_recall_curve(class_info, class_name=None, show=True, save=False, verbose=False): """ 計算PR曲線 :param class_info: :param class_name: :param show: :param save: :param verbose: :return: """ precision, recall, thresholds = precision_recall_curve(class_info['gt_lbl'], class_info['score']) if verbose: print("%s precision:%s " % (class_name, precision,)) print("%s recall:%s " % (class_name, recall,)) print("%s thresholds:%s " % (class_name, thresholds,)) if show: show_PR_curve(recall, precision, class_name) return precision, recall, thresholds
PR曲線繪制方法:
def show_PR_curve(recall, precision, class_name=None, save=False): """ 繪制PR曲線 :param recall: :param precision: :param class_name: :param save: :return: """ plt.figure("%s P-R Curve" % class_name) plt.title('%s Precision/Recall Curve' % class_name) plt.xlabel('Recall') plt.ylabel('Precision') plt.plot(recall, precision) if save: plt.savefig("./%s_pr_curve.png") plt.show()
F1 score 調和平均值
F1
Score又稱F-Measure,是精確率和召回率的調和值,更接近於兩個數較小的那個,所以精確率和召回率接近時F1值最大。很多推薦系統的評測指標就是用F1
Score。
Precision和Recall是既矛盾又統一的兩個指標, 為了提高Precision值,
分類器需要盡量在“更有把握”時才把樣本預測為正樣本,
但此時往往會因為過於保守而漏掉很多“沒有把握”的正樣本,
導致Recall值降低。那么當不同模型的Recall和Precision各有優勢時該如何選擇模型?如果想要找到二者之間的一個平衡點,我們就需要一個新的指標:F1分數。F1分數同時考慮了查准率和查全率,讓二者同時達到最高,取一個平衡。F1分數的公式為
= 2*查准率*查全率 / (查准率 +
查全率)。我們在PR曲線圖1中看到的平衡點就是F1分數得來的結果。
即
在現實場景,如果兩個模型,一個precision特別高,recall特別低,另一個recall特別高,precision特別低的時候,f1-score可能是差不多的,可能不能通過一個f1
socre做出最終判斷,此時就需要根據不同場景選擇其他合適的指標做出評判。
sklearn實現:
from sklearn.metrics import f1_score #調和平均值F1 f1_score(y_true, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None) 返回值: 值。即查准率和查全率的調和均值。 參數:參考precision_score。 #方法封裝 def calc_f1_score(y_true: list, y_pred: list, labels=MY_CLASSES, average=None, verbose=False): res = f1_score(y_true, y_pred, labels=labels, average=average) if verbose: print("f1_score: %s" % res) return res
ROC曲線
ROC(Receiver Operating
Characteristic-受試者工作特征曲線,又稱感受性曲線),用圖形來描述二分類模型的性能表現,是一個全面評估模型的指標。
ROC和AUC可以無視樣本不平衡的原因是:靈敏度和(1-特異度),也叫做真正率(TPR)和假正率(FPR)。由於TPR和FPR分別是基於實際表現1和0出發的,也就是說它們分別在實際的正樣本和負樣本中來觀察相關概率問題。正因為如此,所以無論樣本是否平衡,都不會被影響。
例如:總樣本中,90%是正樣本,10%是負樣本。我們知道用准確率是有水分的,但是用TPR和FPR不一樣。這里,TPR只關注90%正樣本中有多少是被真正覆蓋的,而與那10%毫無關系,同理,FPR只關注10%負樣本中有多少是被錯誤覆蓋的,也與那90%毫無關系,所以可以看出:如果我們從實際表現的各個結果角度出發,就可以避免樣本不平衡的問題了,這也是為什么選用TPR和FPR作為ROC/AUC的指標的原因。
X軸:假正率(FPR),模型預測為假的正例在真實負例的占比。錯誤判斷的正類占所有負類的比例,醫學上等價於誤診率。
Y軸:真正率(TPR),模型預測為真的正例在真實正例的占比。
ROC 曲線離對角線越近,模型的准確率越低。
曲線說明:
ROC曲線是通過不同閾值下的FPR和TPR坐標所得到的。具體來說,通過動態地調整模型概率閾值(概率閾值的意思是模型多大概率判定為正類),
從最高的值開始( 比如1, 對應着ROC曲線的零點) , 逐漸調整到最低概率值,
每一個概率值都會對應一個FPR和TPR, 在ROC圖上繪制出每個概率值對應的位置,
再連接所有點就得到最終的ROC曲線。
曲線特征:
- 通過調整判斷分類的閾值(邏輯回歸默認閾值0.5),TPR和FPR隨之改變,進而在ROC曲線坐標上形成多個點,反應模型分類效果。
- TPR增長越快,同時FPR越低,曲線越凸,模型的分類性能越好,即預測為正確的正例越多。
- ROC曲線比過(0,0), (1,0)兩點。原因:
邏輯回歸模型默認閾值為0.5,sigmoid()結果即類別概率p默認≥0.5時,模型預測為類別1(正例)。那么修改閾值為0時,p≥0模型預測為類別1(正例),說明該模型該閾值下會將所有數據均預測為類別1(無論對錯),此時FN=TN=0個,TPR=FPR=1
修改閾值為1時,p≥1模型預測為類別1(正例),p是不可能大於100%的,說明該模型該閾值下會將所有數據均預測為類別0(無論對錯),此時FP=TP=0個,TPR=FPR=0
sklearn實現:
roc_curve函數用於計算分類結果的ROC曲線。其原型為: sklearn.metrics.roc_curve(y_true, y_score, pos_label=None, sample_weight=None, drop_intermediate=True) 返回值:一個元組,元組內的元素分別為: ROC曲線的FPR序列。該序列是遞增序列,序列第 i 個元素是當正類概率的判定閾值為 thresholds[i]時的假正例率。 ROC曲線的TPR序列。該序列是遞增序列,序列第 i 個元素是當正類概率的判定閾值為 thresholds[i]時的真正例率。 ROC曲線的閾值序列thresholds。該序列是一個遞減序列,給出了判定為正例時的正類概率的閾值。 參數: y_true:真實的標記集合。 y_score:每個樣本預測為正類的概率的集合。 pos_label:正類的類別標記。 sample_weight:樣本權重,默認每個樣本的權重為 1。 drop_intermediate:一個布爾值。如果為True,則拋棄某些不可能出現在ROC曲線上的閾值。 #方法封裝 def calc_roc_curve(class_info, class_name=None, show=True, save=False, verbose=False): """ 計算roc曲線 :param class_info: :param class_name: :param show: :param save: :param verbose: :return: """ fpr, tpr, thresholds = roc_curve(class_info['gt_lbl'], class_info['score'], drop_intermediate=True) if verbose: print("%s fpr:%s " % (class_name, fpr,)) print("%s tpr:%s " % (class_name, tpr,)) print("%s thresholds:%s " % (class_name, thresholds,)) if show: auc_score = calc_auc_score(fpr, tpr) show_roc_curve(fpr, tpr, auc_score, class_name) return fpr, tpr, thresholds
ROC曲線繪制方法:
def show_roc_curve(fpr, tpr, auc_score, class_name=None, save=False): plt.figure("%s ROC Curve" % class_name) plt.title('%s ROC Curve' % class_name) plt.xlabel('False Positive Rate') # 橫坐標是fpr plt.ylabel('True Positive Rate') # 縱坐標是tpr plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % auc_score) plt.legend(loc='lower right') plt.plot([0, 1], [0, 1], 'r--') plt.xlim([-0.1, 1.1]) plt.ylim([-0.1, 1.1]) if save: plt.savefig("./%s_auc_curve.png") plt.show()
AUC(ROC曲線的面積)
AUC (Area Under Curve
被定義為ROC曲線下的面積,顯然這個面積的數值不會大於1。又由於ROC曲線一般都處於y=x這條直線的上方,所以AUC的取值范圍一般在0.5和1之間。使用AUC值作為評價標准是因為很多時候ROC曲線並不能清晰的說明哪個分類器的效果更好,而作為一個數值,對應AUC更大的分類器效果更好。
sklearn實現:
roc_auc_score函數用於計算分類結果的ROC曲線的面積AUC。其原型為: sklearn.metrics.roc_auc_score(y_true, y_score, average='macro', sample_weight=None) 返回值:AUC值。 參數:參考 roc_curve。 #也可以通過如下方法計算得到 def calc_auc_score(fpr, tpr, verbose=False): res = auc(fpr, tpr) if verbose: print("auc:%s" % res) return res
AUC的計算有兩種方式: 梯形法和ROC
AUCH法,都是以逼近法求近似值,具體見wikipedia。
從AUC判斷分類器(預測模型)優劣的標准:
- AUC =
1,是完美分類器,采用這個預測模型時,存在至少一個閾值能得出完美預測。絕大多數預測的場合,不存在完美分類器。 - 0.5 < AUC <
1,優於隨機猜測。這個分類器(模型)妥善設定閾值的話,能有預測價值。 - AUC = 0.5,跟隨機猜測一樣(例:丟銅板),模型沒有預測價值。
- AUC < 0.5,比隨機猜測還差;但只要總是反預測而行,就優於隨機猜測。
三種AUC值示例:
簡單說:AUC值越大的分類器,正確率越高。
注:TPR、FPR、Precision、Recall的定義來對比,TPR、Recall的分母為樣本中正類的個數,FPR的分母為樣本中負類的個數,樣本一旦確定分母即為定值,因此三個指標的變化隨分子增加單調遞增。但是Precision的分母為預測為正類的個數,會隨着閾值的變化而變化,因此Precision的變化受TP和FP的綜合影響,不單調,變化情況不可預測。
多類別情況下ROC-AUC曲線繪制方法
def show_roc_info(classdict, show=True, save=False, figsize=(30, 22), fontsize=12): """ 多類別情況下計算展示每個類別的roc-auc圖 :param classdict: :param show: :param save: :param figsize: :param fontsize: :return: """ def sub_curve(fpr, tpr, auc_score, class_name, sub_idx): plt.subplot(6, 5, sub_idx) plt.title('%s ROC Curve' % class_name) plt.xlabel('False Positive Rate') # 橫坐標是fpr plt.ylabel('True Positive Rate') # 縱坐標是tpr plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % auc_score) plt.legend(loc='lower right') plt.plot([0, 1], [0, 1], 'r--') plt.xlim([-0.1, 1.1]) plt.ylim([-0.1, 1.1]) if show: plt.figure("Maoyan video class AUC Curve", figsize=figsize) plt.subplots_adjust(bottom=0.02, right=0.98, top=0.98) for idx, cls in enumerate(MY_CLASSES): if cls in classdict: fpr, tpr, thresholds = calc_roc_curve(classdict[cls], class_name=cls, show=False) auc_score = calc_auc_score(fpr, tpr) print("%s auc:\t\t\t%.4f" % (cls, auc_score)) if show: sub_curve(fpr, tpr, auc_score, cls, idx + 1) else: print("%s auc:\t\t\t0" % cls) sub_curve([0], [0], 0, cls, idx + 1) if save: plt.savefig("./maoyan_all_auc_curve.png") if show: plt.show()
實際使用技巧
對於ROC,一般來說,如果ROC是光滑的,那么基本可以判斷沒有太大的overfitting(比如圖中0.2到0.4可能就有問題,但是樣本太少了),這個時候調模型可以只看AUC,面積越大一般認為模型越好。
對於PRC(precision recall
curve)和ROC一樣,先看平滑不平滑(藍線明顯好些),再看誰上誰下(同一測試集上),一般來說,上面的比下面的好(綠線比紅線好)。當P和R越接近F1就越大,一般連接(0,0)和(1,1)的線和PRC重合的地方的F1是這條線最大的F1(光滑的情況下),此時的F1對於PRC就好象AUC對於ROC一樣。一個數字比一條線更方便調模型。
AP
嚴格的AP就是PR曲線下的面積,mAP就是所有類AP的算術平均。
但是一般都是用逼近的方法去估計這個面積。
sklearn實現:
sklearn.metrics.average_precision_score(y_true, y_score, average=‘macro’, sample_weight=None) 注意:此實現僅限於二進制分類任務或多標簽分類任務。 參數: y_true : array, shape = [n_samples] or [n_samples, n_classes] 真實標簽:取0和1 y_score : array, shape = [n_samples] or [n_samples, n_classes] 預測標簽:[0,1]之間的值。 可以是正類的概率估計、置信值,也可以是決策的非閾值度量(如某些分類器上的“決策函數”返回的) average : string, [None, ‘micro’, ‘macro’ (default), ‘samples’, ‘weighted’] sample_weight : array-like of shape = [n_samples], optional sample weights. #方法封裝 def calc_AP_score(class_info, class_name=None, average="macro", verbose=True): res = average_precision_score(class_info['gt_lbl'], class_info['score'], average=average) if verbose: print("%s ap:\t\t\t%.4f" % (class_name, res)) return res
AP計算方法
首先用訓練好的模型得到所有測試樣本的confidence
score,假設某類共有20個測試樣本,每個的id,confidence score和ground truth
label如下:
接着對confidence score排序得到:
計算出TopN對應Recall和precision。其中,對於某個recall值r,precision值取所有recall
>=r 中的最大值(這樣保證了p-r曲線是單調遞減的,避免曲線出現搖擺)這種方法叫做all-points-interpolation。這個AP值也就是PR曲線下的面積值。
例如:top5的recall=2/6, precision=2/5=0.4,當recall>=2/6時precision最大為1。
top6的recall=3/6, precision=3/6,在所有recall>=3/6時precision最大為4/7。
此時
AP=1*(1/6) + 1*(1/6)+ (4/7)*(1/6) + (4/7)*(1/6) + (5/11)*(1/6) + (6/16)* (1/6) = 0.6621
相應的Precision-Recall曲線(這條曲線是單調遞減的)如下:
mAP
mean Average Precision, 即各類別AP的平均值
用上述方法分別算出各個類的AP,然后取平均,就得到mAP了。mAP的好處是可以防止AP
bias到某一個數量較多的類別上去。
sklearn實現:
#mAP計算封裝 def calc_mAP_score(classdict, verbose=True): AP = [] for cls in MY_CLASSES: if cls in classdict: AP.append(calc_AP_score(classdict[cls], cls)) else: print("%s ap:\t 0" % cls) AP.append(0) mAP_score = np.mean(AP) if verbose: print("mAP:%s" % mAP_score) return mAP_score
多類別情況下計算展示每個類別的pr圖及對應的AP值
def show_mAP_info(classdict, show=True, save=False, figsize=(30, 22), fontsize=12): """ 多類別情況下計算展示每個類別的pr圖及對應的AP值 :param classdict: :param show: :param save: :param figsize: :param fontsize: :return: """ def sub_curve(recall, precision, class_name, ap_score, sub_idx): plt.subplot(6, 5, sub_idx) plt.title('%s PR Curve, ap:%.4f' % (class_name, ap_score)) plt.xlabel('Recall') plt.ylabel('Precision') plt.plot(recall, precision) AP = [] if show: plt.figure("Maoyan video class P-R Curve", figsize=figsize) plt.subplots_adjust(bottom=0.02, right=0.98, top=0.98) for idx, cls in enumerate(MY_CLASSES): if cls in classdict: ap_score = calc_AP_score(classdict[cls], cls) precision, recall, thresholds = calc_precision_recall_curve(classdict[cls], class_name=cls, show=False) if show: sub_curve(recall, precision, cls, ap_score, idx + 1) else: ap_score = 0 print("%s ap:\t\t\t0" % cls) sub_curve([0], [0], cls, ap_score, idx + 1) AP.append(ap_score) if save: plt.savefig("./maoyan_all_ap_curve.png") if show: plt.show() mAP_score = np.mean(AP) print("mAP:%s" % mAP_score) return mAP_score
多類別情況下獲取所需標簽信息的方法
def get_simple_result(df: DataFrame): y_true = [] y_pred = [] pred_scores = [] for idx, row in df.iterrows(): video_path = row['video_path'] gt_label = video_path.split("/")[-2] y_true.append(gt_label) pred_label = row['cls1'] y_pred.append(pred_label) pred_score = row['score1'] pred_scores.append(pred_score) return y_true, y_pred, pred_scores def get_multiclass_result(df: DataFrame): classdict = {} for idx, row in df.iterrows(): video_path = row['video_path'] gt_label = video_path.split("/")[-2] pred_label = row['cls1'] pred_score = row['score1'] if pred_label in classdict: classdict[pred_label]['score'].append(pred_score) classdict[pred_label]['gt_lbl'].append(1 if gt_label == pred_label else 0) else: classdict[pred_label] = {'score': [pred_score], 'gt_lbl': [1 if gt_label == pred_label else 0]} return classdict
對數損失(log_loss)
from sklearn.metrics import log_loss log_loss(y_true,y_pred)
分類指標的文本報告(classification_report)
classification_report函數用於顯示主要分類指標的文本報告。在報告中顯示每個類的精確度,召回率,F1值等信息。
sklearn實現:
sklearn.metrics.classification_report(y_true, y_pred, labels=None, target_names=None, sample_weight=None, digits=2) 返回值:一個格式化的字符串,給出了分類評估報告。 參數: y_true:真實的標記集合。 y_pred:預測的標記集合。 labels:一個列表,指定報告中出現哪些類別。 target_names:一個列表,指定報告中類別對應的顯示出來的名字。 digits:用於格式化報告中的浮點數,保留幾位小數。 sample_weight:樣本權重,默認每個樣本的權重為 1 分類評估報告的內容如下,其中: precision列:給出了查准率。它依次將類別 0 作為正類,類別 1 作為正類... recall列:給出了查全率。它依次將類別 0 作為正類,類別 1 作為正類... F1列:給出了F1值。 support列:給出了該類有多少個樣本。 avg / total行: 對於precision,recall,f1給出了該列數據的算術平均。 對於support列,給出了該列的算術和(其實就等於樣本集總樣本數量)。
使用總結
- 對於分類模型,AUC、ROC曲線(FPR和TPR的點連成的線)、PR曲線(准確率和召回率的點連成的線)是綜合評價模型區分能力和排序能力的指標,而精確率、召回率和F1值是在確定閾值之后計算得到的指標。
- 對於同一模型,PRC和ROC曲線都可以說明一定的問題,而且二者有一定的相關性,如果想評測模型效果,也可以把兩條曲線都畫出來綜合評價。
- 對於有監督的二分類問題,在正負樣本都足夠的情況下,可以直接用ROC曲線、AUC評價模型效果;而在樣本極不均衡的情況下,PR曲線更能反應模型效果。
- 在確定閾值過程中,可以根據Precision、Recall或者F1來評價模型的分類效果。對於多分類問題,可以對每一類分別計算Precision、Recall和F1,綜合作為模型評價指標。
回歸模型
平均絕對誤差(MAE mean absolute error)
sklearn實現:
mean_absolute_error函數用於計算回歸預測誤差絕對值的均值(mean absolute error:MAE),其原型為: sklearn.metrics.mean_absolute_error(y_true, y_pred, sample_weight=None, multioutput='uniform_average') 返回值:預測誤差絕對值的均值。 參數: y_true:真實的標記集合。 y_pred:預測的標記集合。 multioutput:指定對於多輸出變量的回歸問題的誤差類型。可以為: 'raw_values':對每個輸出變量,計算其誤差 。 'uniform_average':計算其所有輸出變量的誤差的平均值。 sample_weight:樣本權重,默認每個樣本的權重為 1。
均方誤差(MSE mean squared error)
mean_squared_error函數用於計算回歸預測誤差平方的均值(mean square
error:MSE),其原型為:
sklearn.metrics.mean_squared_error(y_true, y_pred, sample_weight=None, multioutput='uniform_average') 返回值:預測誤差的平方的平均值。 參數:參考mean_absolute_error 。

均方根誤差(RMSE root mean squared error)
歸一化均方根誤差(NRMSE normalized root mean squared error)歸一化均方根誤差
決定系數(R2)
R2是多元回歸中的回歸平方和占總平方和的比例,它是度量多元回歸方程中擬合程度的一個統計量,反映了在因變量y的變差中被估計的回歸方程所解釋的比例。
R2越接近1,表明回歸平方和占總平方和的比例越大,回歸線與各觀測點越接近,用x的變化來解釋y值變差的部分就越多,回歸的擬合程度就越好。
from sklearn.metrics import r2_score r2_score(y_true, y_pred, sample_weight=None, multioutput='uniform_average')

參考以下文章,自己總結的深度學習常用評估指標:
Terry:https://zhuanlan.zhihu.com/p/86120987
cicada:https://zhuanlan.zhihu.com/p/267901426
https://www.pythonf.cn/read/128402
路遠: https://www.zhihu.com/question/30643044