-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
WIP: Move to numpy.Generators #6899
base: dev
Are you sure you want to change the base?
WIP: Move to numpy.Generators #6899
Conversation
@wyli This draft PR is still very much WIP, but I wanted to place this here early to discuss how to best implement this migration.
|
thanks for the PR, I remember that the integer random seeds are flexible and could be used for coordinating the randomised behaviour across worker processes (it seems that it's not possible to pass a random state object instead), we may want to keep the integer type random seeds settings. please see usage in dataloader: Lines 702 to 705 in c564ded
|
@wyli Sorry I am not sure what this is referencing. What is changing that is breaking this existing behavior? |
right, I thought the proposal was about replacing both |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR, overall looks good to me. Several minor comments inline, feel free to ignore them.
monai/transforms/transform.py
Outdated
R: np.random.RandomState = np.random.RandomState() | ||
|
||
def set_random_state(self, seed: int | None = None, state: np.random.RandomState | None = None) -> Randomizable: | ||
R: SupportsRandomGeneration = LegacyRandomStateAdaptor() # FIXME Why is this initialized here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems we also need to update the docstring in L181 to tell users we may change to Generator near future.
def handle_legacy_random_state( | ||
rand_state: np.random.RandomState | None = None, | ||
generator: SupportsRandomGeneration | None = None, | ||
return_legacy_default_random: bool = False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the user directly change to the Generator by setting the flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is more of a internal utility function (should probably be prefixed with _) during the migration to be used in the utility functions that accept a random_state (e.g. get_random_patch). The return_legacy_default_random is to return the default value as it is currently done (If there ends up being no use case where the default is not required, the parameter could be removed as well).
To change the default generator for transforms the place would be to change the _default_random_generator_factory variable to numpy.random.default_rng
Regarding my previous comment:
How about we add a __getattr__ method to the LegacyRandomStateAdaptor. When you try to call one of the old methods, they will get redirected to the underlying RandomState but we print a deprecation warning? This of course would mean that you cannot migrate to the new Generator until all your third-party transforms have also migrated, but that should be acceptable |
monai/transforms/transform.py
Outdated
@@ -171,6 +172,9 @@ def _log_stats(data, prefix: str | None = "Data"): | |||
raise RuntimeError(f"applying transform {transform}") from e | |||
|
|||
|
|||
_default_random_generator_factory: Callable[[Any | None], SupportsRandomGeneration] = LegacyRandomStateAdaptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a function to allow users to change this out? For example _set_default_random_generator_factory(factory: Callable|str) where you can supply your own factory or use "legacy" or "generator" to switch to the new or old behavior.
Signed-off-by: John Zielke <[email protected]>
Signed-off-by: John Zielke <[email protected]>
Signed-off-by: John Zielke <[email protected]>
Fixes #6854 .
Description
In order to move from the deprecated numpy.random.RandomState to the faster and supported numpy.random.Generator, in a first step the generation of randomness in transform and related functions is migrated (i.e. everything with self.R/ implementing Randomizable). The idea of this PR is to change the API for randomness to that of Generators. In order to preserve reproducibility, the old Random Generator should still be used by default while providing an option to switch over to the new implementation.
Breaking changes
Types of changes
./runtests.sh -f -u --net --coverage
../runtests.sh --quick --unittests --disttests
.make html
command in thedocs/
folder.