來(lái)源:小白玩轉(zhuǎn)python
介紹
YOLO長(zhǎng)期以來(lái)一直是目標(biāo)檢測(cè)任務(wù)的首選模型之一。它既快速又準(zhǔn)確。此外,其API簡(jiǎn)潔易用。運(yùn)行訓(xùn)練或推斷作業(yè)所需的代碼行數(shù)有限。在2023年下半年,YOLOv8在框架中引入了姿態(tài)估計(jì)后,該框架現(xiàn)在支持最多四個(gè)任務(wù),包括分類、目標(biāo)檢測(cè)、實(shí)例分割和姿態(tài)估計(jì)。
在本文中,我們將詳細(xì)介紹YOLOv8中使用的五個(gè)損失函數(shù)。請(qǐng)注意,我們將僅討論YOLOv8倉(cāng)庫(kù)中配置的默認(rèn)損失函數(shù)。此外,我們還將僅關(guān)注代表性參數(shù),跳過一些標(biāo)量和常數(shù)以進(jìn)行歸一化或縮放,以便更好地理解。YOLOv8中對(duì)應(yīng)的任務(wù)和損失函數(shù)可見于圖1。接下來(lái)我們將分別對(duì)每一個(gè)進(jìn)行討論。
IoU損失
cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1) # convex (smallest enclosing box) width ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1) # convex height if CIoU or DIoU: # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1 c2 = cw ** 2 + ch ** 2 + eps # convex diagonal squared rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4 # center dist ** 2 if CIoU: # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47 v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2) with torch.no_grad(): alpha = v / (v - iou + (1 + eps)) return iou - (rho2 / c2 + v * alpha) # CIoU
當(dāng)考慮評(píng)估邊界框準(zhǔn)確度的方式時(shí),交并比(IoU)指標(biāo)可能是大多數(shù)人首先想到的一個(gè)指標(biāo)。IoU度量了預(yù)測(cè)的邊界框與實(shí)際邊界框之間的重疊程度。它也可以作為一個(gè)損失函數(shù),只需將IoU轉(zhuǎn)換為1-IoU。
在YOLOv8中,修訂后的版本,完全I(xiàn)oU(CIoU)1被應(yīng)用于衡量預(yù)測(cè)邊界框與實(shí)際邊界框之間的差異。CIoU是一個(gè)綜合性指標(biāo),它考慮了邊界框之間的三個(gè)屬性:
重疊比
中心點(diǎn)之間的距離
長(zhǎng)寬比
CIoU的方程可在圖2右側(cè)找到。重疊比、中心點(diǎn)距離和長(zhǎng)寬比這三個(gè)因素分別由方程中的各項(xiàng)表示。方程中涉及的關(guān)鍵參數(shù)在左側(cè)的圖中進(jìn)行了說明,其中p和g表示預(yù)測(cè)和實(shí)際情況,b、w和h分別是相應(yīng)邊界框的中心、寬度和高度。參數(shù)c是包圍邊界框的對(duì)角線(灰色虛線矩形)而ρ是歐氏距離。除了分類任務(wù)外,IoU損失在YOLOv8中的所有其他任務(wù)中都會(huì)應(yīng)用。
分布焦點(diǎn)損失(DFL)
def _df_loss(pred_dist, target): """Return sum of left and right DFL losses.""" # Distribution Focal Loss (DFL) proposed in Generalized Focal Loss https://ieeexplore.ieee.org/document/9792391 tl = target.long() # target left tr = tl + 1 # target right wl = tr - target # weight left wr = 1 - wl # weight right return (F.cross_entropy(pred_dist, tl.view(-1), reduction='none').view(tl.shape) * wl + F.cross_entropy(pred_dist, tr.view(-1), reduction='none').view(tl.shape) * wr).mean(-1, keepdim=True)
另一個(gè)與邊界框相關(guān)的損失函數(shù)是分布焦點(diǎn)損失(DFL)2。DFL關(guān)注的是邊界框回歸的分布差異。YOLOv8中的網(wǎng)絡(luò)不是直接預(yù)測(cè)邊界框,而是預(yù)測(cè)邊界框的概率分布。它旨在解決邊界模糊或部分遮擋的挑戰(zhàn)性對(duì)象。
關(guān)鍵點(diǎn)損失
loss[1] += self.keypoint_loss(pred_kpt, gt_kpt, kpt_mask, area) area:bounding box area class KeypointLoss(nn.Module): def forward(self, pred_kpts, gt_kpts, kpt_mask, area): """Calculates keypoint loss factor and Euclidean distance loss for predicted and actual keypoints.""" d = (pred_kpts[..., 0] - gt_kpts[..., 0]) ** 2 + (pred_kpts[..., 1] - gt_kpts[..., 1]) ** 2 kpt_loss_factor = (torch.sum(kpt_mask != 0) + torch.sum(kpt_mask == 0)) / (torch.sum(kpt_mask != 0) + 1e-9) # e = d / (2 * (area * self.sigmas) ** 2 + 1e-9) # from formula e = d / (2 * self.sigmas) ** 2 / (area + 1e-9) / 2 # from cocoeval return kpt_loss_factor * ((1 - torch.exp(-e)) * kpt_mask).mean()
在YOLOv8中,首次將姿態(tài)估計(jì)任務(wù)納入到框架中。姿態(tài)由一組關(guān)鍵點(diǎn)的坐標(biāo)和順序定義。關(guān)鍵點(diǎn)損失監(jiān)控了預(yù)測(cè)和實(shí)際關(guān)鍵點(diǎn)之間的相似性。兩個(gè)對(duì)應(yīng)關(guān)鍵點(diǎn)之間的歐幾里得距離是關(guān)鍵點(diǎn)損失的主要組成部分。此外,每個(gè)關(guān)鍵點(diǎn)都帶有一個(gè)權(quán)重σ,定義了關(guān)鍵點(diǎn)的重要性,默認(rèn)值為1/關(guān)鍵點(diǎn)數(shù)。例如,如果姿態(tài)有四個(gè)關(guān)鍵點(diǎn),則所有關(guān)鍵點(diǎn)的權(quán)重為1/4 = 0.25。
關(guān)鍵點(diǎn)目標(biāo)損失
import torch.nn as nn loss[2] = nn.BCEWithLogitsLoss(pred_kpt[..., 2], kpt_mask.float())
在大多數(shù)姿態(tài)估計(jì)訓(xùn)練中,我們可以定義每個(gè)關(guān)鍵點(diǎn)的可見性。Python腳本中的參數(shù)kpt_mask攜帶了我們?cè)?a target="_blank">標(biāo)簽中定義的可見性(1/0)。關(guān)鍵點(diǎn)目標(biāo)損失計(jì)算關(guān)鍵點(diǎn)存在的距離。在YOLOv8中,距離由預(yù)測(cè)值和實(shí)際值的二元交叉熵(BCE)測(cè)量。
分類損失和掩碼損失
import torch.nn as nn loss[3] = nn.BCEWithLogitLoss(pred_scores, target_scores.to(dtype)).sum() / target_scores_sum # BCE
分類損失是涉及到所有任務(wù)的唯一損失函數(shù)。無(wú)論我們是在進(jìn)行分類、目標(biāo)檢測(cè)、分割還是姿態(tài)估計(jì),圖像或特定對(duì)象的類別(例如貓、狗、人等)的推斷結(jié)果之間的距離都是通過二元交叉熵(BCE)計(jì)算的。
它還適用于實(shí)例分割中的掩碼損失。掩碼損失將每個(gè)像素視為一個(gè)對(duì)象,并計(jì)算相關(guān)的BCE值。在圖5中計(jì)算了一個(gè)3x3的預(yù)測(cè)掩碼和相應(yīng)的掩碼損失。
總損失
# yolo/cfg/default.yaml ... box: 7.5 # box loss gain cls: 0.5 # cls loss gain (scale with pixels) dfl: 1.5 # dfl loss gain pose: 12.0 # pose loss gain kobj: 1.0 # keypoint obj loss gain ...
好了,以上我們已經(jīng)介紹了所有六個(gè)損失。在網(wǎng)絡(luò)應(yīng)用反向傳播并更新其參數(shù)之前,將損失與相應(yīng)的權(quán)重相加。權(quán)重在配置文件default.yaml中定義,如上所示。如果您想在訓(xùn)練階段動(dòng)態(tài)調(diào)整權(quán)重,您可以考慮直接在存儲(chǔ)庫(kù)中使用下面提供的代碼片段。
loss[0] *= self.hyp.box # box gain loss[1] *= self.hyp.pose / batch_size # pose gain loss[2] *= self.hyp.kobj / batch_size # kobj gain loss[3] *= self.hyp.cls # cls gain loss[4] *= self.hyp.dfl # dfl gain return loss.sum() * batch_size, loss.detach()
總結(jié)
YOLO是一個(gè)為目標(biāo)檢測(cè)任務(wù)而知名的框架。除了在效率和準(zhǔn)確性方面的表現(xiàn)之外,它還在不斷更新最新的研究成果。這是一個(gè)讓計(jì)算機(jī)視覺從業(yè)者跟蹤和學(xué)習(xí)入選技術(shù)的好框架。損失函數(shù)在模型訓(xùn)練中起著重要作用,并決定了最終的準(zhǔn)確性。
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4327瀏覽量
62569 -
目標(biāo)檢測(cè)
+關(guān)注
關(guān)注
0文章
209瀏覽量
15605 -
python
+關(guān)注
關(guān)注
56文章
4792瀏覽量
84626
原文標(biāo)題:YOLOv8中的損失函數(shù)解析
文章出處:【微信號(hào):vision263com,微信公眾號(hào):新機(jī)器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論