-
Notifications
You must be signed in to change notification settings - Fork 45.5k
Add Combined NMS #6138
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
Add Combined NMS #6138
Conversation
@pooyadavoodi do you happen to have any ballpark performance metrics comparing inference before and after the change? |
@dcyoung In our inference benchmarks, I can see from 0.8x to 1.2x speedup when we use CombinedNMS. The smaller the batch size, the bigger the speedup. Note that <1x means regression. Note that CombinedNMS only works on CPU. Someone might implement a GPU version of it in the future to make it much faster. TF-TRT will be able to optimize CombinedNMS (even the CPU version) to TensorRT NMS and with that I can see about 2x speedup across the board. |
"""Multi-class version of non maximum suppression that operates on a batch. | ||
This op is similar to `multiclass_non_max_suppression` but operates on a batch | ||
of boxes and scores. See documentation for `multiclass_non_max_suppression` |
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.
Are these all simply copy/pasted? You should add some comments about what this method really do here.
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.
@pkulzc could you PTAL. I just added a better explanation of what the function does.
with tf.name_scope(scope, 'CombinedNonMaxSuppression'): | ||
nmsed_boxes, nmsed_scores, nmsed_classes, num_detections = tf.image.combined_non_max_suppression( | ||
boxes, scores, max_size_per_class, max_total_size, iou_thresh, | ||
score_thresh, use_static_shapes) |
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.
combined_non_max_suppression doesn't really have a input argument like this, right?
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.
Which particular input are you referring to? The CombinedNonMaxSuppression has 6 inputs as defined in https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/ops/image_ops.cc#L913
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.
There are 7 input arguments here while CombinedNonMaxSuppression only takes 6.
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.
Sorry I missed the last attribute - use_static_shapes is the bool argument pad_per_class.
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.
Could we use keyword argument for combined_non_max_suppression here?
score_thresh, use_static_shapes) | ||
|
||
batch_nmsed_masks = None | ||
batch_nmsed_additional_fields = None |
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.
Why are these not handled?
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.
Currently the CombinedNonMaxSuppression does not have support to handle masks or additional fields. We can handle this once the kernel is updated to use these fields.
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.
Could you add a comment mentioning masks and other fields are not supported when using combined_nms?
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.
Thanks Pooya, just a few more nits.
'max_total_detections.') | ||
|
||
non_max_suppressor_fn = functools.partial( | ||
if(nms_config.combined_nms): |
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.
Nit: space between if and '('.
with tf.name_scope(scope, 'CombinedNonMaxSuppression'): | ||
nmsed_boxes, nmsed_scores, nmsed_classes, num_detections = tf.image.combined_non_max_suppression( | ||
boxes, scores, max_size_per_class, max_total_size, iou_thresh, | ||
score_thresh, use_static_shapes) |
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.
Could we use keyword argument for combined_non_max_suppression here?
score_thresh, use_static_shapes) | ||
|
||
batch_nmsed_masks = None | ||
batch_nmsed_additional_fields = None |
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.
Could you add a comment mentioning masks and other fields are not supported when using combined_nms?
|
||
batch_nmsed_masks = None | ||
batch_nmsed_additional_fields = None | ||
#TODO supriyar: Set static shapes here? |
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.
Remove this?
optional bool use_static_shapes = 6 [default = false]; | ||
|
||
// Whether to use the Combined NMS op | ||
optional bool combined_nms = 7 [default = false]; |
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.
use_combined_nms
optional bool use_static_shapes_for_eval = 37 [default = false]; | ||
|
||
// Whether to use Combined NMS for first stage. | ||
optional bool first_stage_combined_nms = 38 [default=false]; |
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.
use_combined_nms_in_first_stage
self.assertAllClose(nmsed_boxes, exp_nms_corners) | ||
self.assertAllClose(nmsed_scores, exp_nms_scores) | ||
self.assertAllClose(nmsed_classes, exp_nms_classes) | ||
self.assertAllClose(num_detections, [3, 3]) |
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.
assertListEqual
Change url to https://github.com/pooyadavoodi/models.git until PR tensorflow/models#6138 gets merged.
* Change url of tftrt/examples/third_party/models Change url to https://github.com/pooyadavoodi/models.git until PR tensorflow/models#6138 gets merged. * Update submodule tftrt/examples/third_party/models
Pooya, we recently updated the post_processing files and there may have some conflicts with your PR. Could you please resolve them? |
Thanks @pkulzc |
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. ℹ️ Googlers: Go here for more info. |
7a53520
to
b7d2704
Compare
1. Adds a unit test to test post_processing python API 2. Currently sets clip_window to None as the kernel uses the default clip_window of [0,0,1,1] 3. Added use_static_shapes to the API. In old API if use_static_shapes is true, then it pads/clips outputs to max_total_size, if specified. If not specified, it pads to num_classes*max_size_per_class. If use_static_shapes is false, it always pads/clips to max_total_size. Update unit test to account for clipped bouding boxes Changed the name to CombinedNonMaxSuppression based on feedback from Google Added additional parameters to combinedNMS python function. They are currently unused and required for networks like FasterRCNN and MaskRCNN
Because it was removed from CombinedNMS recently in the PR.
Remove redundant arguments from combined_nms
…sion Also rename combined_nms to use_combined_nms
2affe0c
to
2a3cc51
Compare
CLAs look good, thanks! ℹ️ Googlers: Go here for more info. |
…ork" This reverts commit 2a3cc51.
@pkulzc I have made some restructuring in the code. Could you please review. FasterRCNN doesn't work with combined_nms in this PR mainly because of unsupported arguments. I have put some checks in the code to avoid calling combined_nms with those arguments, but some of those arguments can't be checked during graph construction because they are TF tensors (for those I print warning messages instead). We can add TF conditionals to the graph to check those if you think that's necessary (assuming they don't hurt the performance). |
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.
Looks good. Just a few nits.
if nms_config.soft_nms_sigma < 0.0: | ||
raise ValueError('soft_nms_sigma should be non-negative.') | ||
if nms_config.use_combined_nms: | ||
if nms_config.use_class_agnostic_nms: |
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.
Merge two if clauses?
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.
Done.
// Soft NMS sigma parameter; Bodla et al, https://arxiv.org/abs/1704.04503) | ||
optional float soft_nms_sigma = 9 [default = 0.0]; | ||
|
||
// Whether to use tf.image.combined_non_max_suppression |
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.
Please add period to the end of your comments (same for your other changes in this PR as well).
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.
Done.
@pkulzc I think I've answered all the comments. |
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.
LGTM
@pkulzc @pengchongjin could you help to merge this PR? Thanks. |
* Change url of tftrt/examples/third_party/models Change url to https://github.com/pooyadavoodi/models.git until PR tensorflow/models#6138 gets merged. * Update submodule tftrt/examples/third_party/models
CombinedNMS op was recently added to TensorFlow.
tensorflow/tensorflow#23567
This PR adds CombinedNMS to the object detection API in TensorFlow.
The main difference between this new op and the old ones is that it does all of NMS in one op.
It's much more efficient, and it's also easier to swap out with a more efficient version of it from TF custom backends such as TensorRT and XLA.