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

[AIR] Support array output from Torch model #24902

Merged
merged 2 commits into from
May 19, 2022

Conversation

amogkam
Copy link
Contributor

@amogkam amogkam commented May 18, 2022

The previous implementation of TorchPredictor failed when the model outputted an array for each sample (for example outputting logits). This is because Pandas Dataframes cannot hold numpy arrays of more than 1 element. We have to convert the outermost numpy array returned by the model to a list so that it be can stored in a Pandas Dataframe.

The newly added test fails under the old implementation.

Why are these changes needed?

Related issue number

Checks

  • I've run scripts/format.sh to lint the changes in this PR.
  • I've included any doc changes needed for https://docs.ray.io/en/master/.
  • I've made sure the tests are passing. Note that there might be a few flaky tests, see the recent failures at https://flakey-tests.ray.io/
  • Testing Strategy
    • Unit tests
    • Release tests
    • This PR is not tested :(

Copy link
Member

@bveeramani bveeramani left a comment

Choose a reason for hiding this comment

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

Overall LGTM. If we can't use TensorArray here, then I think this should be good to merge

# these cannot be used as values in a Pandas Dataframe.
# We have to convert the outermost dimension to a python list (but the values
# in the list can still be Numpy arrays).
return pd.DataFrame({"predictions": list(prediction)}, columns=["predictions"])
Copy link
Member

Choose a reason for hiding this comment

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

Can we use TensorArray here now that #24752 is merged?

Suggested change
return pd.DataFrame({"predictions": list(prediction)}, columns=["predictions"])
return pd.DataFrame({"predictions": TensorArray(prediction)}, columns=["predictions"])

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 didn't want to have a ray.data dependency in Predictors. Once we do the data type conversion cleanup and probably move TensorArray to a common utils file, I definitely agree though, we should use TensorArray here!

Comment on lines +119 to +122
unsqueeze (bool): If set to True, the features tensors will be unsqueezed
(reshaped to (N, 1)) before being concatenated into the final features
tensor. Otherwise, they will be left as is, that is (N, ).
Defaults to True.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: out of scope for this PR, but this explanation doesn't really make sense for multi-dimensional inputs

Copy link
Member

Choose a reason for hiding this comment

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

We could change the description, yeah. We are now calling unsqueeze which should work with an arbitrary number of dimensions and not just 2, like the view call we were using before.

Copy link
Contributor Author

@amogkam amogkam May 18, 2022

Choose a reason for hiding this comment

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

Agreed the semantics here need to be changed. Though this is out of scope for this PR- this PR is just updating the docstring to match the same as the argument name, which is a mistake we had before.

def test_predict_array_output():
"""Tests if predictor works if model outputs an array instead of single value."""

predictor = TorchPredictor(model=model, preprocessor=preprocessor)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: this is definitely out of scope for this PR, but it might be better to define model and preprocessor in the test because:

  • Less confusion when reading the tests since all of the code is visible from within each test.
  • Less chance of sharing state between tests, which creates unwanted dependencies between them.

Related advice from .NET's unit testing best practices.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated!

def test_predict_array_output():
"""Tests if predictor works if model outputs an array instead of single value."""

predictor = TorchPredictor(model=model, preprocessor=preprocessor)
Copy link
Member

Choose a reason for hiding this comment

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

Just for my own understanding, why do we need to use a preprocessor here?

Copy link
Member

Choose a reason for hiding this comment

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

I believe it is to check that its applied, though that could be covered by other tests and not this one specifically

Copy link
Contributor

Choose a reason for hiding this comment

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

In this case I'd vote to leave it out of this test. We should ideally only test one thing

Copy link
Contributor Author

@amogkam amogkam May 18, 2022

Choose a reason for hiding this comment

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

Sounds good, I updated the tests! PTAL!

Copy link
Member

@Yard1 Yard1 left a comment

Choose a reason for hiding this comment

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

Thanks, this looks good. +1 to Balaji's comment about using a TensorArray once that's possible, though we probably don't need to block on that.

Copy link
Contributor

@krfricke krfricke left a comment

Choose a reason for hiding this comment

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

Generally looks good once @bveeramani's comments are addressed

def test_predict_array_output():
"""Tests if predictor works if model outputs an array instead of single value."""

predictor = TorchPredictor(model=model, preprocessor=preprocessor)
Copy link
Contributor

Choose a reason for hiding this comment

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

In this case I'd vote to leave it out of this test. We should ideally only test one thing

@richardliaw richardliaw added this to the Ray AIR milestone May 18, 2022
@richardliaw richardliaw added the @author-action-required The PR author is responsible for the next step. Remove tag to send back to the reviewer. label May 18, 2022
@amogkam amogkam removed the @author-action-required The PR author is responsible for the next step. Remove tag to send back to the reviewer. label May 18, 2022
@amogkam amogkam requested a review from bveeramani May 18, 2022 23:53
Copy link
Member

@bveeramani bveeramani left a comment

Choose a reason for hiding this comment

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

LGTM

@amogkam amogkam merged commit f7d75c7 into ray-project:master May 19, 2022
@amogkam amogkam deleted the torch-predictor-image-support branch May 19, 2022 19:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants