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

Create Optimizer in BO Suggestion only for the first run #1057

Merged
48 changes: 25 additions & 23 deletions pkg/suggestion/v1alpha3/skopt/base_skopt_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,26 @@ class BaseSkoptService(object):
Refer to https://github.com/scikit-optimize/scikit-optimize .
"""

def __init__(self, algorithm_name="skopt-bayesian-optimization",
def __init__(self,
base_estimator="GP",
n_initial_points=10,
acq_func="gp_hedge",
acq_optimizer="auto",
random_state=None):
random_state=None,
search_space=None):
self.base_estimator = base_estimator
self.n_initial_points = n_initial_points
self.acq_func = acq_func
self.acq_optimizer = acq_optimizer
self.random_state = random_state
self.algorithm_name = algorithm_name

def getSuggestions(self, search_space, trials, request_number):
"""
Get the new suggested trials with skopt algorithm.
"""
self.search_space = search_space
self.skopt_optimizer = None
self.create_optimizer()

def create_optimizer(self):
skopt_search_space = []

for param in search_space.params:
for param in self.search_space.params:
if param.type == INTEGER:
skopt_search_space.append(skopt.space.Integer(
int(param.min), int(param.max), name=param.name))
Expand All @@ -45,21 +44,24 @@ def getSuggestions(self, search_space, trials, request_number):
skopt_search_space.append(
skopt.space.Categorical(param.list, name=param.name))

if self.algorithm_name != "bayesianoptimization":
raise Exception(
'"Failed to create the algortihm: {}'.format(self.algorithm_name))
skopt_optimizer = skopt.Optimizer(skopt_search_space,
base_estimator=self.base_estimator,
n_initial_points=self.n_initial_points,
acq_func=self.acq_func,
acq_optimizer=self.acq_optimizer,
random_state=self.random_state)
self.skopt_optimizer = skopt.Optimizer(
skopt_search_space,
base_estimator=self.base_estimator,
n_initial_points=self.n_initial_points,
acq_func=self.acq_func,
acq_optimizer=self.acq_optimizer,
random_state=self.random_state)

def getSuggestions(self, trials, request_number):
"""
Get the new suggested trials with skopt algorithm.
"""

skopt_suggested = []
loss_for_skopt = []
for trial in trials:
trial_assignment = []
for param in search_space.params:
for param in self.search_space.params:
parameter_value = None
for assignment in trial.assignments:
if assignment.name == param.name:
Expand All @@ -74,19 +76,19 @@ def getSuggestions(self, search_space, trials, request_number):
skopt_suggested.append(trial_assignment)

loss_value = float(trial.target_metric.value)
if search_space.goal == MAX_GOAL:
if self.search_space.goal == MAX_GOAL:
loss_value = -1 * loss_value
loss_for_skopt.append(loss_value)

if loss_for_skopt != [] and skopt_suggested != []:
skopt_optimizer.tell(skopt_suggested, loss_for_skopt)
self.skopt_optimizer.tell(skopt_suggested, loss_for_skopt)

return_trial_list = []

for i in range(request_number):
skopt_suggested = skopt_optimizer.ask()
skopt_suggested = self.skopt_optimizer.ask()
return_trial_list.append(
BaseSkoptService.convert(search_space, skopt_suggested))
BaseSkoptService.convert(self.search_space, skopt_suggested))
return return_trial_list

@staticmethod
Expand Down
48 changes: 29 additions & 19 deletions pkg/suggestion/v1alpha3/skopt_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,35 @@
logger = logging.getLogger("SkoptService")


class SkoptService(
api_pb2_grpc.SuggestionServicer, HealthServicer):
class SkoptService(api_pb2_grpc.SuggestionServicer, HealthServicer):

def __init__(self):
super(SkoptService, self).__init__()
self.base_service = None
self.is_first_run = True

def GetSuggestions(self, request, context):
"""
Main function to provide suggestion.
"""
name, config = OptimizerConfiguration.convertAlgorithmSpec(
algorithm_name, config = OptimizerConfiguration.convertAlgorithmSpec(
request.experiment.spec.algorithm)
base_service = BaseSkoptService(
algorithm_name=name,
base_estimator=config.base_estimator,
n_initial_points=config.n_initial_points,
acq_func=config.acq_func,
acq_optimizer=config.acq_optimizer,
random_state=config.random_state)
if algorithm_name != "bayesianoptimization":
raise Exception("Failed to create the algortihm: {}".format(algorithm_name))

search_space = HyperParameterSearchSpace.convert(request.experiment)
if self.is_first_run:
self.base_service = BaseSkoptService(
base_estimator=config.base_estimator,
n_initial_points=config.n_initial_points,
acq_func=config.acq_func,
acq_optimizer=config.acq_optimizer,
random_state=config.random_state,
search_space=search_space)
self.is_first_run = False

trials = Trial.convert(request.trials)
new_trials = base_service.getSuggestions(
search_space, trials, request.request_number)
new_trials = self.base_service.getSuggestions(trials, request.request_number)
return api_pb2.GetSuggestionsReply(
parameter_assignments=Assignment.generate(new_trials)
)
Expand All @@ -49,16 +59,16 @@ def __init__(self, base_estimator="GP",

@staticmethod
def convertAlgorithmSpec(algorithm_spec):
optmizer = OptimizerConfiguration()
optimizer = OptimizerConfiguration()
for s in algorithm_spec.algorithm_setting:
if s.name == "base_estimator":
optmizer.base_estimator = s.value
optimizer.base_estimator = s.value
elif s.name == "n_initial_points":
optmizer.n_initial_points = int(s.value)
optimizer.n_initial_points = int(s.value)
elif s.name == "acq_func":
optmizer.acq_func = s.value
optimizer.acq_func = s.value
elif s.name == "acq_optimizer":
optmizer.acq_optimizer = s.value
optimizer.acq_optimizer = s.value
elif s.name == "random_state":
optmizer.random_state = int(s.value)
return algorithm_spec.algorithm_name, optmizer
optimizer.random_state = int(s.value)
return algorithm_spec.algorithm_name, optimizer