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

Replace abc.ABC with typing.Protocol in BaseSampler #5425

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

porink0424
Copy link
Contributor

@porink0424 porink0424 commented May 1, 2024

Motivation

In Python, static type checkers are now getting popular, and there are fewer and fewer times to use dynamic ones such as abc.ABC. This PR suggests replacing abc.ABC with Protocol in BaseSampler.

Description of the changes

  • Replaced abc.ABC with typing.Protocol in BaseSampler.
  • Adjusted implementations of each sampler to align with modifications in BaseSampler.
  • Added typing_extensions dependency when python version is less than 3.8.
  • Refactored test_samplers.

Note

By merging this PR, dynamic type checks would be no longer available such as isinstance(obj, BaseSampler), issubclass(cls, BaseSampler). The migration guide will be needed for users who rely on dynamic type checks.

@c-bata c-bata marked this pull request as draft May 1, 2024 05:40
@c-bata c-bata self-assigned this May 1, 2024
@not522 not522 self-assigned this May 1, 2024
pyproject.toml Outdated Show resolved Hide resolved
"If the study is being used for multi-objective optimization, "
f"{self.__class__.__name__} cannot be used."
)
def _raise_error_if_multi_objective(sampler: BaseSampler, study: Study) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

While _rase_error_if_multi_objective is private, some user-defined samplers use it, and these will not be compatible with Optuna v4.
https://github.com/Yard1/autopipeline/blob/b3c8c325adb969ddf9585d313f89dc53e0f6c5eb/automl/search/samplers/optuna_rf_sampler.py#L694

@c-bata c-bata removed their assignment May 8, 2024
@@ -20,7 +27,7 @@
from optuna.study import Study


class BaseSampler(abc.ABC):
class BaseSampler(Protocol):
Copy link
Member

Choose a reason for hiding this comment

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

Following this update, expressions like isinstance(foo, BaseSampler) and issubclass(bar, BaseSampler) will not work. We can see such usage in some OSS code, and it might be helpful to provide a migration guide for those affected.
https://github.com/volico/mlexp/blob/c07c96de964ea181571663a710bb2fc9a1559b25/mlexp/trainers/_base_trainer.py#L78-L80

Copy link
Member

Choose a reason for hiding this comment

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

Although typing.runtime_checkable allows us to use isinstance and issubclass with Protocol, it comes with some drawbacks, including impacts on execution speed and code complexity. Therefore, it may not be a good idea to employ it here. https://docs.python.org/3/library/typing.html#typing.runtime_checkable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@toshihikoyanase
Thank you for your pointing out. Where should I leave a migration guide for this change?

Copy link
Member

Choose a reason for hiding this comment

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

@porink0424 Maybe we can publish the guide in a GitHub discussion along with other breaking changes. Could you outline the guide here, please?

Honestly, I haven't come up with straightforward ways to migrate the code. In this case, we might simply remove the isinstance assertion and rely on the type checking instead.

So, we might recommend users migrate runtime checks such as isinstance and issubclass to type checking such, for example by using mypy.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@toshihikoyanase

Here is my suggestion for the guide:


Runtime check for BaseSampler is not available

In Optuna v4, the BaseSampler class now inherits typing.Protocol instead of abc.ABC. This change makes it possible to type-check samplers using static type checkers. However, this change makes it no longer possible to dynamically check whether a sampler is an instance of BaseSampler or whether a sampler class is a subclass of BaseSampler.

# Optuna v3.x
isinstance(sampler, optuna.samplers.BaseSampler)
issubclass(MySampler, optuna.samplers.BaseSampler)

# These checks are no longer available in Optuna v4

Please use static type checking such as mypy instead of runtime checks in Optuna v4.


Copy link
Member

Choose a reason for hiding this comment

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

Sorry for the delayed response. Seems good to me. Thank you!

@porink0424 porink0424 force-pushed the fix/replace-abc-with-protocol branch from d6efd3e to 2b45b5e Compare May 8, 2024 09:28
@porink0424 porink0424 marked this pull request as ready for review May 8, 2024 09:44
Copy link
Member

@y0z y0z left a comment

Choose a reason for hiding this comment

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

The implementation looks OK.

I think It is required to update some documentations.
For example, the following sentence is no longer exact because duck typing allows you create a sampler without inheriting BaseSampler.
https://optuna.readthedocs.io/en/stable/tutorial/20_recipes/005_user_defined_sampler.html

To create a new sampler, you need to define a class that inherits BaseSampler.

@porink0424
Copy link
Contributor Author

@y0z
Thank you for your comment, I updated the docs on the part you mentioned.
I think other parts are outside the scope of this PR, so I decided not to update them at this time.

Copy link
Member

@y0z y0z left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Collaborator

@nabenabe0928 nabenabe0928 left a comment

Choose a reason for hiding this comment

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

Probably, doc generation fails because of a syntax error.

tutorial/20_recipes/005_user_defined_sampler.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@nabenabe0928 nabenabe0928 left a comment

Choose a reason for hiding this comment

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

I found a typo.

tutorial/20_recipes/005_user_defined_sampler.py Outdated Show resolved Hide resolved
porink0424 and others added 2 commits May 15, 2024 12:40
Co-authored-by: Shuhei Watanabe <47781922+nabenabe0928@users.noreply.github.com>
Co-authored-by: Shuhei Watanabe <47781922+nabenabe0928@users.noreply.github.com>
@porink0424
Copy link
Contributor Author

@nabenabe0928
Thank you for your catch!

Copy link

codecov bot commented May 15, 2024

Codecov Report

Attention: Patch coverage is 75.00000% with 6 lines in your changes are missing coverage. Please review.

Project coverage is 89.72%. Comparing base (181d65f) to head (0a213fc).
Report is 145 commits behind head on master.

Current head 0a213fc differs from pull request most recent head 435ecc9

Please upload reports for the commit 435ecc9 to get more accurate results.

Files Patch % Lines
optuna/samplers/_base.py 66.66% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5425      +/-   ##
==========================================
+ Coverage   89.52%   89.72%   +0.20%     
==========================================
  Files         194      194              
  Lines       12626    12562      -64     
==========================================
- Hits        11303    11271      -32     
+ Misses       1323     1291      -32     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@toshihikoyanase toshihikoyanase left a comment

Choose a reason for hiding this comment

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

@porink0424 You may already be aware, but could you please address this comment? #5425 (comment)

@toshihikoyanase
Copy link
Member

@porink0424 Thank you for your response. I believe it will also be helpful for developers.

@not522 I think my comments have been resolved. Please merge after your review.

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.

None yet

6 participants