изменение от потери классификации к потере регрессии - PullRequest
1 голос
/ 25 января 2020

Общее

Я следую этому репо для обнаружения объектов https://github.com/yhenon/pytorch-retinanet

Мотивация

Сети обнаружения объектов обычно выполняют 2 задачи. Для каждого объект на изображении выводит оценку достоверности класса и оценку регрессии ограничивающего прямоугольника. Для моей задачи наряду с этими двумя выходными данными для каждого объекта я хочу вывести еще одну оценку регрессии, которая будет между 0-5.

Проблема утверждение

Подход, который я выбрал, заключается в том, что, поскольку сеть уже выполняет классификацию, я подумал, что я бы изменил некоторые части и сделал бы это регрессионными потерями. Потеря, использованная в упомянутом выше репо, является фокусными потерями. Часть как выглядит классификационная потеря, описано ниже, я хотел бы изменить ее на регрессионную потерю.

     targets = torch.ones(classification.shape) * -1#Here classification shape is = torch.Size([114048, 1])
    targets = targets.cuda()
    targets[torch.lt(IoU_max, 0.4), :] = 0#Iou_max is a tensor of shape = torch.Size([114048]) which looks like tensor([0., 0., 0.,  ..., 0., 0., 0.], device='cuda:0')
    positive_indices = torch.ge(IoU_max, 0.5)
    num_positive_anchors = positive_indices.sum()
    assigned_annotations = bbox_annotation[IoU_argmax, :]#Here bbox_annotation has the shape torch.Size([6, 6]) and IoU_argmax has the shape torch.Size([114048])
    targets[positive_indices, :] = 0#Here positive indices has the shape torch.Size([114048])
    targets[positive_indices, assigned_annotations[positive_indices, 4].long()] = 1
    alpha_factor = torch.ones(targets.shape).cuda() * alpha#here alpha is 0.25
    alpha_factor = torch.where(torch.eq(targets, 1.), alpha_factor, 1. - alpha_factor)
    focal_weight = torch.where(torch.eq(targets, 1.), 1. - classification, classification)
    focal_weight = alpha_factor * torch.pow(focal_weight, gamma)#here gamma is 2.0

    bce = -(targets * torch.log(classification) + (1.0 - targets) * torch.log(1.0 - classification))
    cls_loss = focal_weight * bce
    cls_loss = torch.where(torch.ne(targets, -1.0), cls_loss,torch.zeros(cls_loss.shape).cuda())
  classification_losses.append(cls_loss.sum()/torch.clamp(num_positive_anchors.float(), min=1.0))

Поэтому я попытался изменить некоторые биты, описанные выше. Но даже если код не нарушается Это ничему не учит. Вот эрозия - это просто тензор, но оценка эрозии - это то, что мы хотим регрессировать.

    targets = torch.ones(erosion.shape) * -1#Here erosion shape is torch.Size([114048, 1])
    targets = targets.cuda()
    targets[torch.lt(IoU_max, 0.4), :] = 0#This part remains the same as above
    positive_indices = torch.ge(IoU_max, 0.5)
    num_positive_anchors = positive_indices.sum()
    assigned_annotations = bbox_annotation[IoU_argmax, :]
    targets[positive_indices, :] = 0
    targets[assigned_annotations[positive_indices, 5].long()] = 1#Here i have indexed along the 5th dimension because the 5th dimension contains annotations for erosion.
    criterion = nn.MSELoss()#This part is where i use the mean squared loss for regression. 
    loss = torch.sqrt(criterion(targets, erosion))
    erosion_losses.append(loss)

Это не выдаст ошибку, но также ничего не узнает.

Может кто-нибудь помочь мне с правильной формулировкой этой потери для выполнения регрессии.

Подробнее

        assigned_annotations_erosion = assigned_annotations[positive_indices, 5]
        erosion_pred =  erosion[positive_indices].view(-1)
        criterion = nn.MSELoss()#
        loss = torch.sqrt(criterion(assigned_annotations_erosion, erosion_pred))
        loss *torch.tensor(5.0).cuda()
        # import pdb;pdb.set_trace()
        erosion_losses.append(loss)

1 Ответ

1 голос
/ 29 января 2020

Если я правильно понимаю, вы хотите добавить другой параметр регрессии, который должен иметь значения в [0-5].

Вместо того, чтобы пытаться изменить часть классификации, вы можете просто добавить ее в часть регрессии блока , Таким образом, вы добавляете еще один параметр для прогнозирования для каждого якоря.

Здесь - расчет потерь для параметров регрессии. Если вы добавили один параметр к каждому якору (возможно, путем увеличения количества фильтров в последнем слое), вы должны «извлечь» его здесь , как с другими параметрами. Вы также, вероятно, захотите подумать об активации для значения, например, sigmoid, чтобы вы получили что-то между 0 и 1, вы можете изменить масштаб на 0-5, если хотите.

После строка 107 вы хотите добавить что-то вроде этого

anchor_erosion_pi = anchor_erosion[positive_indices]

Затем вам нужно как-то получить gt, возможно, изменить его масштаб на 0-1, так что вы можете просто использовать активированный сигмоидный выход для этого значения. Тогда вы должны установить цель. Это просто:

targets_erosion = gt_erosion

Если вы не зависите от якоря, которое, кажется, имеет место. После этого цели складываются, где вам нужно добавить новое значение цели и добавить вес, вы должны решить и попробовать, если вам нужен вес здесь. Я, вероятно, добавил бы начало, добавив 0,2 или что-то к тензорному. Возможно, посмотрите в статье, как выбираются эти другие веса.

targets = targets/torch.Tensor([[0.1, 0.1, 0.2, 0.2, 0.2]]).cuda()

После этого вычисляется Плавная потеря L1 , когда вам, вероятно, не нужно ничего менять.

вероятно, вам нужно сделать еще больше. Просто посмотрите на код, посмотрите, где находятся другие параметры, и попробуйте добавить в него свой параметр.

...