in utils/loss.py [0:0]
def __call__(self, p, targets, imgsz=None, masks=None, m_weights=None): # predictions, targets, model
p_det, p_seg = p
offsets = []
device = targets.device
lcls, lbox, lobj = torch.zeros(1, device=device), torch.zeros(1, device=device), torch.zeros(1, device=device)
lpixl, larea, ldist = torch.zeros(1, device=device), torch.zeros(1, device=device), torch.zeros(1, device=device)
if p_det is not None and p_det[0] is not None and p_det[1] is not None: # stupid
# ta = time_synchronized()
if isinstance(p_det, tuple):
p, offsets = p_det
tcls, tbox, indices, anchors = self.build_patch_targets(offsets, targets, imgsz) # targets
else:
p = p_det
tcls, tbox, indices, anchors = self.build_targets(p, targets)
# print(f'build_targets: {time_synchronized() - ta:.3f}s.')
# Losses
for i, pi in enumerate(p): # layer index, layer predictions
b, a, gj, gi = indices[i] # image, anchor, gridy, gridx
tobj = torch.zeros_like(pi[..., 0], device=device) # target obj
n = b.shape[0] # number of targets
if n:
ps = pi[b, a, gj, gi] # prediction subset corresponding to targets
# Regression
pxy = ps[:, :2].sigmoid() * 2. - 0.5
pwh = (ps[:, 2:4].sigmoid() * 2) ** 2 * anchors[i]
pbox = torch.cat((pxy, pwh), 1) # predicted box
iou = bbox_iou(pbox.T, tbox[i], x1y1x2y2=False, CIoU=True) # iou(prediction, target)
lbox += (1.0 - iou).mean() # iou loss
# Objectness
tobj[b, a, gj, gi] = (1.0 - self.gr) + self.gr * iou.detach().clamp(0).type(tobj.dtype) # iou ratio
# Classification
if self.nc > 1: # cls loss (only if multiple classes)
t = torch.full_like(ps[:, 5:], self.cn, device=device) # targets
t[range(n), tcls[i]] = self.cp
lcls += self.BCEcls(ps[:, 5:], t) # BCE
# Append targets to text file
# with open('targets.txt', 'a') as file:
# [file.write('%11.5g ' * 4 % tuple(x) + '\n') for x in torch.cat((txy[i], twh[i]), 1)]
obji = self.BCEobj(pi[..., 4].clamp_(-9.21, 9.21), tobj)
lobj += obji * self.balance[i] # obj loss
if self.autobalance:
self.balance[i] = self.balance[i] * 0.9999 + 0.0001 / obji.detach().item()
# bs = tobj.shape[0] # batch size
bs = p_seg[0].shape[0] if p_seg is not None else tobj.shape[0]
if self.autobalance:
self.balance = [x / self.balance[self.ssi] for x in self.balance]
lbox *= self.hyp['box']
lobj *= self.hyp['obj'] * 0.5 #(0.5 if (len(offsets) and len(offsets[0]) > bs) else 1.) # adaoff: 0.178
lcls *= self.hyp['cls']
if masks is not None and p_seg is not None:
assert len(p_seg) == 1
lpixl, larea, ldist = self.compute_loss_seg(p_seg[0], masks, targets, weight=m_weights)
loss = (lbox + lobj + lcls) * 1.0 + (lpixl + larea + ldist) * 0.2
loss_items = torch.cat((lbox, lobj, lcls, lpixl, larea, ldist, loss)).detach()
return loss * bs, loss_items