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

Add convergence criteria #1438

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

Add convergence criteria #1438

wants to merge 11 commits into from

Conversation

teytaud
Copy link
Contributor

@teytaud teytaud commented May 1, 2022

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Motivation and Context / Related issue

User request

How Has This Been Tested (if it applies)

Checklist

  • The documentation is up-to-date with the changes I made.
  • I have read the CONTRIBUTING document and completed the CLA (see CLA).
  • All tests passed, and additional code has been covered with new tests.

@facebook-github-bot facebook-github-bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label May 1, 2022
@teytaud teytaud requested review from jrapin and bottler May 2, 2022 13:09
@jrapin
Copy link
Contributor

jrapin commented May 2, 2022

It would be simpler / more tunable / more independent if we use callbacks

class EarlyStopping:
"""Callback for stopping the :code:`minimize` method before the budget is
fully used.
Parameters
----------
stopping_criterion: func(optimizer) -> bool
function that takes the current optimizer as input and returns True
if the minimization must be stopped
Note
----
This callback must be register on the "ask" method only.
Example
-------
In the following code, the :code:`minimize` method will be stopped at the 4th "ask"
>>> early_stopping = ng.callbacks.EarlyStopping(lambda opt: opt.num_ask > 3)
>>> optimizer.register_callback("ask", early_stopping)
>>> optimizer.minimize(_func, verbosity=2)
A couple other options (equivalent in case of non-noisy optimization) for stopping
if the loss is below 12:
>>> early_stopping = ng.callbacks.EarlyStopping(lambda opt: opt.recommend().loss < 12)
>>> early_stopping = ng.callbacks.EarlyStopping(lambda opt: opt.current_bests["minimum"].mean < 12)
"""
def __init__(self, stopping_criterion: tp.Callable[[base.Optimizer], bool]) -> None:
self.stopping_criterion = stopping_criterion
def __call__(self, optimizer: base.Optimizer, *args: tp.Any, **kwargs: tp.Any) -> None:
if args or kwargs:
raise errors.NevergradRuntimeError("EarlyStopping must be registered on ask method")
if self.stopping_criterion(optimizer):
raise errors.NevergradEarlyStopping("Early stopping criterion is reached")
@classmethod
def timer(cls, max_duration: float) -> "EarlyStopping":
"""Early stop when max_duration seconds has been reached (from the first ask)"""
return cls(_DurationCriterion(max_duration))
class _DurationCriterion:
def __init__(self, max_duration: float) -> None:
self._start = float("inf")
self._max_duration = max_duration
def __call__(self, optimizer: base.Optimizer) -> bool:
if np.isinf(self._start):
self._start = time.time()
return time.time() > self._start + self._max_duration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Do not delete this pull request or issue due to inactivity.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants