YOLOV5代碼詳解之損失函數(shù)的計算
摘要:
神經(jīng)網(wǎng)絡的訓練的主要流程包括圖像輸入神經(jīng)網(wǎng)絡, 得到模型的輸出結果,計算模型的輸出與真實值的損失, 計算損失值的梯度,最后用梯度下降算法更新模型參數(shù)。損失函數(shù)值的計算是非常關鍵的一個步驟。
本博客將對yolov5損失值的計算過程代碼的實現(xiàn)做簡要的理解。
def compute_loss(p, targets, model): # predictions, targets, model device = targets.device lcls, lbox, lobj = torch.zeros(1, device=device), torch.zeros(1, device=device), torch.zeros(1, device=device) tcls, tbox, indices, anchors = build_targets(p, targets, model) # targets h = model.hyp # hyperparameters # Define criteria BCEcls = nn.BCEWithLogitsLoss(pos_weight=torch.Tensor([h['cls_pw']])).to(device) BCEobj = nn.BCEWithLogitsLoss(pos_weight=torch.Tensor([h['obj_pw']])).to(device) # Class label smoothing https://arxiv.org/pdf/1902.04103.pdf eqn 3 cp, cn = smooth_BCE(eps=0.0) # Focal loss g = h['fl_gamma'] # focal loss gamma if g > 0: BCEcls, BCEobj = FocalLoss(BCEcls, g), FocalLoss(BCEobj, g) 。。。。。。
yolov5代碼用IOU指標評價目標框和預測框的位置損失損失。yolov5代碼用nn.BCEWithLogitsLoss或FocalLoss評價目標框和預測框的類損失和置信度損失 .
yolov5代碼用寬高比選擇對應真實框的預測框,且每一個真實框對應三個預測框 。
1、位置損失
yolov5代碼用IOU值評價預測框和真實框的位置損失, 本文介紹CIoU指標.
公式如下截圖:
公式中參數(shù)代表的意義如下:
IOU: 預測框和真實框的叫并比
v是衡量長寬比一致性的參數(shù),我們也可以定義為:
代碼實現(xiàn):
iou = bbox_iou(pbox.T, tbox[i], x1y1x2y2=False, CIoU=True) # iou(prediction, target) lbox += (1.0 - iou).mean() # iou loss
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-9): # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4 box2 = box2.T # Get the coordinates of bounding boxes if x1y1x2y2: # x1, y1, x2, y2 = box1 b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3] b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3] else: # transform from xywh to xyxy b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2 b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2 b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2 b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2 # Intersection area inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \ (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0) # Union Area w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + eps w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps union = w1 * h1 + w2 * h2 - inter + eps iou = inter / union if GIoU or DIoU or CIoU: cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1) # convex (smallest enclosing box) width ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, 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 distance squared if DIoU: return iou - rho2 / c2 # DIoU elif CIoU: # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47 v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2) with torch.no_grad(): alpha = v / ((1 + eps) - iou + v) return iou - (rho2 / c2 + v * alpha) # CIoU else: # GIoU https://arxiv.org/pdf/1902.09630.pdf c_area = cw * ch + eps # convex area return iou - (c_area - union) / c_area # GIoU else: return iou # IoU
2、置信度損失和類損失
yolov5代碼用nn.BCEWithLogitsLoss或FocalLoss評價目標框和預測框的類損失和置信度損失,本節(jié)一一介紹這兩個損失函數(shù)。
- nn.BCEWithLogitsLoss:
首先對預測輸出作sigmoid變換,然后求變換后的結果與真實值的二值交叉熵.
假設預測輸出是3分類,預測輸出:
預測輸出sigmoid變換:
假設真實輸出是:
兩者的二值交叉熵的計算方法:
接口函數(shù)驗證下上面的結果:
- FocalLoss損失:
FocalLoss損失考慮的是:目標檢測中正負樣本嚴重不均衡的一種策略。該損失函數(shù)的設計思想類似于boosting,降低容易分類的樣本對損失函數(shù)的影響,注重較難分類的樣本的訓練.
簡而言之,FocalLoss更加關注的是比較難分的樣本,何謂難分?若某一個真實類預測的概率只有0.2,我們認為它比較難分,相反若該真實類的預測概率是0.95,則容易分類.
FocalLoss通過提高難分類別的損失函數(shù)來實現(xiàn),公式如下:
圖像如下:
可以看出預測真實類概率越大,則損失函數(shù)越小,即實現(xiàn)了之前的想法.
為了能夠平衡正負樣本的重要性,我們可以給各個類別添加一個權重常數(shù) α ,比如想使正樣本初始權重為0.8,負樣本就為0.2.
代碼實現(xiàn)為:
class FocalLoss(nn.Module): # Wraps focal loss around existing loss_fcn(), i.e. criteria = FocalLoss(nn.BCEWithLogitsLoss(), gamma=1.5) def __init__(self, loss_fcn, gamma=1.5, alpha=0.25): super(FocalLoss, self).__init__() self.loss_fcn = loss_fcn # must be nn.BCEWithLogitsLoss() self.gamma = gamma self.alpha = alpha self.reduction = loss_fcn.reduction self.loss_fcn.reduction = 'none' # required to apply FL to each element def forward(self, pred, true): loss = self.loss_fcn(pred, true) # p_t = torch.exp(-loss) # loss *= self.alpha * (1.000001 - p_t) ** self.gamma # non-zero power for gradient stability # TF implementation https://github.com/tensorflow/addons/blob/v0.7.1/tensorflow_addons/losses/focal_loss.py pred_prob = torch.sigmoid(pred) # prob from logits p_t = true * pred_prob + (1 - true) * (1 - pred_prob) alpha_factor = true * self.alpha + (1 - true) * (1 - self.alpha) modulating_factor = (1.0 - p_t) ** self.gamma loss *= alpha_factor * modulating_factor if self.reduction == 'mean': return loss.mean() elif self.reduction == 'sum': return loss.sum() else: # 'none' return loss
其中成員函數(shù)loss_fcn為nn.BCEWithLogitsLoss。
總結
到此這篇關于YOLOV5代碼詳解之損失函數(shù)計算的文章就介紹到這了,更多相關YOLOV5損失函數(shù)計算內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python利用PsUtil實現(xiàn)實時監(jiān)控系統(tǒng)狀態(tài)
PSUtil是一個跨平臺的Python庫,用于檢索有關正在運行的進程和系統(tǒng)利用率(CPU,內存,磁盤,網(wǎng)絡,傳感器)的信息。本文就來用PsUtil實現(xiàn)實時監(jiān)控系統(tǒng)狀態(tài),感興趣的可以跟隨小編一起學習一下2023-04-04python使用matplotlib的savefig保存時圖片保存不完整的問題
這篇文章主要介紹了python使用matplotlib的savefig保存時圖片保存不完整的問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01詳解用pyecharts Geo實現(xiàn)動態(tài)數(shù)據(jù)熱力圖城市找不到問題解決
這篇文章主要介紹了詳解用pyecharts Geo實現(xiàn)動態(tài)數(shù)據(jù)熱力圖城市找不到問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-06-06