Skip to content

Conversation

pooyadavoodi
Copy link

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.

@pooyadavoodi
Copy link
Author

+@azaks2 @aaroey

@aaroey
Copy link
Member

aaroey commented Feb 1, 2019

+@pengchongjin

@dcyoung
Copy link

dcyoung commented Feb 2, 2019

@pooyadavoodi do you happen to have any ballpark performance metrics comparing inference before and after the change?

@aaroey aaroey requested a review from pengchongjin February 4, 2019 19:06
@pooyadavoodi
Copy link
Author

@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`
Copy link
Contributor

@pkulzc pkulzc Feb 10, 2019

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.

Copy link
Author

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)
Copy link
Contributor

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?

Copy link

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

Copy link
Contributor

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.

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.

Copy link
Contributor

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
Copy link
Contributor

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?

Copy link

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.

Copy link
Contributor

@pkulzc pkulzc May 20, 2019

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?

Copy link
Contributor

@pkulzc pkulzc left a 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):
Copy link
Contributor

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)
Copy link
Contributor

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
Copy link
Contributor

@pkulzc pkulzc May 20, 2019

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?
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?

optional bool use_static_shapes = 6 [default = false];

// Whether to use the Combined NMS op
optional bool combined_nms = 7 [default = false];
Copy link
Contributor

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];
Copy link
Contributor

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])
Copy link
Contributor

Choose a reason for hiding this comment

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

assertListEqual

@aaroey aaroey self-requested a review May 21, 2019 17:08
pooyadavoodi pushed a commit to pooyadavoodi/tensorrt that referenced this pull request May 23, 2019
pooyadavoodi pushed a commit to tensorflow/tensorrt that referenced this pull request May 24, 2019
* 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
@pkulzc
Copy link
Contributor

pkulzc commented Jun 5, 2019

Pooya, we recently updated the post_processing files and there may have some conflicts with your PR. Could you please resolve them?

@pooyadavoodi
Copy link
Author

Thanks @pkulzc
I will check. There is also some problem in the PR that causes accuracy regression on Faster-RCNN and Mask-RCNN (not in SSD). I am looking into that too.

@googlebot
Copy link

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.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

@googlebot googlebot added cla: no and removed cla: yes labels Jun 8, 2019
@pooyadavoodi pooyadavoodi changed the title Add Combined NMS WIP: Add Combined NMS Aug 7, 2019
Pooya Davoodi added 7 commits September 4, 2019 13:23
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
@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@googlebot googlebot added cla: yes and removed cla: no labels Sep 4, 2019
@pooyadavoodi pooyadavoodi changed the title WIP: Add Combined NMS Add Combined NMS Sep 18, 2019
@pooyadavoodi pooyadavoodi requested a review from pkulzc September 18, 2019 20:53
@pooyadavoodi
Copy link
Author

@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).

Copy link
Contributor

@pkulzc pkulzc left a 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:
Copy link
Contributor

Choose a reason for hiding this comment

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

Merge two if clauses?

Copy link
Author

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
Copy link
Contributor

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).

Copy link
Author

Choose a reason for hiding this comment

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

Done.

@pooyadavoodi
Copy link
Author

@pkulzc I think I've answered all the comments.
Please let me know what you think.

Copy link
Contributor

@pkulzc pkulzc left a comment

Choose a reason for hiding this comment

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

LGTM

@aaroey
Copy link
Member

aaroey commented Oct 8, 2019

@pkulzc @pengchongjin could you help to merge this PR? Thanks.

@saberkun saberkun merged commit 3980d2a into tensorflow:master Oct 9, 2019
DEKHTIARJonathan pushed a commit to tensorflow/tensorrt that referenced this pull request Nov 19, 2021
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants