I am using Optuna to optimize some objective functions. I would like to create my custom class that "wraps" the standard Optuna code.
As an example, this is my class(it is still a work in progress!):
class Optimizer(object):
def __init__(self, param_dict, model, train_x, valid_x, train_y, valid_y):
self.model = model
self.param_dict = param_dict
self.train_x, self.valid_x, self.train_y, self.valid_y = train_x, valid_x, train_y, valid_y
def optimization_function(self, trial):
self.dtrain = lgb.Dataset(self.train_x, label=self.train_y)
gbm = lgb.train(param, dtrain)
preds = gbm.predict(self.valid_x)
pred_labels = np.rint(preds)
accuracy = sklearn.metrics.accuracy_score(self.valid_y, pred_labels)
return accuracy
def optimize(self, direction, n_trials):
study = optuna.create_study(direction = direction)
study.optimize(self.optimization_function, n_trials = n_trials)
return study.best_trial
I am trying to wrap all the "logic" of optuna optimization in this class, instead of writing everytime some code as the following one (from docs):
import optuna
class Objective(object):
def __init__(self, min_x, max_x):
# Hold this implementation specific arguments as the fields of the class.
self.min_x = min_x
self.max_x = max_x
def __call__(self, trial):
# Calculate an objective value by using the extra arguments.
x = trial.suggest_float("x", self.min_x, self.max_x)
return (x - 2) ** 2
# Execute an optimization by using an `Objective` instance.
study = optuna.create_study()
study.optimize(Objective(-100, 100), n_trials=100)
I would like to make my code "modular" and merge everything together in a single class. My final goal is to set different "templates" of optimization function, based on the given input model in the __init__
function.
So, getting back to the main question, I would like to pass from the outside the param
dictionary. Basically I would like to be able to declare it from outside my class and pass my dictionary in the __init__
function.
However the ranges and distributions commonly used inside Optuna's codes, depends on the trial
object, so I am not able to do something like:
my_dict = {
'objective': 'binary',
'metric': 'binary_logloss',
'verbosity': -1,
'boosting_type': 'gbdt',
# HERE I HAVE A DEPENDENCY FROM trial.suggest_loguniform, I can't declare the dictionary outside the objective function
'lambda_l1': trial.suggest_loguniform('lambda_l1', 1e-8, 10.0),
'lambda_l2': trial.suggest_loguniform('lambda_l2', 1e-8, 10.0),
'num_leaves': trial.suggest_int('num_leaves', 2, 256),
'feature_fraction': trial.suggest_uniform('feature_fraction', 0.4, 1.0),
'bagging_fraction': trial.suggest_uniform('bagging_fraction', 0.4, 1.0),
'bagging_freq': trial.suggest_int('bagging_freq', 1, 7),
'min_child_samples': trial.suggest_int('min_child_samples', 5, 100),
}
my_optimizer = Optimizer(my_dict, ..., ..., ..., ......)
best_result = my_optimizer.optimize('maximize', 100)
Is there any work around or solution to pass this dictionary?