評價指標
准確率 Accuracy
,混淆矩陣 Confusion Matrix
,精確率Precision
,召回率Recall
,平均正確率AP
,mean Average Precision mAP
,交除並IoU
,ROC + AUC,非極大值抑制(NMS)
交並比-IOU
預測框與標注框的交集與並集之比,數值越大表示該檢測器的性能越好。
一般情況下對於檢測框的判定都會存在一個閾值,也就是IoU
的閾值,一般可以設置當IoU
的值大於0.5
的時候,則可認為檢測到目標物體。
def box_iou_calc(boxes1, boxes2):
# https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py
"""
Return intersection-over-union (Jaccard index) of boxes.
Both sets of boxes are expected to be in (x1, y1, x2, y2) format.
Arguments:
boxes1 (Array[N, 4])
boxes2 (Array[M, 4])
Returns:
iou (Array[N, M]): the NxM matrix containing the pairwise
IoU values for every element in boxes1 and boxes2
This implementation is taken from the above link and changed so that it only uses numpy..
"""
def box_area(box):
# box = 4xn
return (box[2] - box[0]) * (box[3] - box[1])
area1 = box_area(boxes1.T)
area2 = box_area(boxes2.T)
lt = np.maximum(boxes1[:, None, :2], boxes2[:, :2]) # [N,1,2] and [M,2] >>> [N,M,2] # 交集左下角
print(lt.shape)
rb = np.minimum(boxes1[:, None, 2:], boxes2[:, 2:]) # [N,M,2] # 交集右上角
inter = np.prod(np.clip(rb - lt, a_min=0, a_max=None), 2) # [N,M] 坐標相乘,且最小為0
return inter / (area1[:, None] + area2 - inter) # iou = inter / (area1 + area2 - inter)
# torch 版本
def box_iou(box1, box2):
# https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py
"""
Return intersection-over-union (Jaccard index) of boxes.
Both sets of boxes are expected to be in (x1, y1, x2, y2) format.
Arguments:
box1 (Tensor[N, 4])
box2 (Tensor[M, 4])
Returns:
iou (Tensor[N, M]): the NxM matrix containing the pairwise
IoU values for every element in boxes1 and boxes2
"""
def box_area(box):
# box = 4xn
return (box[2] - box[0]) * (box[3] - box[1])
area1 = box_area(box1.T)
area2 = box_area(box2.T)
# inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)
inter = (torch.min(box1[:, None, 2:], box2[:, 2:]) - torch.max(box1[:, None, :2], box2[:, :2])).clamp(0).prod(2)
iou = inter / (area1[:, None] + area2 - inter)
return iou # iou = inter / (area1 + area2 - inter)
混淆矩陣-Confusion Matrix
混淆矩陣是ROC曲線繪制的基礎,同時它也是衡量分類型模型准確度中最基本,最直觀,計算最簡單的方法。
混淆矩陣中的橫軸是模型預測的類別數量統計,縱軸是數據真實標簽的數量統計。
實驗預測 | 實驗預測 | 實驗預測 | ||
---|---|---|---|---|
car | person | char | ||
真實 | car | 5 | 3 | 0 |
真實 | person | 4 | 8 | 0 |
真實 | char | 0 | 2 | 6 |
對角線,表示模型預測和數據標簽一致的數目,所以對角線之和除以測試集總數就是 准確率。對角線上數字越大越好,在可視化結果中顏色越深,說明模型在該類的預測准確率越高。如果按行來看,每行不在對角線位置的就是錯誤預測的類別。總的來說,我們希望對角線越高越好,非對角線越低越好。
- 預測值為正例,記為P(Positive)
- 預測值為反例,記為N(Negative)
- 預測值與真實值相同,記為T(True)
- 預測值與真實值相反,記為F(False)
對應對car
這個類別的混淆表格為
預測為正P | 預測為負數N | |
---|---|---|
真實為正 | TP=8 | FN=3 |
真實為負 | FP=4 | TN=16 |
對應person
這類別的混淆表格為
預測為正P | 預測為負數N | |
---|---|---|
真實為正 | TP=8 | FN=4 |
真實為負 | FP=5 | TN=11 |
- TP-預測為正例,實際為正例——正樣本 正確識別為正
- TN-預測為負例,實際為負例——負樣本 正確識別為負
- FP-預測為正例,實際為負例——正樣本 錯誤識別為負
- FN-預測為負例,實際為正例——負樣本 錯誤識別為正
記憶技巧
-
第 1 個字母表示算法預測正確或者錯誤,即 True、False 描述的是這個分類器是否判斷正確。
-
第 2 個字母表示算法預測的結果,即 Positive、Negative 是這個分類器的分類結果
TP+TN+FP+FN= 總樣本數
P = TP + FN :所有 "實際為正例" 的樣本數
N = FP + TN :所有 "實際 為負例" 的樣本數
准確率(Acc)
准確率一般用來評估模型的全局准確程度,不能包含太多信息,無法全面評價一個模型性能。
准確率accuracy
常見的評價指標,被分對的樣本數除以所有的樣本數,通常來說,准確率越高,分類器越好
公式
accuracy = (TP+TN)/(TP+TN+FP+FN)
- 分母是全部四種數據;分子中第一個字母是 T 表示 "算法預測正確了"。
特點
准確率有一個缺點,就是數據的樣本不均衡,這個指標是不能評價模型的性能優劣的。
假如一個測試集有正樣本99個,負樣本1個。我們設計的模型是個無腦模型,即把所有的樣本都預測為正樣本,那么模型的Accuracy為99%,看評價指標,模型的效果很好,但實際上模型沒有任何預測能力。
精准率(Precision)
針對預測,又稱為查准率
Precision 在預測的結果來統計, 就是在識別出來的圖片中,即在模型預測為正樣本的結果中,真正是正樣本所占的百分比。或者說是 在預測為正樣本的結果中,有多少是准確的
公式
分母中, TP表示 : 算法預測正確 & 預測的是正例,FP表示 : 算法預測錯誤 & 預測的是正例(實際是負例)
特點
分類閾值較高,需要盡可能地把所需的類別檢測准確,而不在乎這些類別是否都被檢測出來。比如對於罪犯的預測,我們希望預測結果是非常准確的,即使放過了一些真正的罪犯,也不能錯怪一個好人。
召回率(Recall)
針對原始樣本真實數據的一個評價指標,又稱為查全率
Recall 是在實際為正樣本中,被預測為正樣本所占的百分比
預測樣本中實際正樣本數 / 預測的樣本數即 Recall=TP/(TP+FN)
找的全的比例
公式
特點
召回率分類閾值較低。盡量檢測數據,不遺漏數據,所謂的寧肯錯殺一千,不肯放過一個。
比如對於地震的預測,希望每次地震都能被預測出來,這個時候可以犧牲precision。假如一共發生了10次地震,我們情願發出1000次警報
精准率 VS 召回率
關注點不同
召回率是覆蓋面的度量,度量有多個真實正例被預測為正例。精度是精確性的度量,表示被預測為正例的示例中實際為正例的比例。
不同的應用場景下,我們的關注點不同
相互矛盾
- recall和precision是相互矛盾的。如果想要更高的recall,那么就要讓模型的預測能覆蓋到更多的樣本,但是這樣模型就更有可能犯錯,也就是說precision會比較低。如果模型很保守,只能檢測出它很確定的樣本,那么其precision會很高,但是recall會相對低。
- recall(TPR)的分母是樣本中正類的個數,因此樣本一旦確定,其分母即為定值,也就是說recall的變化隨分子增加而單調遞增;precision的分母是樣本中預測為正類的個數,其會隨着分類閾值的變化而變化,因此Precision的變化受TP和FP的綜合影響,不單調,變化情況不可預測。
Precision-recall 曲線
改變識別閾值,使得系統依次能夠識別前K張圖片,閾值的變化同時會導致Precision與Recall值發生變化,從而得到曲線。
如果一個分類器的性能比較好,那么它應該有如下的表現:
在Recall值增長的同時,Precision的值保持在一個很高的水平。
而性能比較差的分類器可能會損失很多Precision值才能換來Recall值的提高。
通常情況下,文章中都會使用Precision-recall曲線,來顯示出分類器在Precision與Recall之間的權衡。
PR
曲線中precision
為縱坐標,recall
為橫坐標
如果模型的精度越高,召回率越高,那么模型的性能越好。也就是說PR
曲線下面的面積越大,模型的性能越好
PR
曲線反映了分類器對正例的識別准確程度和對正例的覆蓋能力之間的權衡。
F1 Score
在一些場景下要兼顧精准率和召回率,就有 F1 score。F1值就是精確值和召回率的調和均值
准確率和召回率的調和平均
F1
分數(F1-score
)是分類問題的一個衡量指標。F1
分數認為召回率和精度同等重要, 一些多分類問題的機器學習競賽,常常將F1-score
作為最終測評的方法。它是精確率和召回率的調和平均數,最大為1,最小為0
F1 = 2TP/(2TP+FP+FN)
公式
此外還有F2
分數和F0.5
分數。F2
分數認為召回率的重要程度是精度的2倍,而F0.5
分數認為召回率的重要程度是精度的一半
特點
調和平均數的性質就是,只有當精准率和召回率二者都非常高的時候,它們的調和平均才會高
Average-Precision(AP)
AP
即Average Precision
,稱為平均精准率,是對不同召回率點上的准確率進行平均,在PR
曲線圖上表現為PR
曲線下面的面積。AP
的值越大,則說明模型的平均准確率越高。
AP就是Precision-recall 曲線下面的面積,通常來說一個越好的分類器,AP值越高。
mean Average Precision(mAP)
MAP 均值平均精度
mAP = 所有類別的平均精度求和除以所有類別
- mAP: mean Average Precision, 即各類別AP的平均值
- AP: PR曲線下面積
- PR曲線: Precision-Recall曲線
- Precision: TP / (TP + FP)
- Recall: TP / (TP + FN)
- TP: IoU>0.5的檢測框數量(同一Ground Truth只計算一次)
- FP: IoU<=0.5的檢測框,或者是檢測到同一個GT的多余檢測框的數量
- FN: 沒有檢測到的GT的數量
公式
mAP
衡量的是的模型在所有類別上的好壞,是目標檢測中一個最為重要的指標,一般看論文或者評估一個目標檢測模型,都會看這個值,這個值是在0-1
直接,越大越好。
mAP 的計算大致可以分解為以下幾步:
階段 | 輸出 | 關鍵變量 |
---|---|---|
針對單個目標 | TP、FP、FN | IOU(交並比) |
針對單個類別 | PR-Curve、AP | Confidence(置信度) |
針對測試集全集 | mAP |
對於任何算法,評估指標需要知道ground truth(真實標簽)數據。 我們只知道訓練、驗證和測試數據集的ground truth。對於目標檢測問題,ground truth包括圖像中物體的類別以及該圖像中每個物體的真實邊界框。
我們首先需要判斷每個檢測的正確性。這里采用IoU(Intersection over Union),它可以作為評價邊界框正確性的度量指標
def compute_ap(gt_boxes, gt_class_ids,
pred_boxes, pred_class_ids, pred_scores,
iou_threshold=0.5):
"""Compute Average Precision at a set IoU threshold (default 0.5).
Returns:
mAP: Mean Average Precision
precisions: List of precisions at different class score thresholds.
recalls: List of recall values at different class score thresholds.
overlaps: [pred_boxes, gt_boxes] IoU overlaps.
"""
# Trim zero padding and sort predictions by score from high to low
gt_boxes = trim_zeros(gt_boxes)
pred_boxes = trim_zeros(pred_boxes)
pred_scores = pred_scores[:pred_boxes.shape[0]]
indices = np.argsort(pred_scores)[::-1]
pred_boxes = pred_boxes[indices]
pred_class_ids = pred_class_ids[indices]
pred_scores = pred_scores[indices]
# Compute IoU overlaps [pred_boxes, gt_boxes]
overlaps = compute_overlaps(pred_boxes, gt_boxes)
# Loop through ground truth boxes and find matching predictions
match_count = 0
pred_match = np.zeros([pred_boxes.shape[0]])
gt_match = np.zeros([gt_boxes.shape[0]])
for i in range(len(pred_boxes)):
# Find best matching ground truth box
sorted_ixs = np.argsort(overlaps[i])[::-1]
for j in sorted_ixs:
# If ground truth box is already matched, go to next one
if gt_match[j] == 1:
continue
# If we reach IoU smaller than the threshold, end the loop
iou = overlaps[i, j]
if iou < iou_threshold:
break
# Do we have a match?
if pred_class_ids[i] == gt_class_ids[j]:
match_count += 1
gt_match[j] = 1
pred_match[i] = 1
break
# Compute precision and recall at each prediction box step
precisions = np.cumsum(pred_match) / (np.arange(len(pred_match)) + 1)
recalls = np.cumsum(pred_match).astype(np.float32) / len(gt_match)
# Pad with start and end values to simplify the math
precisions = np.concatenate([[0], precisions, [0]])
recalls = np.concatenate([[0], recalls, [1]])
# Ensure precision values decrease but don't increase. This way, the
# precision value at each recall threshold is the maximum it can be
# for all following recall thresholds, as specified by the VOC paper.
for i in range(len(precisions) - 2, -1, -1):
precisions[i] = np.maximum(precisions[i], precisions[i + 1])
# Compute mean AP over recall range
indices = np.where(recalls[:-1] != recalls[1:])[0] + 1
mAP = np.sum((recalls[indices] - recalls[indices - 1]) *
precisions[indices])
return mAP, precisions, recalls,