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

Identity box coder, similarity calculator, target assigner #8962

Merged
merged 48 commits into from
Sep 15, 2020

Conversation

kmindspark
Copy link
Contributor

Description

📝 Please include a summary of the change.

  • Please also include relevant motivation and context.
  • List any dependencies that are required for this change.

Type of change

For a new feature or function, please create an issue first to discuss it
with us before submitting a pull request.

Note: Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • Documentation update
  • TensorFlow 2 migration
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • A new research paper code implementation
  • Other (Specify)

Tests

📝 Please describe the tests that you ran to verify your changes.

  • Provide instructions so we can reproduce.
  • Please also list any relevant details for your test configuration.

Test Configuration:

Checklist

tf.expand_dims(tf.transpose(w1), axis=1))
return ycenters + xcenters + heights + widths

def giou_loss(boxlist1, boxlist2, scope=None):
Copy link
Contributor

@bhack bhack Jul 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is already available at https://www.tensorflow.org/addons/api_docs/python/tfa/losses/GIoULoss
If you need any extension please open a PR in TFA. /cc @tensorflow/sig-addons-maintainers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tombstone told me to implement this separately so we wouldn't need that dependency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another GIOU Is landing from #9083

Copy link
Contributor

@tombstone tombstone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kmindspark

@@ -31,11 +31,11 @@
from object_detection.core import box_list_ops
from object_detection.core import standard_fields as fields


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Internal lint required two lines.

EPSILON = 1e-8


class DETRBoxCoder(box_coder.BoxCoder):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed offline, it might be best to follow CenterNet's pattern here to create a single class that does the target assignment.

Copy link
Contributor

@tombstone tombstone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kmindspark. I left some comments. PTAL

@@ -35,7 +35,8 @@
class RegionSimilarityCalculator(six.with_metaclass(ABCMeta, object)):
"""Abstract base class for region similarity calculator."""

def compare(self, boxlist1, boxlist2, scope=None):
def compare(self, boxlist1, boxlist2, scope=None,
groundtruth_labels=None, predicted_labels=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

groundtruth_labels and predicted_labels can be fields inside boxlist. We don't need to add additional arguments to the interface.

"""
classification_scores = tf.matmul(groundtruth_labels,
tf.nn.softmax(predicted_labels), transpose_b=True)
return -5 * box_list_ops.l1(boxlist1, boxlist2) + 2 * box_list_ops.giou(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the scale factors 5 and 2 as constructor arguments. Also are these values mentioned in the paper ?

"""
classification_scores = tf.matmul(groundtruth_labels,
tf.nn.softmax(predicted_labels), transpose_b=True)
return -5 * box_list_ops.l1(boxlist1, boxlist2) + 2 * box_list_ops.giou(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't the second term be -2 * box_list_ops.giou(..) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is + because this is calculating similarity, and box list ops giou is not doing 1-giou

"""Target assigner to compute classification and regression targets."""

def __init__(self,
similarity_calc,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's hardcode this class to use DETRSimilarityCalc

self._negative_class_weight = negative_class_weight

def assign(self,
anchors,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we have anchors here ? Do you mean predicted boxes ?

anchors,
groundtruth_boxes,
groundtruth_labels=None,
unmatched_class_label=None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need unmatched_class_label for DETR.

Copy link
Contributor Author

@kmindspark kmindspark Aug 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that? Should I hard code it to [1] + [0]*num_classes inside target assigner?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed to keep compatible with batch_assign_targets so decided to leave this in, is that ok?

representing weights for each element in cls_targets.
reg_targets: a float32 tensor with shape [num_anchors, box_code_dimension]
reg_weights: a float32 tensor with shape [num_anchors]
match: an int32 tensor of shape [num_anchors] containing result of anchor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to return match object. Let's simplify.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case it would be difficult to use the existing batch_assign_targets right? Which would be nice to use.

0))
groundtruth_labels = tf.expand_dims(groundtruth_labels, -1)

unmatched_shape_assert = shape_utils.assert_shape_equal(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove shape asserts.


def __init__(self,
similarity_calc,
matcher,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hardcode to use hungarian matcher.

cls_weights = tf.tile(cls_weights, weights_multiple)

num_anchors = anchors.num_boxes_static()
if num_anchors is not None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you rename anchors throughout to be predicted_boxes ?

Copy link
Contributor

@tombstone tombstone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kmindspark

@@ -107,7 +108,8 @@ def assign(self,
groundtruth_boxes,
groundtruth_labels=None,
unmatched_class_label=None,
groundtruth_weights=None):
groundtruth_weights=None,
class_predictions=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do because in batch_assign it by default now passes in class predictions.

@@ -434,6 +436,9 @@ def create_target_assigner(reference, stage=None,
use_matmul_gather=use_matmul_gather)
box_coder_instance = faster_rcnn_box_coder.FasterRcnnBoxCoder()

elif reference == 'DETR':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to add it here. In DETR meta architecture you can directly create DETRTargetAssigner()

@@ -1897,3 +1911,197 @@ def assign_corner_offset_targets(

return (tf.stack(corner_targets, axis=0),
tf.stack(foreground_targets, axis=0))

class DETRTargetAssigner(object):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still a bit worried that we are carrying around a lot of legacy code for the DETR Target Assigner. Can you take a look at https://github.com/facebookresearch/detr/blob/master/models/matcher.py and see if we can do something similiar ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That file just does the matching. Do you mean the fact that we do similarity calculation separately from the target assigner?

Copy link
Contributor

@tombstone tombstone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kmindspark . This is looking good.

research/object_detection/core/target_assigner.py Outdated Show resolved Hide resolved
research/object_detection/core/target_assigner.py Outdated Show resolved Hide resolved
research/object_detection/core/target_assigner_test.py Outdated Show resolved Hide resolved
research/object_detection/core/target_assigner_test.py Outdated Show resolved Hide resolved
research/object_detection/core/target_assigner_test.py Outdated Show resolved Hide resolved
groundtruth_boxes,
box_preds)
match = self._matcher.match(match_quality_matrix,
valid_rows=tf.greater(groundtruth_weights, 0))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question - where do we ensure that the number of predicted boxes and number of padded groundtruth boxes is equal ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default number of boxes to pad to in the config (max_number_of_boxes) is 100. I could explicitly set this in the config. I can also add an assert to confirm.

groundtruth_boxes,
box_preds)
match = self._matcher.match(match_quality_matrix,
valid_rows=tf.greater(groundtruth_weights, 0))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice does DETR use zeros to represent null groundtruths ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's how the data loading works I believe (giving 0 weights to padded boxes), if that's not the case let me know 👍

@@ -0,0 +1,118 @@
# Faster R-CNN with Resnet-50 (v1) with 640x640 input resolution
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this config from the PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops not sure how this snuck in.

Copy link
Contributor

@tombstone tombstone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kmindspark

@tombstone tombstone added the ready to pull ready to pull (create internal pr review and merge automatically) label Aug 27, 2020
@tf-models-copybara-bot tf-models-copybara-bot merged commit 13a030e into tensorflow:master Sep 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes ready to pull ready to pull (create internal pr review and merge automatically)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants