-
Notifications
You must be signed in to change notification settings - Fork 61
BalancingLearner: add a "cycle" strategy, sampling the learners one by one #188
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
from collections.abc import Iterable | ||
from contextlib import suppress | ||
from functools import partial | ||
import itertools | ||
from operator import itemgetter | ||
|
||
import numpy as np | ||
|
@@ -50,10 +51,11 @@ class BalancingLearner(BaseLearner): | |
function : callable | ||
A function that calls the functions of the underlying learners. | ||
Its signature is ``function(learner_index, point)``. | ||
strategy : 'loss_improvements' (default), 'loss', or 'npoints' | ||
strategy : 'loss_improvements' (default), 'loss', 'npoints', or 'cycle'. | ||
The points that the `BalancingLearner` choses can be either based on: | ||
the best 'loss_improvements', the smallest total 'loss' of the | ||
child learners, or the number of points per learner, using 'npoints'. | ||
child learners, the number of points per learner, using 'npoints', | ||
or by cycling through the learners one by one using 'cycle'. | ||
One can dynamically change the strategy while the simulation is | ||
running by changing the ``learner.strategy`` attribute. | ||
|
||
|
@@ -90,10 +92,11 @@ def __init__(self, learners, *, cdims=None, strategy="loss_improvements"): | |
|
||
@property | ||
def strategy(self): | ||
"""Can be either 'loss_improvements' (default), 'loss', or 'npoints' | ||
The points that the `BalancingLearner` choses can be either based on: | ||
the best 'loss_improvements', the smallest total 'loss' of the | ||
child learners, or the number of points per learner, using 'npoints'. | ||
"""Can be either 'loss_improvements' (default), 'loss', 'npoints', or | ||
'cycle'. The points that the `BalancingLearner` choses can be either | ||
based on: the best 'loss_improvements', the smallest total 'loss' of | ||
the child learners, the number of points per learner, using 'npoints', | ||
or by going through all learners one by one using 'cycle'. | ||
One can dynamically change the strategy while the simulation is | ||
running by changing the ``learner.strategy`` attribute.""" | ||
return self._strategy | ||
|
@@ -107,10 +110,13 @@ def strategy(self, strategy): | |
self._ask_and_tell = self._ask_and_tell_based_on_loss | ||
elif strategy == "npoints": | ||
self._ask_and_tell = self._ask_and_tell_based_on_npoints | ||
elif strategy == "cycle": | ||
self._ask_and_tell = self._ask_and_tell_based_on_cycle | ||
self._cycle = itertools.cycle(range(len(self.learners))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now the cycle will be reset every time the strategy is set dynamically. I'm not sure what the best thing to do here is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That might be the intention? We could also just put in in |
||
else: | ||
raise ValueError( | ||
'Only strategy="loss_improvements", strategy="loss", or' | ||
' strategy="npoints" is implemented.' | ||
'Only strategy="loss_improvements", strategy="loss",' | ||
' strategy="npoints", or strategy="cycle" is implemented.' | ||
) | ||
|
||
def _ask_and_tell_based_on_loss_improvements(self, n): | ||
|
@@ -173,6 +179,17 @@ def _ask_and_tell_based_on_npoints(self, n): | |
points, loss_improvements = map(list, zip(*selected)) | ||
return points, loss_improvements | ||
|
||
def _ask_and_tell_based_on_cycle(self, n): | ||
points, loss_improvements = [], [] | ||
for _ in range(n): | ||
index = next(self._cycle) | ||
point, loss_improvement = self.learners[index].ask(n=1) | ||
points.append((index, point[0])) | ||
loss_improvements.append(loss_improvement[0]) | ||
self.tell_pending((index, point[0])) | ||
|
||
return points, loss_improvements | ||
|
||
def ask(self, n, tell_pending=True): | ||
"""Chose points for learners.""" | ||
if n == 0: | ||
|
Uh oh!
There was an error while loading. Please reload this page.