Skip to content

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

@facebook-github-bot
Copy link

Hi @teytaud!

Thank you for your pull request.

We require contributors to sign our Contributor License Agreement, and yours needs attention.

You currently have a record in our system, but the CLA is no longer valid, and will need to be resubmitted.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

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