def __call__(self, outputs, targets): loss = (1 - self.jaccard_weight) * self.nll_loss(outputs, targets) # for binary, this equals to log(mean(iou)) if self.jaccard_weight > 0: ious = iou_binary_torch(targets.float(), torch.sigmoid(outputs)) loss -= self.jaccard_weight * torch.log(torch.mean(ious)) return loss
def __call__(self, outputs, targets): ''' @param outputs: n-d tensor (probability map) @param targets: tensor (0-1 map) @return loss: loss ''' loss = (1 - self.jaccard_weight) * self.ce_loss(outputs, targets) jaccard_loss = 0 # turn logits into prob maps outputs = torch.softmax(outputs, dim=1) if self.jaccard_weight > 0: # for each class, calculate jaccard loss for cls in range(self.num_classes): metric = iou_binary_torch((targets == cls).float(), outputs[:, cls]) # metric = iou_binary_dice((targets == cls).float(), outputs[:, cls:cls+1]) # mean of metric(class = cls) for all inputs jaccard_loss += torch.mean(metric) loss -= self.jaccard_weight * torch.log( jaccard_loss / self.num_classes) return loss
def validation_binary(model, criterion, valid_loader, num_classes=None): with torch.no_grad(): # set eval mode model.eval() valid_losses = [] ious = [] dices = [] report_each = 10 tq = tqdm.tqdm(total=len(valid_loader.dataset)) tq.set_description('Valid [{}]'.format(params.model.__name__)) # for inputs, targets in valid_loader: for i, (idxs, inputs, targets, attmaps) in enumerate(valid_loader): inputs = inputs.cuda(non_blocking=True) targets = targets.cuda(non_blocking=True) attmaps = attmaps.cuda(non_blocking=True) # outputs = model(inputs) outputs = model(inputs, attmaps) loss = criterion(outputs, targets) valid_losses.append(loss.item()) ious += list( iou_binary_torch((targets == 1).float(), (outputs > 0).float()).data.cpu().numpy()) dices += list( dice_binary_torch((targets == 1).float(), (outputs > 0).float()).data.cpu().numpy()) # update attention maps using prediction valid_loader.dataset.update_attmaps(outputs.cpu(), idxs) # update tq bar tq.update(valid_loader.batch_size) tq.set_postfix( loss='{:.5f}'.format(np.mean(valid_losses[-report_each:]))) # close tq bar tq.close() sum_valid_loss = np.sum(valid_losses) valid_loss = np.mean(valid_losses) # type: float valid_iou = np.mean(ious).astype(np.float64) valid_dice = np.mean(dices).astype(np.float64) print('sum valid loss: {:.5f}, average valid loss: {:.5f}, average IoU: {:.5f}, average Dice: {:.5f}' \ .format(sum_valid_loss, valid_loss, valid_iou, valid_dice)) metrics = { 'sum_valid_loss': sum_valid_loss, 'valid_loss': valid_loss, 'IoU': valid_iou, 'Dice': valid_dice } return metrics
def __call__(self, outputs, targets): loss = (1 - self.jaccard_weight) * self.nll_loss(outputs, targets) jaccard_loss = 0 for cls in range(self.num_classes): # outputs[:, cls].exp() ious = iou_binary_torch((targets == cls).float(), outputs[:, cls].exp()) jaccard_loss += torch.mean(ious) loss -= self.jaccard_weight * torch.log( jaccard_loss / self.num_classes) return loss