fast-reid/fastreid/modeling/losses/cross_entroy_loss.py

63 lines
1.8 KiB
Python
Raw Normal View History

2020-02-10 22:13:04 +08:00
# encoding: utf-8
"""
@author: l1aoxingyu
@contact: sherlockliao01@gmail.com
"""
import torch
import torch.nn.functional as F
from fastreid.utils.events import get_event_storage
2020-02-10 22:13:04 +08:00
2020-09-01 16:14:45 +08:00
def log_accuracy(pred_class_logits, gt_classes, topk=(1,)):
2020-02-10 22:13:04 +08:00
"""
2020-09-01 16:14:45 +08:00
Log the accuracy metrics to EventStorage.
2020-02-10 22:13:04 +08:00
"""
2020-09-01 16:14:45 +08:00
bsz = pred_class_logits.size(0)
maxk = max(topk)
_, pred_class = pred_class_logits.topk(maxk, 1, True, True)
pred_class = pred_class.t()
correct = pred_class.eq(gt_classes.view(1, -1).expand_as(pred_class))
2020-02-10 22:13:04 +08:00
2020-09-01 16:14:45 +08:00
ret = []
for k in topk:
correct_k = correct[:k].view(-1).float().sum(dim=0, keepdim=True)
ret.append(correct_k.mul_(1. / bsz))
2020-02-10 22:13:04 +08:00
2020-09-01 16:14:45 +08:00
storage = get_event_storage()
storage.put_scalar("cls_accuracy", ret[0])
2020-02-10 22:13:04 +08:00
2020-09-01 16:14:45 +08:00
def cross_entropy_loss(pred_class_logits, gt_classes, eps, alpha=0.2):
num_classes = pred_class_logits.size(1)
2020-02-10 22:13:04 +08:00
2020-09-01 16:14:45 +08:00
if eps >= 0:
smooth_param = eps
else:
# Adaptive label smooth regularization
soft_label = F.softmax(pred_class_logits, dim=1)
smooth_param = alpha * soft_label[torch.arange(soft_label.size(0)), gt_classes].unsqueeze(1)
2020-09-01 16:14:45 +08:00
log_probs = F.log_softmax(pred_class_logits, dim=1)
with torch.no_grad():
targets = torch.ones_like(log_probs)
targets *= smooth_param / (num_classes - 1)
targets.scatter_(1, gt_classes.data.unsqueeze(1), (1 - smooth_param))
2020-09-01 16:14:45 +08:00
loss = (-targets * log_probs).sum(dim=1)
2020-09-01 16:14:45 +08:00
"""
# confidence penalty
conf_penalty = 0.3
probs = F.softmax(pred_class_logits, dim=1)
entropy = torch.sum(-probs * log_probs, dim=1)
loss = torch.clamp_min(loss - conf_penalty * entropy, min=0.)
"""
2020-08-20 15:51:41 +08:00
2020-09-01 16:14:45 +08:00
with torch.no_grad():
non_zero_cnt = max(loss.nonzero(as_tuple=False).size(0), 1)
2020-09-01 16:14:45 +08:00
loss = loss.sum() / non_zero_cnt
2020-09-01 16:14:45 +08:00
return loss