Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

giou #1842

Closed
ZYN-guy opened this issue Dec 20, 2019 · 3 comments
Closed

giou #1842

ZYN-guy opened this issue Dec 20, 2019 · 3 comments

Comments

@ZYN-guy
Copy link

ZYN-guy commented Dec 20, 2019

I modified iou_loss.py

### ### ### ### ### ### ### ### ### ### ### ### ###

@weighted_loss
def giou_bbox_overlaps(bboxes1, bboxes2,mode='iou', is_aligned=False):
'''Calculate generative overlap between two set of bboxes.

If ``is_aligned`` is ``False``, then calculate the ious between each bbox
of bboxes1 and bboxes2, otherwise the ious between each aligned pair of
bboxes1 and bboxes2.

Args:
    bboxes1 (Tensor): shape (m, 4)
    bboxes2 (Tensor): shape (n, 4), if is_aligned is ``True``, then m and n
        must be equal.

Returns:
    gious(Tensor): shape (m, n) if is_aligned == False else shape (m, 1)
'''
assert mode in ['iou', 'iof']
rows = bboxes1.size(0)
cols = bboxes2.size(0)
if is_aligned:
    assert rows == cols
if rows * cols == 0:
    return bboxes1.new(rows, 1) if is_aligned else bboxes1.new(rows, cols)

if is_aligned:
    overlaps_lt = torch.max(bboxes1[:, :2], bboxes2[:, :2])  # [rows, 2]
    overlaps_rb = torch.min(bboxes1[:, 2:], bboxes2[:, 2:])  # [rows, 2]
    overlaps_wh = (overlaps_rb - overlaps_lt + 1).clamp(min=0)  # [rows, 2]

    closure_lt = torch.min(bboxes1[:, :2], bboxes2[:, :2])  # [rows, 2]
    closure_rb = torch.max(bboxes1[:, 2:], bboxes2[:, 2:])  # [rows, 2]
    closure_wh = (closure_rb - closure_lt + 1).clamp(min=0)  # [rows, 2]
    overlap = overlaps_wh[:, 0] * overlaps_wh[:, 1]
    closure = closure_wh[:, 0] * closure_wh[:, 1]
    area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * (
        bboxes1[:, 3] - bboxes1[:, 1] + 1)
    if mode == 'iou':
        area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * (
            bboxes2[:, 3] - bboxes2[:, 1] + 1)
        union = (area1 + area2 - overlap)
        ious = overlap / union
        gious = ious - (closure-union)/closure
    else:
        gious = overlap / area1
else:
    overlaps_lt = torch.max(bboxes1[:, None, :2], bboxes2[:, :2])  # [rows, cols, 2]
    overlaps_rb = torch.min(bboxes1[:, None, 2:], bboxes2[:, 2:])  # [rows, cols, 2]
    overlaps_wh = (overlaps_rb - overlaps_lt + 1).clamp(min=0)  # [rows, cols, 2]

    closure_lt = torch.min(bboxes1[:, None, :2], bboxes2[:, :2])  # [rows, cols, 2]
    closure_rb = torch.max(bboxes1[:, None, 2:], bboxes2[:, 2:])  # # [rows, cols, 2]
    closure_wh = (closure_rb - closure_lt + 1).clamp(min=0)  # [rows, cols, 2]

    overlap = overlaps_wh[:, :, 0] * overlaps_wh[:, :, 1]
    closure = closure_wh[:, :, 0] * closure_wh[:, :, 1]

    area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * (
        bboxes1[:, 3] - bboxes1[:, 1] + 1)
    if mode == 'iou':
        area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * (
            bboxes2[:, 3] - bboxes2[:, 1] + 1)

        union = (area1[:, None] + area2 - overlap)
        ious = overlap / union
        gious = ious - (closure - union) / closure
    else:
        gious = overlap / (area1[:, None])
return gious

@weighted_loss
def giou_loss(pred, target, eps=1e-6):
"""IoU loss.

Computing the IoU loss between a set of predicted bboxes and target bboxes.
The loss is calculated as negative log of IoU.

Args:
    pred (Tensor): Predicted bboxes of format (x1, y1, x2, y2),
        shape (n, 4).
    target (Tensor): Corresponding gt bboxes, shape (n, 4).
    eps (float): Eps to avoid log(0).

Return:
    Tensor: Loss tensor.
"""
gious = giou_bbox_overlaps(pred, target, is_aligned=True).clamp(min=eps)
loss = 1.-gious
return loss

@LOSSES.register_module
class GIoULoss(nn.Module):

def __init__(self, eps=1e-6, reduction='mean', loss_weight=1.0):
    super(GIoULoss, self).__init__()
    self.eps = eps
    self.reduction = reduction
    self.loss_weight = loss_weight

def forward(self,
            pred,
            target,
            weight=None,
            avg_factor=None,
            reduction_override=None,
            **kwargs):
    if weight is not None and not torch.any(weight > 0):
        return (pred * weight).sum()  # 0
    assert reduction_override in (None, 'none', 'mean', 'sum')
    reduction = (
        reduction_override if reduction_override else self.reduction)
    loss = self.loss_weight * giou_loss(
        pred,
        target,
        weight,
        eps=self.eps,
        reduction=reduction,
        avg_factor=avg_factor,
        **kwargs)
    return loss

### ### ### ### ### ### ###

I use #loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0))), It can work . But I get a error when I use GioULoss.
****
result:
box: 0.0170, loss_cls: 0.0432, acc: 99.3516, loss_bbox: 0.0207, loss: 0.1334
2019-12-20 21:54:13,546 - INFO - Epoch [1][550/5405] lr: 0.00100, eta: 0:56:04, time: 0.128, data_time: 0.001, memory: 1259, loss_rpn_cls: 0.0358, loss_rpn_bbox: 0.0216, loss_cls: 0.0631, acc: 98.8945, loss_bbox: 0.0410, loss: 0.1615
2019-12-20 21:54:19,938 - INFO - Epoch [1][600/5405] lr: 0.00100, eta: 0:56:00, time: 0.128, data_time: 0.001, memory: 1259, loss_rpn_cls: 0.0416, loss_rpn_bbox: 0.0158, loss_cls: 0.0405, acc: 99.4062, loss_bbox: 0.0197, loss: 0.1176
/opt/conda/conda-bld/pytorch_1573049310284/work/aten/src/ATen/native/cuda/IndexKernel.cu:60: lambda ->auto::operator()(int)->auto: block: [1,0,0], thread: [0,0,0] Assertion index >= -sizes[i] && index < sizes[i] && "index out of bounds" failed.
/opt/conda/conda-bld/pytorch_1573049310284/work/aten/src/ATen/native/cuda/IndexKernel.cu:60: lambda ->auto::operator()(int)->auto: block: [1,0,0], thread: [1,0,0] Assertion index >= -sizes[i] && index < sizes[i] && "index out of bounds" failed.
/opt/conda/conda-bld/pytorch_1573049310284/work/aten/src/ATen/native/cuda/IndexKernel.cu:60: lambda ->auto::operator()(int)->auto: block: [1,0,0], thread: [2,0,0] Assertion index >= -sizes[i] && index < sizes[i] && "index out of bounds" failed.
/opt/conda/conda-bld/pytorch_1573049310284/work/aten/src/ATen/native/cuda/IndexKernel.cu:60: lambda ->auto::operator()(int)->auto: block: [1,0,0], thread: [3,0,0] Assertion index >= -sizes[i] && index < sizes[i] && "index out of bounds" failed.
return self.forward_train(img, img_meta, **kwargs)
File "/home/zhangyanan/Desktop/钢材表面/mmdetection/mmdet/models/detectors/two_stage.py", line 199, in forward_train
gt_labels[i])
File "/home/zhangyanan/Desktop/钢材表面/mmdetection/mmdet/core/bbox/assigners/max_iou_assigner.py", line 90, in assign
assign_result = self.assign_wrt_overlaps(overlaps, gt_labels)
File "/home/zhangyanan/Desktop/钢材表面/mmdetection/mmdet/core/bbox/assigners/max_iou_assigner.py", line 124, in assign_wrt_overlaps
& (max_overlaps < self.neg_iou_thr)] = 0
RuntimeError: copy_if failed to synchronize: device-side assert triggered
terminate called after throwing an instance of 'c10::Error'
what(): CUDA error: device-side assert triggered (insert_events at /opt/conda/conda-bld/pytorch_1573049310284/work/c10/cuda/CUDACachingAllocator.cpp:569)
frame #0: c10::Error::Error(c10::SourceLocation, std::string const&) + 0x47 (0x7fdc29885687 in /home/zhangyanan/anaconda3/lib/python3.7/site-packages/torch/lib/libc10.so)
frame #1: + 0x17044 (0x7fdc29ac1044 in /home/zhangyanan/anaconda3/lib/python3.7/site-packages/torch/lib/libc10_cuda.so)
frame #2: + 0x1cccb (0x7fdc29ac6ccb in /home/zhangyanan/anaconda3/lib/python3.7/site-packages/torch/lib/libc10_cuda.so)
frame #3: c10::TensorImpl::release_resources() + 0x4d (0x7fdc29872e9d in /home/zhangyanan/anaconda3/lib/python3.7/site-packages/torch/lib/libc10.so)
frame #4: + 0x1c8519 (0x7fdc59598519 in /home/zhangyanan/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
frame #5: + 0x4b1b9b (0x7fdc59881b9b in /home/zhangyanan/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)
frame #6: + 0x4b1bd6 (0x7fdc59881bd6 in /home/zhangyanan/anaconda3/lib/python3.7/site-packages/torch/lib/libtorch_python.so)

frame #26: __libc_start_main + 0xf0 (0x7fdc68f86830 in /lib/x86_64-linux-gnu/libc.so.6)

@hellock
Copy link
Member

hellock commented Dec 21, 2019

Please follow the Error report issue template and fomat the codeblocks.

@ZYN-guy ZYN-guy closed this as completed Dec 21, 2019
@ZYN-guy
Copy link
Author

ZYN-guy commented Dec 21, 2019

iou_loss.py

###

import torch
import torch.nn as nn

from mmdet.core import bbox_overlaps
from ..registry import LOSSES
from .utils import weighted_loss

@weighted_loss
def iou_loss(pred, target, eps=1e-6):
"""IoU loss.

Computing the IoU loss between a set of predicted bboxes and target bboxes.
The loss is calculated as negative log of IoU.

Args:
    pred (Tensor): Predicted bboxes of format (x1, y1, x2, y2),
        shape (n, 4).
    target (Tensor): Corresponding gt bboxes, shape (n, 4).
    eps (float): Eps to avoid log(0).

Return:
    Tensor: Loss tensor.
"""
ious = bbox_overlaps(pred, target, is_aligned=True).clamp(min=eps)
loss = -ious.log()
return loss

@weighted_loss
def bounded_iou_loss(pred, target, beta=0.2, eps=1e-3):
"""Improving Object Localization with Fitness NMS and Bounded IoU Loss,
https://arxiv.org/abs/1711.00164.

Args:
    pred (tensor): Predicted bboxes.
    target (tensor): Target bboxes.
    beta (float): beta parameter in smoothl1.
    eps (float): eps to avoid NaN.
"""
pred_ctrx = (pred[:, 0] + pred[:, 2]) * 0.5
pred_ctry = (pred[:, 1] + pred[:, 3]) * 0.5
pred_w = pred[:, 2] - pred[:, 0] + 1
pred_h = pred[:, 3] - pred[:, 1] + 1
with torch.no_grad():
    target_ctrx = (target[:, 0] + target[:, 2]) * 0.5
    target_ctry = (target[:, 1] + target[:, 3]) * 0.5
    target_w = target[:, 2] - target[:, 0] + 1
    target_h = target[:, 3] - target[:, 1] + 1

dx = target_ctrx - pred_ctrx
dy = target_ctry - pred_ctry

loss_dx = 1 - torch.max(
    (target_w - 2 * dx.abs()) /
    (target_w + 2 * dx.abs() + eps), torch.zeros_like(dx))
loss_dy = 1 - torch.max(
    (target_h - 2 * dy.abs()) /
    (target_h + 2 * dy.abs() + eps), torch.zeros_like(dy))
loss_dw = 1 - torch.min(target_w / (pred_w + eps), pred_w /
                        (target_w + eps))
loss_dh = 1 - torch.min(target_h / (pred_h + eps), pred_h /
                        (target_h + eps))
loss_comb = torch.stack([loss_dx, loss_dy, loss_dw, loss_dh],
                        dim=-1).view(loss_dx.size(0), -1)

loss = torch.where(loss_comb < beta, 0.5 * loss_comb * loss_comb / beta,
                   loss_comb - 0.5 * beta)
return loss

@LOSSES.register_module
class IoULoss(nn.Module):

def __init__(self, eps=1e-6, reduction='mean', loss_weight=1.0):
    super(IoULoss, self).__init__()
    self.eps = eps
    self.reduction = reduction
    self.loss_weight = loss_weight

def forward(self,
            pred,
            target,
            weight=None,
            avg_factor=None,
            reduction_override=None,
            **kwargs):
    if weight is not None and not torch.any(weight > 0):
        return (pred * weight).sum()  # 0
    assert reduction_override in (None, 'none', 'mean', 'sum')
    reduction = (
        reduction_override if reduction_override else self.reduction)
    loss = self.loss_weight * iou_loss(
        pred,
        target,
        weight,
        eps=self.eps,
        reduction=reduction,
        avg_factor=avg_factor,
        **kwargs)
    return loss

@LOSSES.register_module
class BoundedIoULoss(nn.Module):

def __init__(self, beta=0.2, eps=1e-3, reduction='mean', loss_weight=1.0):
    super(BoundedIoULoss, self).__init__()
    self.beta = beta
    self.eps = eps
    self.reduction = reduction
    self.loss_weight = loss_weight

def forward(self,
            pred,
            target,
            weight=None,
            avg_factor=None,
            reduction_override=None,
            **kwargs):
    if weight is not None and not torch.any(weight > 0):
        return (pred * weight).sum()  # 0
    assert reduction_override in (None, 'none', 'mean', 'sum')
    reduction = (
        reduction_override if reduction_override else self.reduction)
    loss = self.loss_weight * bounded_iou_loss(
        pred,
        target,
        weight,
        beta=self.beta,
        eps=self.eps,
        reduction=reduction,
        avg_factor=avg_factor,
        **kwargs)
    return loss

@weighted_loss
def giou_bbox_overlaps(bboxes1, bboxes2,mode='iou', is_aligned=False):
'''Calculate generative overlap between two set of bboxes.

If ``is_aligned`` is ``False``, then calculate the ious between each bbox
of bboxes1 and bboxes2, otherwise the ious between each aligned pair of
bboxes1 and bboxes2.

Args:
    bboxes1 (Tensor): shape (m, 4)
    bboxes2 (Tensor): shape (n, 4), if is_aligned is ``True``, then m and n
        must be equal.

Returns:
    gious(Tensor): shape (m, n) if is_aligned == False else shape (m, 1)
'''
assert mode in ['iou', 'iof']
rows = bboxes1.size(0)
cols = bboxes2.size(0)
if is_aligned:
    assert rows == cols
if rows * cols == 0:
    return bboxes1.new(rows, 1) if is_aligned else bboxes1.new(rows, cols)

if is_aligned:
    overlaps_lt = torch.max(bboxes1[:, :2], bboxes2[:, :2])  # [rows, 2]
    overlaps_rb = torch.min(bboxes1[:, 2:], bboxes2[:, 2:])  # [rows, 2]
    overlaps_wh = (overlaps_rb - overlaps_lt + 1).clamp(min=0)  # [rows, 2]

    closure_lt = torch.min(bboxes1[:, :2], bboxes2[:, :2])  # [rows, 2]
    closure_rb = torch.max(bboxes1[:, 2:], bboxes2[:, 2:])  # [rows, 2]
    closure_wh = (closure_rb - closure_lt + 1).clamp(min=0)  # [rows, 2]
    overlap = overlaps_wh[:, 0] * overlaps_wh[:, 1]
    closure = closure_wh[:, 0] * closure_wh[:, 1]
    area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * (
        bboxes1[:, 3] - bboxes1[:, 1] + 1)
    if mode == 'iou':
        area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * (
            bboxes2[:, 3] - bboxes2[:, 1] + 1)
        union = (area1 + area2 - overlap)
        ious = overlap / union
        gious = ious - (closure-union)/(closure + 1e-7)
    else:
        gious = overlap / area1
else:
    overlaps_lt = torch.max(bboxes1[:, None, :2], bboxes2[:, :2])  # [rows, cols, 2]
    overlaps_rb = torch.min(bboxes1[:, None, 2:], bboxes2[:, 2:])  # [rows, cols, 2]
    overlaps_wh = (overlaps_rb - overlaps_lt + 1).clamp(min=0)  # [rows, cols, 2]

    closure_lt = torch.min(bboxes1[:, None, :2], bboxes2[:, :2])  # [rows, cols, 2]
    closure_rb = torch.max(bboxes1[:, None, 2:], bboxes2[:, 2:])  # # [rows, cols, 2]
    closure_wh = (closure_rb - closure_lt + 1).clamp(min=0)  # [rows, cols, 2]

    overlap = overlaps_wh[:, :, 0] * overlaps_wh[:, :, 1]
    closure = closure_wh[:, :, 0] * closure_wh[:, :, 1]

    area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * (
        bboxes1[:, 3] - bboxes1[:, 1] + 1)
    if mode == 'iou':
        area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * (
            bboxes2[:, 3] - bboxes2[:, 1] + 1)

        union = (area1[:, None] + area2 - overlap)
        ious = overlap / union
        gious = ious - (closure - union) / (closure + 1e-7)
    else:
        gious = overlap / (area1[:, None])
return gious

@weighted_loss
def giou_loss(pred, target, eps=1e-6):
"""IoU loss.

Computing the IoU loss between a set of predicted bboxes and target bboxes.
The loss is calculated as negative log of IoU.

Args:
    pred (Tensor): Predicted bboxes of format (x1, y1, x2, y2),
        shape (n, 4).
    target (Tensor): Corresponding gt bboxes, shape (n, 4).
    eps (float): Eps to avoid log(0).

Return:
    Tensor: Loss tensor.
"""
gious = giou_bbox_overlaps(pred, target, is_aligned=True).clamp(min=eps)
loss = 1 - gious
return loss

@LOSSES.register_module
class GIoULoss(nn.Module):

def __init__(self, eps=1e-6, reduction='mean', loss_weight=1.0):
    super(GIoULoss, self).__init__()
    self.eps = eps
    self.reduction = reduction
    self.loss_weight = loss_weight

def forward(self,
            pred,
            target,
            weight=None,
            avg_factor=None,
            reduction_override=None,
            **kwargs):
    if weight is not None and not torch.any(weight > 0):
        return (pred * weight).sum()  # 0
    assert reduction_override in (None, 'none', 'mean', 'sum')
    reduction = (
        reduction_override if reduction_override else self.reduction)
    loss = self.loss_weight * giou_loss(
        pred,
        target,
        weight,
        eps=self.eps,
        reduction=reduction,
        avg_factor=avg_factor,
        **kwargs)
    return loss

if name is "main":
bbox1 = torch.Tensor([[0, 0, 100, 100], [0, 0, 100, 100]])
bbox2 = torch.Tensor([[0, 50, 150, 100], [0, 50, 150, 100]])
gious_loss = GIoULoss()
gloss = gious_loss(bbox1, bbox2)

@ZYN-guy
Copy link
Author

ZYN-guy commented Dec 21, 2019

result:
2019-12-21 17:10:22,196 - INFO - Epoch [3][750/5405] lr: 0.00100, eta: 6:01:21, time: 0.206, data_time: 0.002, memory: 2182, loss_rpn_cls: 16960480.4187, loss_rpn_bbox: 570987.5918, s0.loss_cls: 531304628.6139, s0.acc: 96.2693, s0.loss_bbox: -4597231082981395791872.0000, s1.loss_cls: 12599753.1277, s1.acc: 96.2693, s1.loss_bbox: 1250569.1136, s2.loss_cls: 5367157.6594, s2.acc: 96.2693, s2.loss_bbox: 853494.4172, loss: -4597231082981395791872.0000
loss is bad

FANGAreNotGnu pushed a commit to FANGAreNotGnu/mmdetection that referenced this issue Oct 23, 2023
* Removing defaults channel

* openmp

* cuda

* cuda

* cuda

* sphinx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants