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

Subclass PyTorchYolo and PyTorchDetectionTransformer off PyTorchObjectDetector #2321

Merged
merged 24 commits into from
Feb 27, 2024

Conversation

f4str
Copy link
Collaborator

@f4str f4str commented Nov 9, 2023

Description

Modify both the PyTorchYolo and PyTorchDetectionTransformer estimators to be subclassed off the PyTorchObjectDetector estimator. This reduces a lot of redundant code and allows most functionality to be shared among the estimators. Additionally, this adds the option to train the PyTorchDetectionTransformer since the code is inherited accordingly.

The PyTorchObjectSeeker class was also cleaned up accordingly since there is now one unified superclass for all PyTorch object detectors.

Additionally updated the unit tests for all PyTorch object detection estimators to use a fixed input. This reduces randomness and ensures that outputs can remain consistent throughout tests.

Fixes #2267

Type of change

Please check all relevant options.

  • Improvement (non-breaking)
  • Bug fix (non-breaking)
  • New feature (non-breaking)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Testing

Please describe the tests that you ran to verify your changes. Consider listing any relevant details of your test configuration.

  • Updated unit tests for PyTorchObjectDetector
  • Updated unit tests for PyTorchFasterRCNN
  • Updated unit tests for PyTorchYolo
  • Updated unit tests for PyTorchDetectionTransformer

Test Configuration:

  • OS
  • Python version
  • ART version or commit number
  • TensorFlow / Keras / PyTorch / MXNet version

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • My changes have been tested using both CPU and GPU devices

@f4str f4str force-pushed the pytorch-yolo-rebase branch from baeec58 to 008679e Compare November 9, 2023 01:01
@codecov-commenter
Copy link

codecov-commenter commented Nov 9, 2023

Codecov Report

Attention: 21 lines in your changes are missing coverage. Please review.

Comparison is base (80fd393) 85.39% compared to head (9e347e6) 85.54%.

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff               @@
##           dev_1.18.0    #2321      +/-   ##
==============================================
+ Coverage       85.39%   85.54%   +0.14%     
==============================================
  Files             327      327              
  Lines           30205    29888     -317     
  Branches         5589     5528      -61     
==============================================
- Hits            25793    25567     -226     
+ Misses           2964     2900      -64     
+ Partials         1448     1421      -27     
Files Coverage Δ
...ators/certification/object_seeker/object_seeker.py 99.15% <100.00%> (+1.00%) ⬆️
...estimators/object_detection/pytorch_faster_rcnn.py 100.00% <ø> (ø)
...mators/object_detection/pytorch_object_detector.py 89.41% <100.00%> (+3.62%) ⬆️
art/estimators/object_detection/pytorch_yolo.py 86.95% <100.00%> (+4.00%) ⬆️
.../object_detection/pytorch_detection_transformer.py 85.00% <77.50%> (+21.73%) ⬆️
.../estimators/certification/object_seeker/pytorch.py 81.92% <77.77%> (-1.95%) ⬇️

... and 2 files with indirect coverage changes

@f4str f4str marked this pull request as draft November 9, 2023 06:03
@f4str f4str marked this pull request as ready for review November 10, 2023 00:58
@beat-buesser beat-buesser self-requested a review November 30, 2023 15:56
@beat-buesser beat-buesser self-assigned this Nov 30, 2023
@beat-buesser beat-buesser added the improvement Improve implementation label Nov 30, 2023
@beat-buesser beat-buesser added this to the ART 1.17.0 milestone Nov 30, 2023
@@ -247,8 +249,41 @@ def _preprocess_and_convert_inputs(

return x_preprocessed, y_preprocessed

def _translate_labels(self, labels: List[Dict[str, "torch.Tensor"]]) -> Any:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we define the return type more accurately?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since _translate_labels() and _translate_predictions() need to be overridden for each object detector model, this can take many different types (e.g., dictionary for FRCNN, tensor for Yolo, list of tensor for Detr). Replacing the Any would require a very long Union with every possible type for all subtypes which would need to updated if any new object detector is added. Therefore, it makes the most sense to keep this an Any type.

labels_translated = [{k: v.to(self.device) for k, v in y_i.items()} for y_i in labels]
return labels_translated

def _translate_predictions(self, predictions: Any) -> List[Dict[str, np.ndarray]]: # pylint: disable=R0201
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we remove the pylint comment and decorate this function with @staticmethod?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since _translate_predictions needs to be overridden for all subclasses, it cannot be a static method. For the specific cases of Faster RCNN, it does not use any of the properties, but this is not the case for YOLO and Detr.

Copy link
Collaborator

@beat-buesser beat-buesser left a comment

Choose a reason for hiding this comment

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

Hi @f4str Thank you very much for your pull request! I have added a few questions to get a better understanding of all the changes. Please let me know what you think?


if isinstance(x, torch.Tensor):
return loss
return loss # type: ignore
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is there a type ignore?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This should be resolved now


return loss.detach().cpu().numpy()
return loss.detach().cpu().numpy() # type: ignore
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is there a type ignore?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This should be resolved now



@pytest.fixture()
def get_pytorch_detr(get_default_cifar10_subset):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please add a docstring.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

art/estimators/certification/object_seeker/pytorch.py Fixed Show resolved Hide resolved
@@ -247,8 +249,41 @@ def _preprocess_and_convert_inputs(

return x_preprocessed, y_preprocessed

def _translate_labels(self, labels: List[Dict[str, "torch.Tensor"]]) -> Any:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a way to ensure that inheriting classes remember to update the label and precision translations?

Comment on lines +301 to +302
self.set_dropout(False)
self.set_multihead_attention(False)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this new?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, these are required for PyTorchDetectionTransformer since it is a subclass of PyTorchObjectDetector. Since PyTorchObjectDetector and PyTorchYolo do not have attention layers, this is just a no-op and does not affect functionality.

from art.utils import load_dataset
from art.estimators.object_detection.pytorch_detection_transformer import PyTorchDetectionTransformer
@pytest.mark.only_with_platform("pytorch")
def test_predict(art_warning, get_pytorch_detr):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why did the expected values for predictions change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

PyTorchFasterRCNN previously did not support the preprocessing parameter. This is probably legacy before the original refactor from before as it is fully supported now. Therefore, this test case is no longer applicable.

@beat-buesser
Copy link
Collaborator

Hi @f4str It looks like that one of the new unit test is change the prediction when the test runs on the GitHubActions machine. I have tried to fix it with #2371 but was not yet successful. Do you have an idea why the mode changes its predictions in that failing test?

f4str added 12 commits January 18, 2024 16:00
Signed-off-by: Farhan Ahmed <[email protected]>
Signed-off-by: Farhan Ahmed <[email protected]>
Signed-off-by: Farhan Ahmed <[email protected]>
Signed-off-by: Farhan Ahmed <[email protected]>
Signed-off-by: Farhan Ahmed <[email protected]>
Signed-off-by: Farhan Ahmed <[email protected]>
f4str added 3 commits January 18, 2024 16:03
Signed-off-by: Farhan Ahmed <[email protected]>
Signed-off-by: Farhan Ahmed <[email protected]>
@f4str f4str force-pushed the pytorch-yolo-rebase branch from 750bd30 to 400f839 Compare January 19, 2024 00:03
@f4str f4str changed the base branch from dev_1.17.0 to dev_1.18.0 January 19, 2024 00:03
Signed-off-by: Farhan Ahmed <[email protected]>
@f4str f4str requested a review from beat-buesser January 19, 2024 18:22
Copy link
Collaborator

@beat-buesser beat-buesser left a comment

Choose a reason for hiding this comment

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

Hi @f4str Thank you very much! The changes look good to me.

@beat-buesser beat-buesser merged commit 3597228 into Trusted-AI:dev_1.18.0 Feb 27, 2024
31 checks passed
@f4str f4str deleted the pytorch-yolo-rebase branch February 27, 2024 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement Improve implementation
Projects
No open projects
Status: Pull request done
3 participants