摘要:這篇文章主要向你們介紹深度學習分類任務評價指標,主要內容包括基礎應用、實用技巧、原理機制等方面,但願對你們有所幫助。
本文分享自華爲雲社區《深度學習分類任務經常使用評估指標》,原文做者:lutianfei 。python
這篇文章主要向你們介紹深度學習分類任務評價指標,主要內容包括基礎應用、實用技巧、原理機制等方面,但願對你們有所幫助。git
分類模型
混淆矩陣
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()
混淆矩陣是監督學習中的一種可視化工具,主要用於比較分類結果和實例的真實信息。矩陣中的每一行表明實例的預測類別,每一列表明實例的真實類別。app
理解方法:ide
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