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] Accessors for preprocessor in Predictor class #26600

Merged
merged 14 commits into from
Jul 19, 2022

Conversation

ericl
Copy link
Contributor

@ericl ericl commented Jul 15, 2022

Why are these changes needed?

There is currently no way to get/set a preprocessor on a BatchPredictor / Predictor once created. This makes it very difficult to figure out how to pass a custom preprocessor to a predictor.

Changes

  1. Added Checkpoint.get_preprocessor() to unify Preprocessor retrieval logic.
    1. This could be further optimized. Ideally we can unify dict & dir checkpoints, but a short-term optimization would be to check if the original format is dict or dir so that we don't need to check both (which may incur extra conversions).
  2. Added Predictor.get_preprocessor() and Predictor.set_preprocessor().
  3. Added BatchPredictor.get_preprocessor() and BatchPredictor.set_preprocessor().

Related issue number

Closes #26528

TODO:

  • Unit tests

@richardliaw richardliaw self-assigned this Jul 17, 2022
return self._override_preprocessor

checkpoint_data = self._checkpoint.to_dict()
preprocessor = checkpoint_data.get(PREPROCESSOR_KEY)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just fyi This implementation currently won’t work for gbdt predictors as they use directory Checkpoints not dict checkpoints

Copy link
Contributor

Choose a reason for hiding this comment

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

What’s the user journey that we are trying to solve by introducing these apis?

It seems by doing this we are making assumptions about the underlying checkpoint structure (assuming there is a PREPROCESSOR_KEY in the checkpoint). So these will only work for checkpoints outputted by our trainers and not for the general case. BatchPredictor will no longer work with any predictor and any checkpoint. I’m wondering if there is an alternative solution here to resolve the user problem.

Copy link
Contributor

Choose a reason for hiding this comment

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

If it’s just the ability to override the preprocessor, then we currently have other mechanisms to do this and it might just be a matter of documenting them better

Copy link
Contributor

Choose a reason for hiding this comment

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

(moved to slack)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@matthewdeng this is the tricky issue

Copy link
Contributor

Choose a reason for hiding this comment

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

Added Checkpoint.get_preprocessor() to unify this logic, though it's not optimized in this PR.

Signed-off-by: Matthew Deng <[email protected]>
Signed-off-by: Matthew Deng <[email protected]>
Signed-off-by: Matthew Deng <[email protected]>
@@ -42,7 +42,8 @@ def from_checkpoint(cls, checkpoint: Checkpoint) -> "LightGBMPredictor":
``LightGBMTrainer`` run.

"""
bst, preprocessor = load_checkpoint(checkpoint)
bst, _ = load_checkpoint(checkpoint)
Copy link
Contributor

Choose a reason for hiding this comment

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

Leaving this line here for now as load_checkpoint will be removed with #26651

Comment on lines 65 to 67
# Ensure the proper conversion functions are called.
convert_to_pandas_mock.assert_called_once()
convert_from_pandas_mock.assert_called_once()
Copy link
Contributor

Choose a reason for hiding this comment

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

Removing these mocks since they cause the prediction logic to no longer be tested. Didn't seem valuable enough of a test to create a second test that just tests the call logic.

Copy link
Contributor

@amogkam amogkam Jul 19, 2022

Choose a reason for hiding this comment

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

Hmm I wrote the mocks after our previous discussions on not writing integration tests for everything.

If we make sure the conversion functions are called and since the conversion functions are also tested, then we don’t need to write tests for predictor against all possible input and output types. This was the original intention but the mocks may not have been the best way to achieve this- do you have any other suggestions to not lose this test coverage?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah gotcha. I think in that case I can extend the mocks to return concrete values and validate the inputs/outputs.

@matthewdeng matthewdeng changed the title [WIP] Accessors for preprocessor in Predictor class [air] Accessors for preprocessor in Predictor class Jul 19, 2022
Copy link
Contributor

@amogkam amogkam left a comment

Choose a reason for hiding this comment

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

As discussed offline, what does the developer api look like?

with framework specific checkpoints we should make the base Checkpoint class a developer api, right? This may be out of scope for this PR, so we can do this in a follow up as well!

Comment on lines 65 to 67
# Ensure the proper conversion functions are called.
convert_to_pandas_mock.assert_called_once()
convert_from_pandas_mock.assert_called_once()
Copy link
Contributor

@amogkam amogkam Jul 19, 2022

Choose a reason for hiding this comment

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

Hmm I wrote the mocks after our previous discussions on not writing integration tests for everything.

If we make sure the conversion functions are called and since the conversion functions are also tested, then we don’t need to write tests for predictor against all possible input and output types. This was the original intention but the mocks may not have been the best way to achieve this- do you have any other suggestions to not lose this test coverage?

@amogkam
Copy link
Contributor

amogkam commented Jul 19, 2022

Actually nvm Checkpoint will still be exposed to Tune users who use trainables directly and not any of the trainers.

Signed-off-by: Matthew Deng <[email protected]>
Signed-off-by: Matthew Deng <[email protected]>
Signed-off-by: Matthew Deng <[email protected]>
@ericl
Copy link
Contributor Author

ericl commented Jul 19, 2022

with framework specific checkpoints we should make the base Checkpoint class a developer api, right? This may be out of scope for this PR, so we can do this in a follow up as well!

The base class should remain a PublicAPI since all the methods are still publicly accessible. Futhermore, you are always allowed to load a checkpoint generically using the base class.

@amogkam
Copy link
Contributor

amogkam commented Jul 19, 2022

Agreed for Checkpoint let's keep it as PublicAPI since it will still be exposed to users who are not using any of the Trainers.

The base class should remain a PublicAPI since all the methods are still publicly accessible.

For this case, the pattern that we have been following is the class is DeveloperAPI, but individual methods can be denoted as PublicAPI. This is what we do for BaseTrainer for example.

@ericl ericl added the tests-ok The tagger certifies test failures are unrelated and assumes personal liability. label Jul 19, 2022
@richardliaw richardliaw merged commit b0eb051 into ray-project:master Jul 19, 2022
Rohan138 pushed a commit to Rohan138/ray that referenced this pull request Jul 28, 2022
Stefan-1313 pushed a commit to Stefan-1313/ray_mod that referenced this pull request Aug 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tests-ok The tagger certifies test failures are unrelated and assumes personal liability.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[air] Add set_preprocessor / get_preprocessor on the Predictor class
4 participants