-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Cleaning up Ops Boxes and Losses 🧹 #5979
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
Changes from 4 commits
0d728c4
475f656
e28511d
77f8f7a
4d55891
8fd0e30
6aea76e
d3b4951
5fdd7a8
2488305
4175be3
4237e4e
6599ec0
9b6bfb1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
import torch | ||
|
||
from ..utils import _log_api_usage_once | ||
from .giou_loss import _upcast | ||
from ._utils import _loss_inter_union | ||
from .diou_loss import distance_box_iou_loss | ||
|
||
|
||
def complete_box_iou_loss( | ||
|
@@ -12,6 +13,9 @@ def complete_box_iou_loss( | |
) -> torch.Tensor: | ||
|
||
""" | ||
# Original Implementation from | ||
https://github.com/facebookresearch/detectron2/blob/main/detectron2/layers/losses.py | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would leave this as a comment on the source. Long unrendered URLs are not particularly helpful for the documentation. We should make the same change on diou. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeap. That looks ugly and it's on multiple places. If you want bring a separate quick PR that moves attributions on the main part of the methods to avoid the issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One option is to embed the link e.g.
But the docstring should at least start by describing what the object is, even if it's very obvious from its name already. So I would suggest to write something like """Complete Box IoU Loss.
Implementation is adapted from `Detectron2 <https://github.com/facebookresearch/detectron2/blob/main/detectron2/layers/losses.py>`__.
... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's how it's currently over main branch. I would suggest adding 3 words in end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a great description but the preview is a bit long @oke-aditya . It's best to skip a line after the first sentence (there's even a PEP for that) to keep the preview is short and to-the-point.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will be tackling this in seperate PR anyways to unify all stuff. I feel we need bit more revamp for Ops docs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should definitely provide attribution to other projects when we use code from them. Let's keep the reference on the code as a comment on the main body of the method similar to what we do in most places instead of placing a link. We can review this on the future and make changes in a coordinated manner. |
||
|
||
Gradient-friendly IoU loss with an additional penalty that is non-zero when the | ||
boxes do not overlap overlap area, This loss function considers important geometrical | ||
factors such as overlap area, normalized central point distance and aspect ratio. | ||
|
@@ -30,50 +34,25 @@ def complete_box_iou_loss( | |
``'sum'``: The output will be summed. Default: ``'none'`` | ||
eps : (float): small number to prevent division by zero. Default: 1e-7 | ||
|
||
Reference: | ||
Returns: | ||
Tensor: Loss tensor with the reduction option applied. | ||
|
||
Complete Intersection over Union Loss (Zhaohui Zheng et. al) | ||
https://arxiv.org/abs/1911.08287 | ||
Reference: | ||
Zhaohui Zheng et. al: Complete Intersection over Union Loss: | ||
https://arxiv.org/abs/1911.08287 | ||
|
||
""" | ||
|
||
# Original Implementation : https://github.com/facebookresearch/detectron2/blob/main/detectron2/layers/losses.py | ||
|
||
if not torch.jit.is_scripting() and not torch.jit.is_tracing(): | ||
_log_api_usage_once(complete_box_iou_loss) | ||
|
||
boxes1 = _upcast(boxes1) | ||
boxes2 = _upcast(boxes2) | ||
diou_loss = distance_box_iou_loss(boxes1, boxes2, reduction="none", eps=eps) | ||
intsct, union = _loss_inter_union(boxes1, boxes2) | ||
oke-aditya marked this conversation as resolved.
Show resolved
Hide resolved
|
||
iou = intsct / (union + eps) | ||
|
||
x1, y1, x2, y2 = boxes1.unbind(dim=-1) | ||
x1g, y1g, x2g, y2g = boxes2.unbind(dim=-1) | ||
|
||
# Intersection keypoints | ||
xkis1 = torch.max(x1, x1g) | ||
ykis1 = torch.max(y1, y1g) | ||
xkis2 = torch.min(x2, x2g) | ||
ykis2 = torch.min(y2, y2g) | ||
|
||
intsct = torch.zeros_like(x1) | ||
mask = (ykis2 > ykis1) & (xkis2 > xkis1) | ||
intsct[mask] = (xkis2[mask] - xkis1[mask]) * (ykis2[mask] - ykis1[mask]) | ||
union = (x2 - x1) * (y2 - y1) + (x2g - x1g) * (y2g - y1g) - intsct + eps | ||
iou = intsct / union | ||
|
||
# smallest enclosing box | ||
xc1 = torch.min(x1, x1g) | ||
yc1 = torch.min(y1, y1g) | ||
xc2 = torch.max(x2, x2g) | ||
yc2 = torch.max(y2, y2g) | ||
diag_len = ((xc2 - xc1) ** 2) + ((yc2 - yc1) ** 2) + eps | ||
|
||
# centers of boxes | ||
x_p = (x2 + x1) / 2 | ||
y_p = (y2 + y1) / 2 | ||
x_g = (x1g + x2g) / 2 | ||
y_g = (y1g + y2g) / 2 | ||
distance = ((x_p - x_g) ** 2) + ((y_p - y_g) ** 2) | ||
|
||
# width and height of boxes | ||
w_pred = x2 - x1 | ||
h_pred = y2 - y1 | ||
|
@@ -83,7 +62,7 @@ def complete_box_iou_loss( | |
with torch.no_grad(): | ||
alpha = v / (1 - iou + v + eps) | ||
|
||
loss = 1 - iou + (distance / diag_len) + alpha * v | ||
loss = diou_loss + alpha * v | ||
if reduction == "mean": | ||
loss = loss.mean() if loss.numel() > 0 else 0.0 * loss.sum() | ||
elif reduction == "sum": | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,7 @@ | ||
import torch | ||
from torch import Tensor | ||
|
||
from ..utils import _log_api_usage_once | ||
|
||
|
||
def _upcast(t: Tensor) -> Tensor: | ||
# Protects from numerical overflows in multiplications by upcasting to the equivalent higher type | ||
if t.dtype not in (torch.float32, torch.float64): | ||
return t.float() | ||
return t | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not the same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I do understand that I have not used the
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The On the losses side, I'm not aware of any application that does things on integer space. Not only that but doing So I think it's important prior merging this PR, to make an explicit decision of what has to support integers and what doesn't, handle it appropriately and add tests and xfails to ensure we are not breaking anything. |
||
from ._utils import _upcast, _loss_inter_union | ||
|
||
|
||
def generalized_box_iou_loss( | ||
|
@@ -38,6 +31,9 @@ def generalized_box_iou_loss( | |
``'sum'``: The output will be summed. Default: ``'none'`` | ||
eps (float): small number to prevent division by zero. Default: 1e-7 | ||
|
||
Returns: | ||
Tensor: Loss tensor with the reduction option applied. | ||
|
||
Reference: | ||
Hamid Rezatofighi et. al: Generalized Intersection over Union: | ||
A Metric and A Loss for Bounding Box Regression: | ||
|
@@ -51,16 +47,7 @@ def generalized_box_iou_loss( | |
x1, y1, x2, y2 = boxes1.unbind(dim=-1) | ||
x1g, y1g, x2g, y2g = boxes2.unbind(dim=-1) | ||
|
||
# Intersection keypoints | ||
xkis1 = torch.max(x1, x1g) | ||
ykis1 = torch.max(y1, y1g) | ||
xkis2 = torch.min(x2, x2g) | ||
ykis2 = torch.min(y2, y2g) | ||
|
||
intsctk = torch.zeros_like(x1) | ||
mask = (ykis2 > ykis1) & (xkis2 > xkis1) | ||
intsctk[mask] = (xkis2[mask] - xkis1[mask]) * (ykis2[mask] - ykis1[mask]) | ||
unionk = (x2 - x1) * (y2 - y1) + (x2g - x1g) * (y2g - y1g) - intsctk | ||
intsctk, unionk = _loss_inter_union(boxes1, boxes2) | ||
iouk = intsctk / (unionk + eps) | ||
|
||
# smallest enclosing box | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that previous code used different versions of upcast. More specifically boxes permitted integers while losses didn't.