摘要:這篇文章主要向大家介紹深度學習分類任務評價名額,主要内容包括基礎應用、實用技巧、原理機制等方面,希望對大家有所幫助。
作者: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%的準确率。是以,當不同類别的樣本比例非常不均衡時,占比大的類别往往成為影響準确率的最主要因素。
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次,隻預測到了兩次會漲,預測這兩次都對了,那麼就是我們想要的精準度高,此時召回率不重要。
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%。
召回率的應用場景:比如拿網貸違約率為例,相對好使用者,我們更關心壞使用者,不能錯放過任何一個壞使用者。因為如果我們過多的将壞使用者當成好使用者,這樣後續可能發生的違約金額會遠超過好使用者償還的借貸利息金額,造成嚴重償失。召回率越高,代表實際壞使用者被預測出來的機率越高,它的含義類似:甯可錯殺一千,絕不放過一個。
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.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做出最終判斷,此時就需要根據不同場景選擇其他合适的名額做出評判。
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
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更大的分類器效果更好。
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.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到某一個數量較多的類别上去。
#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.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)
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')